Skip to content

Commit f1021ed

Browse files
committed
Implement Debug for C-like enums with an array
1 parent 2d429f3 commit f1021ed

File tree

2 files changed

+51
-7
lines changed

2 files changed

+51
-7
lines changed

compiler/rustc_builtin_macros/src/deriving/debug.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,14 @@ fn show_fieldless_enum(
216216
substr: &Substructure<'_>,
217217
) -> BlockOrExpr {
218218
let fmt = substr.nonselflike_args[0].clone();
219+
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
220+
if let Some(name) = show_fieldless_enum_array(cx, span, def) {
221+
return BlockOrExpr::new_expr(cx.expr_call_global(
222+
span,
223+
fn_path_write_str,
224+
thin_vec![fmt, name],
225+
));
226+
}
219227
let arms = def
220228
.variants
221229
.iter()
@@ -236,6 +244,47 @@ fn show_fieldless_enum(
236244
})
237245
.collect::<ThinVec<_>>();
238246
let name = cx.expr_match(span, cx.expr_self(span), arms);
239-
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
240247
BlockOrExpr::new_expr(cx.expr_call_global(span, fn_path_write_str, thin_vec![fmt, name]))
241248
}
249+
250+
/// Specialer case for fieldless enums with no discriminants. Builds
251+
/// ```text
252+
/// impl ::core::fmt::Debug for A {
253+
/// fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
254+
/// ::core::fmt::Formatter::write_str(f, ["A", "B", "C"][*self as usize])
255+
/// }
256+
/// }
257+
/// ```
258+
fn show_fieldless_enum_array(
259+
cx: &mut ExtCtxt<'_>,
260+
span: Span,
261+
def: &EnumDef,
262+
) -> Option<ast::ptr::P<ast::Expr>> {
263+
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
264+
let has_derive_copy = cx.resolver.has_derive_copy(container_id);
265+
// FIXME(clubby789): handle repr(xx) enums too
266+
if !has_derive_copy {
267+
return None;
268+
}
269+
if def.variants.len() >= cx.sess.target.pointer_width as usize {
270+
return None;
271+
}
272+
// FIXME(clubby789): handle enums with discriminants matching their indexes
273+
let name_array = def
274+
.variants
275+
.iter()
276+
.map(|v| if v.disr_expr.is_none() { Some(cx.expr_str(span, v.ident.name)) } else { None })
277+
.collect::<Option<ThinVec<_>>>()?;
278+
let name = cx.expr(
279+
span,
280+
ast::ExprKind::Index(
281+
cx.expr_array(span, name_array),
282+
cx.expr_cast(
283+
span,
284+
cx.expr_deref(span, cx.expr_self(span)),
285+
cx.ty_path(ast::Path::from_ident(Ident::with_dummy_span(sym::usize))),
286+
),
287+
),
288+
);
289+
Some(name)
290+
}

tests/ui/deriving/deriving-all-codegen.stdout

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -989,12 +989,7 @@ impl ::core::marker::Copy for Fieldless { }
989989
#[automatically_derived]
990990
impl ::core::fmt::Debug for Fieldless {
991991
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
992-
::core::fmt::Formatter::write_str(f,
993-
match self {
994-
Fieldless::A => "A",
995-
Fieldless::B => "B",
996-
Fieldless::C => "C",
997-
})
992+
::core::fmt::Formatter::write_str(f, ["A", "B", "C"][*self as usize])
998993
}
999994
}
1000995
#[automatically_derived]

0 commit comments

Comments
 (0)