@@ -2,6 +2,7 @@ use crate::deriving::generic::ty::*;
2
2
use crate :: deriving:: generic:: * ;
3
3
use crate :: deriving:: path_std;
4
4
5
+ use ast:: EnumDef ;
5
6
use rustc_ast:: { self as ast, MetaItem } ;
6
7
use rustc_expand:: base:: { Annotatable , ExtCtxt } ;
7
8
use rustc_span:: symbol:: { sym, Ident , Symbol } ;
@@ -31,7 +32,8 @@ pub fn expand_deriving_debug(
31
32
nonself_args: vec![ ( fmtr, sym:: f) ] ,
32
33
ret_ty: Path ( path_std!( fmt:: Result ) ) ,
33
34
attributes: ast:: AttrVec :: new( ) ,
34
- fieldless_variants_strategy: FieldlessVariantsStrategy :: Default ,
35
+ fieldless_variants_strategy:
36
+ FieldlessVariantsStrategy :: SpecializeIfAllVariantsFieldless ,
35
37
combine_substructure: combine_substructure( Box :: new( |a, b, c| {
36
38
show_substructure( a, b, c)
37
39
} ) ) ,
@@ -49,7 +51,8 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
49
51
let ( ident, vdata, fields) = match substr. fields {
50
52
Struct ( vdata, fields) => ( substr. type_ident , * vdata, fields) ,
51
53
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 ( ..) => {
53
56
cx. span_bug ( span, "nonsensical .fields in `#[derive(Debug)]`" )
54
57
}
55
58
} ;
@@ -174,3 +177,47 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
174
177
BlockOrExpr :: new_mixed ( stmts, Some ( expr) )
175
178
}
176
179
}
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
+ }
0 commit comments