@@ -16,13 +16,14 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
16
16
use rustc_hir:: def_id:: DefId ;
17
17
use rustc_hir:: definitions:: { DefPathData , DefPathDataName , DisambiguatedDefPathData } ;
18
18
use rustc_hir:: { AsyncGeneratorKind , GeneratorKind , Mutability } ;
19
- use rustc_middle:: ty:: layout:: IntegerExt ;
19
+ use rustc_middle:: ty:: layout:: { IntegerExt , TyAndLayout } ;
20
20
use 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 } ;
22
22
use rustc_query_system:: ich:: NodeIdHashingMode ;
23
23
use rustc_target:: abi:: { Integer , TagEncoding , Variants } ;
24
24
use smallvec:: SmallVec ;
25
25
26
+ use std:: borrow:: Cow ;
26
27
use std:: fmt:: Write ;
27
28
28
29
use crate :: debuginfo:: wants_c_like_enum_debuginfo;
@@ -76,7 +77,16 @@ fn push_debuginfo_type_name<'tcx>(
76
77
let ty_and_layout = tcx. layout_of ( ParamEnv :: reveal_all ( ) . and ( t) ) . expect ( "layout error" ) ;
77
78
78
79
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
+ ) ;
80
90
} else {
81
91
push_item_name ( tcx, def. did ( ) , qualified, output) ;
82
92
push_generic_params_internal ( tcx, substs, output, visited) ;
@@ -352,40 +362,26 @@ fn push_debuginfo_type_name<'tcx>(
352
362
ty:: Closure ( def_id, substs) | ty:: Generator ( def_id, substs, ..) => {
353
363
// Name will be "{closure_env#0}<T1, T2, ...>", "{generator_env#0}<T1, T2, ...>", or
354
364
// "{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) ;
361
380
}
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) ;
385
381
}
386
382
// Type parameters from polymorphized functions.
387
383
ty:: Param ( _) => {
388
- output . push_str ( & format ! ( "{:?}" , t) ) ;
384
+ write ! ( output , "{:?}" , t) . unwrap ( ) ;
389
385
}
390
386
ty:: Error ( _)
391
387
| ty:: Infer ( _)
@@ -408,24 +404,32 @@ fn push_debuginfo_type_name<'tcx>(
408
404
// `EnumMemberDescriptionFactor::create_member_descriptions`.
409
405
fn msvc_enum_fallback < ' tcx > (
410
406
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 > > ) ,
414
409
output : & mut String ,
415
410
visited : & mut FxHashSet < Ty < ' tcx > > ,
416
411
) {
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 ;
418
414
419
415
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
+ } ;
422
426
423
427
if let Variants :: Multiple {
424
428
tag_encoding : TagEncoding :: Niche { dataful_variant, .. } ,
425
429
tag,
426
430
variants,
427
431
..
428
- } = & layout . variants
432
+ } = & ty_and_layout . variants
429
433
{
430
434
let dataful_variant_layout = & variants[ * dataful_variant] ;
431
435
@@ -439,16 +443,13 @@ fn push_debuginfo_type_name<'tcx>(
439
443
let max = dataful_discriminant_range. end ;
440
444
let max = tag. value . size ( & tcx) . truncate ( max) ;
441
445
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 {
446
449
// Uninhabited enums can't be constructed and should never need to be visualized so
447
450
// 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 ( ) ;
452
453
}
453
454
}
454
455
push_close_angle_bracket ( true , output) ;
@@ -700,6 +701,49 @@ pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, out
700
701
push_generic_params_internal ( tcx, substs, output, & mut visited) ;
701
702
}
702
703
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
+
703
747
fn push_close_angle_bracket ( cpp_like_debuginfo : bool , output : & mut String ) {
704
748
// MSVC debugger always treats `>>` as a shift, even when parsing templates,
705
749
// so add a space to avoid confusion.
0 commit comments