about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_macros/src/serialize.rs47
-rw-r--r--compiler/rustc_serialize/src/serialize.rs12
2 files changed, 30 insertions, 29 deletions
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<F>(&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<const ID: usize>(&mut self) {
-        self.emit_usize(ID)
-    }
 }
 
 // Note: all the methods in this trait are infallible, which may be surprising.