Skip to content

Commit 7de205e

Browse files
committed
Emit the enum discriminant separately for the Encodable macro
1 parent 07c993e commit 7de205e

File tree

2 files changed

+30
-29
lines changed

2 files changed

+30
-29
lines changed

compiler/rustc_macros/src/serialize.rs

+30-17
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ fn decodable_body(
4242
}
4343
let ty_name = s.ast().ident.to_string();
4444
let decode_body = match s.variants() {
45+
[] => {
46+
let message = format!("`{}` has no variants to decode", ty_name);
47+
quote! {
48+
panic!(#message)
49+
}
50+
}
4551
[vi] => vi.construct(|field, _index| decode_field(field)),
4652
variants => {
4753
let match_inner: TokenStream = variants
@@ -139,6 +145,11 @@ fn encodable_body(
139145
});
140146

141147
let encode_body = match s.variants() {
148+
[] => {
149+
quote! {
150+
match *self {}
151+
}
152+
}
142153
[_] => {
143154
let encode_inner = s.each_variant(|vi| {
144155
vi.bindings()
@@ -160,6 +171,23 @@ fn encodable_body(
160171
}
161172
}
162173
_ => {
174+
let disc = {
175+
let mut variant_idx = 0usize;
176+
let encode_inner = s.each_variant(|_| {
177+
let result = quote! {
178+
#variant_idx
179+
};
180+
variant_idx += 1;
181+
result
182+
});
183+
quote! {
184+
let disc = match *self {
185+
#encode_inner
186+
};
187+
::rustc_serialize::Encoder::emit_usize(__encoder, disc);
188+
}
189+
};
190+
163191
let mut variant_idx = 0usize;
164192
let encode_inner = s.each_variant(|vi| {
165193
let encode_fields: TokenStream = vi
@@ -176,26 +204,11 @@ fn encodable_body(
176204
result
177205
})
178206
.collect();
179-
180-
let result = if !vi.bindings().is_empty() {
181-
quote! {
182-
::rustc_serialize::Encoder::emit_enum_variant(
183-
__encoder,
184-
#variant_idx,
185-
|__encoder| { #encode_fields }
186-
)
187-
}
188-
} else {
189-
quote! {
190-
::rustc_serialize::Encoder::emit_fieldless_enum_variant::<#variant_idx>(
191-
__encoder,
192-
)
193-
}
194-
};
195207
variant_idx += 1;
196-
result
208+
encode_fields
197209
});
198210
quote! {
211+
#disc
199212
match *self {
200213
#encode_inner
201214
}

compiler/rustc_serialize/src/serialize.rs

-12
Original file line numberDiff line numberDiff line change
@@ -43,25 +43,13 @@ pub trait Encoder {
4343
fn emit_str(&mut self, v: &str);
4444
fn emit_raw_bytes(&mut self, s: &[u8]);
4545

46-
// Convenience for the derive macro:
4746
fn emit_enum_variant<F>(&mut self, v_id: usize, f: F)
4847
where
4948
F: FnOnce(&mut Self),
5049
{
5150
self.emit_usize(v_id);
5251
f(self);
5352
}
54-
55-
// We put the field index in a const generic to allow the emit_usize to be
56-
// compiled into a more efficient form. In practice, the variant index is
57-
// known at compile-time, and that knowledge allows much more efficient
58-
// codegen than we'd otherwise get. LLVM isn't always able to make the
59-
// optimization that would otherwise be necessary here, likely due to the
60-
// multiple levels of inlining and const-prop that are needed.
61-
#[inline]
62-
fn emit_fieldless_enum_variant<const ID: usize>(&mut self) {
63-
self.emit_usize(ID)
64-
}
6553
}
6654

6755
// Note: all the methods in this trait are infallible, which may be surprising.

0 commit comments

Comments
 (0)