Skip to content

Commit 95a824c

Browse files
committed
Special case derive(Debug) for fieldless enums
1 parent 97cf171 commit 95a824c

File tree

2 files changed

+55
-7
lines changed

2 files changed

+55
-7
lines changed

compiler/rustc_builtin_macros/src/deriving/debug.rs

+49-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::deriving::generic::ty::*;
22
use crate::deriving::generic::*;
33
use crate::deriving::path_std;
44

5+
use ast::EnumDef;
56
use rustc_ast::{self as ast, MetaItem};
67
use rustc_expand::base::{Annotatable, ExtCtxt};
78
use rustc_span::symbol::{sym, Ident, Symbol};
@@ -31,7 +32,8 @@ pub fn expand_deriving_debug(
3132
nonself_args: vec![(fmtr, sym::f)],
3233
ret_ty: Path(path_std!(fmt::Result)),
3334
attributes: ast::AttrVec::new(),
34-
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
35+
fieldless_variants_strategy:
36+
FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless,
3537
combine_substructure: combine_substructure(Box::new(|a, b, c| {
3638
show_substructure(a, b, c)
3739
})),
@@ -49,7 +51,8 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
4951
let (ident, vdata, fields) = match substr.fields {
5052
Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
5153
EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields),
52-
AllFieldlessEnum(..) | EnumTag(..) | StaticStruct(..) | StaticEnum(..) => {
54+
AllFieldlessEnum(enum_def) => return show_fieldless_enum(cx, span, enum_def, substr),
55+
EnumTag(..) | StaticStruct(..) | StaticEnum(..) => {
5356
cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
5457
}
5558
};
@@ -174,3 +177,47 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
174177
BlockOrExpr::new_mixed(stmts, Some(expr))
175178
}
176179
}
180+
181+
/// Special case for enums with no fields. Builds:
182+
/// ```text
183+
/// impl ::core::fmt::Debug for A {
184+
/// fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
185+
/// ::core::fmt::Formatter::write_str(f,
186+
/// match self {
187+
/// A::A => "A",
188+
/// A::B() => "B",
189+
/// A::C {} => "C",
190+
/// })
191+
/// }
192+
/// }
193+
/// ```
194+
fn show_fieldless_enum(
195+
cx: &mut ExtCtxt<'_>,
196+
span: Span,
197+
def: &EnumDef,
198+
substr: &Substructure<'_>,
199+
) -> BlockOrExpr {
200+
let fmt = substr.nonselflike_args[0].clone();
201+
let arms = def
202+
.variants
203+
.iter()
204+
.map(|v| {
205+
let variant_path = cx.path(span, vec![substr.type_ident, v.ident]);
206+
let pat = match &v.data {
207+
ast::VariantData::Tuple(fields, _) => {
208+
debug_assert!(fields.is_empty());
209+
cx.pat_tuple_struct(span, variant_path, vec![])
210+
}
211+
ast::VariantData::Struct(fields, _) => {
212+
debug_assert!(fields.is_empty());
213+
cx.pat_struct(span, variant_path, vec![])
214+
}
215+
ast::VariantData::Unit(_) => cx.pat_path(span, variant_path),
216+
};
217+
cx.arm(span, pat, cx.expr_str(span, v.ident.name))
218+
})
219+
.collect::<Vec<_>>();
220+
let name = cx.expr_match(span, cx.expr_self(span), arms);
221+
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
222+
BlockOrExpr::new_expr(cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]))
223+
}

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

+6-5
Original file line numberDiff line numberDiff line change
@@ -731,11 +731,12 @@ impl ::core::marker::Copy for Fieldless { }
731731
#[automatically_derived]
732732
impl ::core::fmt::Debug for Fieldless {
733733
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
734-
match self {
735-
Fieldless::A => ::core::fmt::Formatter::write_str(f, "A"),
736-
Fieldless::B => ::core::fmt::Formatter::write_str(f, "B"),
737-
Fieldless::C => ::core::fmt::Formatter::write_str(f, "C"),
738-
}
734+
::core::fmt::Formatter::write_str(f,
735+
match self {
736+
Fieldless::A => "A",
737+
Fieldless::B => "B",
738+
Fieldless::C => "C",
739+
})
739740
}
740741
}
741742
#[automatically_derived]

0 commit comments

Comments
 (0)