@@ -2,6 +2,7 @@ use crate::deriving::generic::ty::*;
22use crate :: deriving:: generic:: * ;
33use crate :: deriving:: path_std;
44
5+ use ast:: EnumDef ;
56use rustc_ast:: { self as ast, MetaItem } ;
67use rustc_expand:: base:: { Annotatable , ExtCtxt } ;
78use 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+ }
0 commit comments