diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index 82e6972d027..8d017d149f6 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -42,6 +42,12 @@ fn decodable_body( } let ty_name = s.ast().ident.to_string(); let decode_body = match s.variants() { + [] => { + let message = format!("`{}` has no variants to decode", ty_name); + quote! { + panic!(#message) + } + } [vi] => vi.construct(|field, _index| decode_field(field)), variants => { let match_inner: TokenStream = variants @@ -139,6 +145,11 @@ fn encodable_body( }); let encode_body = match s.variants() { + [] => { + quote! { + match *self {} + } + } [_] => { let encode_inner = s.each_variant(|vi| { vi.bindings() @@ -160,6 +171,23 @@ fn encodable_body( } } _ => { + let disc = { + let mut variant_idx = 0usize; + let encode_inner = s.each_variant(|_| { + let result = quote! { + #variant_idx + }; + variant_idx += 1; + result + }); + quote! { + let disc = match *self { + #encode_inner + }; + ::rustc_serialize::Encoder::emit_usize(__encoder, disc); + } + }; + let mut variant_idx = 0usize; let encode_inner = s.each_variant(|vi| { let encode_fields: TokenStream = vi @@ -176,26 +204,11 @@ fn encodable_body( result }) .collect(); - - let result = if !vi.bindings().is_empty() { - quote! { - ::rustc_serialize::Encoder::emit_enum_variant( - __encoder, - #variant_idx, - |__encoder| { #encode_fields } - ) - } - } else { - quote! { - ::rustc_serialize::Encoder::emit_fieldless_enum_variant::<#variant_idx>( - __encoder, - ) - } - }; variant_idx += 1; - result + encode_fields }); quote! { + #disc match *self { #encode_inner } diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 377c364961b..567fe06109b 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -43,7 +43,6 @@ pub trait Encoder { fn emit_str(&mut self, v: &str); fn emit_raw_bytes(&mut self, s: &[u8]); - // Convenience for the derive macro: fn emit_enum_variant(&mut self, v_id: usize, f: F) where F: FnOnce(&mut Self), @@ -51,17 +50,6 @@ pub trait Encoder { self.emit_usize(v_id); f(self); } - - // We put the field index in a const generic to allow the emit_usize to be - // compiled into a more efficient form. In practice, the variant index is - // known at compile-time, and that knowledge allows much more efficient - // codegen than we'd otherwise get. LLVM isn't always able to make the - // optimization that would otherwise be necessary here, likely due to the - // multiple levels of inlining and const-prop that are needed. - #[inline] - fn emit_fieldless_enum_variant(&mut self) { - self.emit_usize(ID) - } } // Note: all the methods in this trait are infallible, which may be surprising.