Skip to content

Commit 4d76b33

Browse files
committed
Use a lookup table in #[derive(Debug)] for field-less enums
1 parent b6dd153 commit 4d76b33

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

Diff for: compiler/rustc_builtin_macros/src/deriving/debug.rs

+19-10
Original file line numberDiff line numberDiff line change
@@ -197,15 +197,18 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
197197
}
198198

199199
/// Special case for enums with no fields. Builds:
200+
///
200201
/// ```text
201-
/// impl ::core::fmt::Debug for A {
202+
/// impl ::core::fmt::Debug for Fieldless {
202203
/// fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
203-
/// ::core::fmt::Formatter::write_str(f,
204-
/// match self {
205-
/// A::A => "A",
206-
/// A::B() => "B",
207-
/// A::C {} => "C",
208-
/// })
204+
/// ::core::fmt::Formatter::write_str(
205+
/// f,
206+
/// const { ["A", "B", "C"] }[match self {
207+
/// Fieldless::A => 0usize,
208+
/// Fieldless::B => 1usize,
209+
/// Fieldless::C => 2usize,
210+
/// }],
211+
/// )
209212
/// }
210213
/// }
211214
/// ```
@@ -216,10 +219,14 @@ fn show_fieldless_enum(
216219
substr: &Substructure<'_>,
217220
) -> BlockOrExpr {
218221
let fmt = substr.nonselflike_args[0].clone();
222+
223+
let strs = def.variants.iter().map(|v| cx.expr_str(span, v.ident.name)).collect();
224+
let array = cx.expr_const_block(span, cx.block_expr(cx.expr_array(span, strs)));
219225
let arms = def
220226
.variants
221227
.iter()
222-
.map(|v| {
228+
.enumerate()
229+
.map(|(i, v)| {
223230
let variant_path = cx.path(span, vec![substr.type_ident, v.ident]);
224231
let pat = match &v.data {
225232
ast::VariantData::Tuple(fields, _) => {
@@ -232,10 +239,12 @@ fn show_fieldless_enum(
232239
}
233240
ast::VariantData::Unit(_) => cx.pat_path(span, variant_path),
234241
};
235-
cx.arm(span, pat, cx.expr_str(span, v.ident.name))
242+
cx.arm(span, pat, cx.expr_usize(span, i))
236243
})
237244
.collect::<ThinVec<_>>();
238-
let name = cx.expr_match(span, cx.expr_self(span), arms);
245+
let match_expr = cx.expr_match(span, cx.expr_self(span), arms);
246+
let name = cx.expr_index(span, array, match_expr);
247+
239248
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
240249
BlockOrExpr::new_expr(cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, name]))
241250
}

Diff for: compiler/rustc_expand/src/build.rs

+19
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ impl<'a> ExtCtxt<'a> {
250250
pub fn expr_ident(&self, span: Span, id: Ident) -> P<ast::Expr> {
251251
self.expr_path(self.path_ident(span, id))
252252
}
253+
253254
pub fn expr_self(&self, span: Span) -> P<ast::Expr> {
254255
self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower))
255256
}
@@ -276,6 +277,10 @@ impl<'a> ExtCtxt<'a> {
276277
self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e))
277278
}
278279

280+
pub fn expr_index(&self, span: Span, val: P<ast::Expr>, index: P<ast::Expr>) -> P<ast::Expr> {
281+
self.expr(span, ast::ExprKind::Index(val, index))
282+
}
283+
279284
pub fn expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
280285
self.expr(sp, ast::ExprKind::Paren(e))
281286
}
@@ -288,6 +293,7 @@ impl<'a> ExtCtxt<'a> {
288293
) -> P<ast::Expr> {
289294
self.expr(span, ast::ExprKind::Call(expr, args))
290295
}
296+
291297
pub fn expr_call_ident(
292298
&self,
293299
span: Span,
@@ -296,6 +302,7 @@ impl<'a> ExtCtxt<'a> {
296302
) -> P<ast::Expr> {
297303
self.expr(span, ast::ExprKind::Call(self.expr_ident(span, id), args))
298304
}
305+
299306
pub fn expr_call_global(
300307
&self,
301308
sp: Span,
@@ -305,9 +312,19 @@ impl<'a> ExtCtxt<'a> {
305312
let pathexpr = self.expr_path(self.path_global(sp, fn_path));
306313
self.expr_call(sp, pathexpr, args)
307314
}
315+
308316
pub fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
309317
self.expr(b.span, ast::ExprKind::Block(b, None))
310318
}
319+
320+
pub fn expr_const(&self, span: Span, kind: ast::ExprKind) -> P<ast::Expr> {
321+
self.expr(span, ast::ExprKind::ConstBlock(self.anon_const(span, kind)))
322+
}
323+
324+
pub fn expr_const_block(&self, span: Span, b: P<ast::Block>) -> P<ast::Expr> {
325+
self.expr_const(span, ast::ExprKind::Block(b, None))
326+
}
327+
311328
pub fn field_imm(&self, span: Span, ident: Ident, e: P<ast::Expr>) -> ast::ExprField {
312329
ast::ExprField {
313330
ident: ident.with_span_pos(span),
@@ -319,6 +336,7 @@ impl<'a> ExtCtxt<'a> {
319336
is_placeholder: false,
320337
}
321338
}
339+
322340
pub fn expr_struct(
323341
&self,
324342
span: Span,
@@ -335,6 +353,7 @@ impl<'a> ExtCtxt<'a> {
335353
})),
336354
)
337355
}
356+
338357
pub fn expr_struct_ident(
339358
&self,
340359
span: Span,

Diff for: tests/ui/deriving/deriving-all-codegen.stdout

+7-5
Original file line numberDiff line numberDiff line change
@@ -997,11 +997,13 @@ impl ::core::marker::Copy for Fieldless { }
997997
impl ::core::fmt::Debug for Fieldless {
998998
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
999999
::core::fmt::Formatter::write_str(f,
1000-
match self {
1001-
Fieldless::A => "A",
1002-
Fieldless::B => "B",
1003-
Fieldless::C => "C",
1004-
})
1000+
const {
1001+
["A", "B", "C"]
1002+
}[match self {
1003+
Fieldless::A => 0usize,
1004+
Fieldless::B => 1usize,
1005+
Fieldless::C => 2usize,
1006+
}])
10051007
}
10061008
}
10071009
#[automatically_derived]

0 commit comments

Comments
 (0)