@@ -16,13 +16,14 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1616use rustc_hir:: def_id:: DefId ;
1717use rustc_hir:: definitions:: { DefPathData , DefPathDataName , DisambiguatedDefPathData } ;
1818use rustc_hir:: { AsyncGeneratorKind , GeneratorKind , Mutability } ;
19- use rustc_middle:: ty:: layout:: IntegerExt ;
19+ use rustc_middle:: ty:: layout:: { IntegerExt , TyAndLayout } ;
2020use rustc_middle:: ty:: subst:: { GenericArgKind , SubstsRef } ;
21- use rustc_middle:: ty:: { self , AdtDef , ExistentialProjection , ParamEnv , Ty , TyCtxt } ;
21+ use rustc_middle:: ty:: { self , ExistentialProjection , GeneratorSubsts , ParamEnv , Ty , TyCtxt } ;
2222use rustc_query_system:: ich:: NodeIdHashingMode ;
2323use rustc_target:: abi:: { Integer , TagEncoding , Variants } ;
2424use smallvec:: SmallVec ;
2525
26+ use std:: borrow:: Cow ;
2627use std:: fmt:: Write ;
2728
2829use crate :: debuginfo:: wants_c_like_enum_debuginfo;
@@ -76,7 +77,16 @@ fn push_debuginfo_type_name<'tcx>(
7677 let ty_and_layout = tcx. layout_of ( ParamEnv :: reveal_all ( ) . and ( t) ) . expect ( "layout error" ) ;
7778
7879 if def. is_enum ( ) && cpp_like_debuginfo && !wants_c_like_enum_debuginfo ( ty_and_layout) {
79- msvc_enum_fallback ( tcx, t, def, substs, output, visited) ;
80+ msvc_enum_fallback (
81+ tcx,
82+ ty_and_layout,
83+ & |output, visited| {
84+ push_item_name ( tcx, def. did ( ) , true , output) ;
85+ push_generic_params_internal ( tcx, substs, output, visited) ;
86+ } ,
87+ output,
88+ visited,
89+ ) ;
8090 } else {
8191 push_item_name ( tcx, def. did ( ) , qualified, output) ;
8292 push_generic_params_internal ( tcx, substs, output, visited) ;
@@ -352,40 +362,26 @@ fn push_debuginfo_type_name<'tcx>(
352362 ty:: Closure ( def_id, substs) | ty:: Generator ( def_id, substs, ..) => {
353363 // Name will be "{closure_env#0}<T1, T2, ...>", "{generator_env#0}<T1, T2, ...>", or
354364 // "{async_fn_env#0}<T1, T2, ...>", etc.
355- let def_key = tcx. def_key ( def_id) ;
356-
357- if qualified {
358- let parent_def_id = DefId { index : def_key. parent . unwrap ( ) , ..def_id } ;
359- push_item_name ( tcx, parent_def_id, true , output) ;
360- output. push_str ( "::" ) ;
365+ // In the case of cpp-like debuginfo, the name additionally gets wrapped inside of
366+ // an artificial `enum$<>` type, as defined in msvc_enum_fallback().
367+ if cpp_like_debuginfo && matches ! ( t. kind( ) , ty:: Generator ( ..) ) {
368+ let ty_and_layout = tcx. layout_of ( ParamEnv :: reveal_all ( ) . and ( t) ) . unwrap ( ) ;
369+ msvc_enum_fallback (
370+ tcx,
371+ ty_and_layout,
372+ & |output, visited| {
373+ push_closure_or_generator_name ( tcx, def_id, substs, true , output, visited) ;
374+ } ,
375+ output,
376+ visited,
377+ ) ;
378+ } else {
379+ push_closure_or_generator_name ( tcx, def_id, substs, qualified, output, visited) ;
361380 }
362-
363- let mut label = String :: with_capacity ( 20 ) ;
364- write ! ( & mut label, "{}_env" , generator_kind_label( tcx. generator_kind( def_id) ) ) . unwrap ( ) ;
365-
366- push_disambiguated_special_name (
367- & label,
368- def_key. disambiguated_data . disambiguator ,
369- cpp_like_debuginfo,
370- output,
371- ) ;
372-
373- // We also need to add the generic arguments of the async fn/generator or
374- // the enclosing function (for closures or async blocks), so that we end
375- // up with a unique name for every instantiation.
376-
377- // Find the generics of the enclosing function, as defined in the source code.
378- let enclosing_fn_def_id = tcx. typeck_root_def_id ( def_id) ;
379- let generics = tcx. generics_of ( enclosing_fn_def_id) ;
380-
381- // Truncate the substs to the length of the above generics. This will cut off
382- // anything closure- or generator-specific.
383- let substs = substs. truncate_to ( tcx, generics) ;
384- push_generic_params_internal ( tcx, substs, output, visited) ;
385381 }
386382 // Type parameters from polymorphized functions.
387383 ty:: Param ( _) => {
388- output . push_str ( & format ! ( "{:?}" , t) ) ;
384+ write ! ( output , "{:?}" , t) . unwrap ( ) ;
389385 }
390386 ty:: Error ( _)
391387 | ty:: Infer ( _)
@@ -408,24 +404,32 @@ fn push_debuginfo_type_name<'tcx>(
408404 // `EnumMemberDescriptionFactor::create_member_descriptions`.
409405 fn msvc_enum_fallback < ' tcx > (
410406 tcx : TyCtxt < ' tcx > ,
411- ty : Ty < ' tcx > ,
412- def : AdtDef < ' tcx > ,
413- substs : SubstsRef < ' tcx > ,
407+ ty_and_layout : TyAndLayout < ' tcx > ,
408+ push_inner : & dyn Fn ( /*output*/ & mut String , /*visited*/ & mut FxHashSet < Ty < ' tcx > > ) ,
414409 output : & mut String ,
415410 visited : & mut FxHashSet < Ty < ' tcx > > ,
416411 ) {
417- let layout = tcx. layout_of ( tcx. param_env ( def. did ( ) ) . and ( ty) ) . expect ( "layout error" ) ;
412+ debug_assert ! ( !wants_c_like_enum_debuginfo( ty_and_layout) ) ;
413+ let ty = ty_and_layout. ty ;
418414
419415 output. push_str ( "enum$<" ) ;
420- push_item_name ( tcx, def. did ( ) , true , output) ;
421- push_generic_params_internal ( tcx, substs, output, visited) ;
416+ push_inner ( output, visited) ;
417+
418+ let variant_name = |variant_index| match ty. kind ( ) {
419+ ty:: Adt ( adt_def, _) => {
420+ debug_assert ! ( adt_def. is_enum( ) ) ;
421+ Cow :: from ( adt_def. variant ( variant_index) . name . as_str ( ) )
422+ }
423+ ty:: Generator ( ..) => GeneratorSubsts :: variant_name ( variant_index) ,
424+ _ => unreachable ! ( ) ,
425+ } ;
422426
423427 if let Variants :: Multiple {
424428 tag_encoding : TagEncoding :: Niche { dataful_variant, .. } ,
425429 tag,
426430 variants,
427431 ..
428- } = & layout . variants
432+ } = & ty_and_layout . variants
429433 {
430434 let dataful_variant_layout = & variants[ * dataful_variant] ;
431435
@@ -439,16 +443,13 @@ fn push_debuginfo_type_name<'tcx>(
439443 let max = dataful_discriminant_range. end ;
440444 let max = tag. value . size ( & tcx) . truncate ( max) ;
441445
442- let dataful_variant_name = def. variant ( * dataful_variant) . name . as_str ( ) ;
443-
444- output. push_str ( & format ! ( ", {}, {}, {}" , min, max, dataful_variant_name) ) ;
445- } else if let Variants :: Single { index : variant_idx } = & layout. variants {
446+ let dataful_variant_name = variant_name ( * dataful_variant) ;
447+ write ! ( output, ", {}, {}, {}" , min, max, dataful_variant_name) . unwrap ( ) ;
448+ } else if let Variants :: Single { index : variant_idx } = & ty_and_layout. variants {
446449 // Uninhabited enums can't be constructed and should never need to be visualized so
447450 // skip this step for them.
448- if def. variants ( ) . len ( ) != 0 {
449- let variant = def. variant ( * variant_idx) . name . as_str ( ) ;
450-
451- output. push_str ( & format ! ( ", {}" , variant) ) ;
451+ if !ty_and_layout. abi . is_uninhabited ( ) {
452+ write ! ( output, ", {}" , variant_name( * variant_idx) ) . unwrap ( ) ;
452453 }
453454 }
454455 push_close_angle_bracket ( true , output) ;
@@ -700,6 +701,49 @@ pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, out
700701 push_generic_params_internal ( tcx, substs, output, & mut visited) ;
701702}
702703
704+ fn push_closure_or_generator_name < ' tcx > (
705+ tcx : TyCtxt < ' tcx > ,
706+ def_id : DefId ,
707+ substs : SubstsRef < ' tcx > ,
708+ qualified : bool ,
709+ output : & mut String ,
710+ visited : & mut FxHashSet < Ty < ' tcx > > ,
711+ ) {
712+ // Name will be "{closure_env#0}<T1, T2, ...>", "{generator_env#0}<T1, T2, ...>", or
713+ // "{async_fn_env#0}<T1, T2, ...>", etc.
714+ let def_key = tcx. def_key ( def_id) ;
715+ let generator_kind = tcx. generator_kind ( def_id) ;
716+
717+ if qualified {
718+ let parent_def_id = DefId { index : def_key. parent . unwrap ( ) , ..def_id } ;
719+ push_item_name ( tcx, parent_def_id, true , output) ;
720+ output. push_str ( "::" ) ;
721+ }
722+
723+ let mut label = String :: with_capacity ( 20 ) ;
724+ write ! ( & mut label, "{}_env" , generator_kind_label( generator_kind) ) . unwrap ( ) ;
725+
726+ push_disambiguated_special_name (
727+ & label,
728+ def_key. disambiguated_data . disambiguator ,
729+ cpp_like_debuginfo ( tcx) ,
730+ output,
731+ ) ;
732+
733+ // We also need to add the generic arguments of the async fn/generator or
734+ // the enclosing function (for closures or async blocks), so that we end
735+ // up with a unique name for every instantiation.
736+
737+ // Find the generics of the enclosing function, as defined in the source code.
738+ let enclosing_fn_def_id = tcx. typeck_root_def_id ( def_id) ;
739+ let generics = tcx. generics_of ( enclosing_fn_def_id) ;
740+
741+ // Truncate the substs to the length of the above generics. This will cut off
742+ // anything closure- or generator-specific.
743+ let substs = substs. truncate_to ( tcx, generics) ;
744+ push_generic_params_internal ( tcx, substs, output, visited) ;
745+ }
746+
703747fn push_close_angle_bracket ( cpp_like_debuginfo : bool , output : & mut String ) {
704748 // MSVC debugger always treats `>>` as a shift, even when parsing templates,
705749 // so add a space to avoid confusion.
0 commit comments