@@ -85,25 +85,14 @@ pub fn push_debuginfo_type_name<'tcx>(
8585
8686 for component_type in component_types {
8787 push_debuginfo_type_name ( tcx, component_type. expect_ty ( ) , true , output, visited) ;
88- output. push ( ',' ) ;
89-
90- // Natvis does not always like having spaces between parts of the type name
91- // and this causes issues when we need to write a typename in natvis, for example
92- // as part of a cast like the `HashMap` visualizer does.
93- if !cpp_like_names {
94- output. push ( ' ' ) ;
95- }
88+ push_arg_separator ( cpp_like_names, output) ;
9689 }
9790 if !component_types. is_empty ( ) {
98- output. pop ( ) ;
99-
100- if !cpp_like_names {
101- output. pop ( ) ;
102- }
91+ pop_arg_separator ( output) ;
10392 }
10493
10594 if cpp_like_names {
106- push_close_angle_bracket ( tcx , output) ;
95+ push_close_angle_bracket ( cpp_like_names , output) ;
10796 } else {
10897 output. push ( ')' ) ;
10998 }
@@ -125,7 +114,7 @@ pub fn push_debuginfo_type_name<'tcx>(
125114 push_debuginfo_type_name ( tcx, inner_type, qualified, output, visited) ;
126115
127116 if cpp_like_names {
128- push_close_angle_bracket ( tcx , output) ;
117+ push_close_angle_bracket ( cpp_like_names , output) ;
129118 }
130119 }
131120 ty:: Ref ( _, inner_type, mutbl) => {
@@ -151,7 +140,7 @@ pub fn push_debuginfo_type_name<'tcx>(
151140 push_debuginfo_type_name ( tcx, inner_type, qualified, output, visited) ;
152141
153142 if cpp_like_names && !is_slice_or_str {
154- push_close_angle_bracket ( tcx , output) ;
143+ push_close_angle_bracket ( cpp_like_names , output) ;
155144 }
156145 }
157146 ty:: Array ( inner_type, len) => {
@@ -183,7 +172,7 @@ pub fn push_debuginfo_type_name<'tcx>(
183172 push_debuginfo_type_name ( tcx, inner_type, true , output, visited) ;
184173
185174 if cpp_like_names {
186- push_close_angle_bracket ( tcx , output) ;
175+ push_close_angle_bracket ( cpp_like_names , output) ;
187176 } else {
188177 output. push ( ']' ) ;
189178 }
@@ -196,7 +185,7 @@ pub fn push_debuginfo_type_name<'tcx>(
196185 false
197186 } else {
198187 if trait_data. len ( ) > 1 && auto_traits. len ( ) != 0 {
199- // We need enclosing parens
188+ // We need enclosing parens because there is more than one trait
200189 output. push_str ( "(dyn " ) ;
201190 true
202191 } else {
@@ -209,7 +198,8 @@ pub fn push_debuginfo_type_name<'tcx>(
209198 let principal =
210199 tcx. normalize_erasing_late_bound_regions ( ty:: ParamEnv :: reveal_all ( ) , principal) ;
211200 push_item_name ( tcx, principal. def_id , qualified, output) ;
212- push_generic_params_internal ( tcx, principal. substs , output, visited) ;
201+ let principal_has_generic_params =
202+ push_generic_params_internal ( tcx, principal. substs , output, visited) ;
213203
214204 let projection_bounds: SmallVec < [ _ ; 4 ] > = trait_data
215205 . projection_bounds ( )
@@ -220,25 +210,29 @@ pub fn push_debuginfo_type_name<'tcx>(
220210 . collect ( ) ;
221211
222212 if projection_bounds. len ( ) != 0 {
223- pop_close_angle_bracket ( output) ;
213+ if principal_has_generic_params {
214+ // push_generic_params_internal() above added a `>` but we actually
215+ // want to add more items to that list, so remove that again.
216+ pop_close_angle_bracket ( output) ;
217+ }
224218
225219 for ( item_def_id, ty) in projection_bounds {
226- output . push_str ( ", " ) ;
220+ push_arg_separator ( cpp_like_names , output ) ;
227221
228222 if cpp_like_names {
229223 output. push_str ( "assoc$<" ) ;
230224 push_item_name ( tcx, item_def_id, false , output) ;
231- output . push_str ( ", " ) ;
225+ push_arg_separator ( cpp_like_names , output ) ;
232226 push_debuginfo_type_name ( tcx, ty, true , output, visited) ;
233- push_close_angle_bracket ( tcx , output) ;
227+ push_close_angle_bracket ( cpp_like_names , output) ;
234228 } else {
235229 push_item_name ( tcx, item_def_id, false , output) ;
236230 output. push ( '=' ) ;
237231 push_debuginfo_type_name ( tcx, ty, true , output, visited) ;
238232 }
239233 }
240234
241- push_close_angle_bracket ( tcx , output) ;
235+ push_close_angle_bracket ( cpp_like_names , output) ;
242236 }
243237
244238 if auto_traits. len ( ) != 0 {
@@ -262,11 +256,11 @@ pub fn push_debuginfo_type_name<'tcx>(
262256 push_auto_trait_separator ( cpp_like_names, output) ;
263257 }
264258
265- pop_auto_trait_separator ( cpp_like_names , output) ;
259+ pop_auto_trait_separator ( output) ;
266260 }
267261
268262 if cpp_like_names {
269- push_close_angle_bracket ( tcx , output) ;
263+ push_close_angle_bracket ( cpp_like_names , output) ;
270264 } else if has_enclosing_parens {
271265 output. push ( ')' ) ;
272266 }
@@ -320,10 +314,9 @@ pub fn push_debuginfo_type_name<'tcx>(
320314 if !sig. inputs ( ) . is_empty ( ) {
321315 for & parameter_type in sig. inputs ( ) {
322316 push_debuginfo_type_name ( tcx, parameter_type, true , output, visited) ;
323- output . push_str ( ", " ) ;
317+ push_arg_separator ( cpp_like_names , output ) ;
324318 }
325- output. pop ( ) ;
326- output. pop ( ) ;
319+ pop_arg_separator ( output) ;
327320 }
328321
329322 if sig. c_variadic {
@@ -429,21 +422,25 @@ pub fn push_debuginfo_type_name<'tcx>(
429422 output. push_str ( & format ! ( ", {}" , variant) ) ;
430423 }
431424 }
432- push_close_angle_bracket ( tcx , output) ;
425+ push_close_angle_bracket ( true , output) ;
433426 }
434427
435- fn auto_trait_separator ( cpp_like_names : bool ) -> & ' static str {
436- if cpp_like_names { ", " } else { " + " }
437- }
428+ const NON_CPP_AUTO_TRAIT_SEPARATOR : & str = " + " ;
438429
439430 fn push_auto_trait_separator ( cpp_like_names : bool , output : & mut String ) {
440- output. push_str ( auto_trait_separator ( cpp_like_names) ) ;
431+ if cpp_like_names {
432+ push_arg_separator ( cpp_like_names, output) ;
433+ } else {
434+ output. push_str ( NON_CPP_AUTO_TRAIT_SEPARATOR ) ;
435+ }
441436 }
442437
443- fn pop_auto_trait_separator ( cpp_like_names : bool , output : & mut String ) {
444- let sep = auto_trait_separator ( cpp_like_names) ;
445- assert ! ( output. ends_with( sep) ) ;
446- output. truncate ( output. len ( ) - sep. len ( ) ) ;
438+ fn pop_auto_trait_separator ( output : & mut String ) {
439+ if output. ends_with ( NON_CPP_AUTO_TRAIT_SEPARATOR ) {
440+ output. truncate ( output. len ( ) - NON_CPP_AUTO_TRAIT_SEPARATOR . len ( ) ) ;
441+ } else {
442+ pop_arg_separator ( output) ;
443+ }
447444 }
448445}
449446
@@ -504,13 +501,15 @@ fn push_generic_params_internal<'tcx>(
504501 substs : SubstsRef < ' tcx > ,
505502 output : & mut String ,
506503 visited : & mut FxHashSet < Ty < ' tcx > > ,
507- ) {
504+ ) -> bool {
508505 if substs. non_erasable_generics ( ) . next ( ) . is_none ( ) {
509- return ;
506+ return false ;
510507 }
511508
512509 debug_assert_eq ! ( substs, tcx. normalize_erasing_regions( ty:: ParamEnv :: reveal_all( ) , substs) ) ;
513510
511+ let cpp_like_names = cpp_like_names ( tcx) ;
512+
514513 output. push ( '<' ) ;
515514
516515 for type_parameter in substs. non_erasable_generics ( ) {
@@ -524,13 +523,12 @@ fn push_generic_params_internal<'tcx>(
524523 other => bug ! ( "Unexpected non-erasable generic: {:?}" , other) ,
525524 }
526525
527- output . push_str ( ", " ) ;
526+ push_arg_separator ( cpp_like_names , output ) ;
528527 }
528+ pop_arg_separator ( output) ;
529+ push_close_angle_bracket ( cpp_like_names, output) ;
529530
530- output. pop ( ) ;
531- output. pop ( ) ;
532-
533- push_close_angle_bracket ( tcx, output) ;
531+ true
534532}
535533
536534fn push_const_param < ' tcx > ( tcx : TyCtxt < ' tcx > , ct : & ' tcx ty:: Const < ' tcx > , output : & mut String ) {
@@ -583,24 +581,45 @@ pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, out
583581 push_generic_params_internal ( tcx, substs, output, & mut visited) ;
584582}
585583
586- fn push_close_angle_bracket < ' tcx > ( tcx : TyCtxt < ' tcx > , output : & mut String ) {
584+ fn push_close_angle_bracket ( cpp_like_names : bool , output : & mut String ) {
587585 // MSVC debugger always treats `>>` as a shift, even when parsing templates,
588586 // so add a space to avoid confusion.
589- if cpp_like_names ( tcx ) && output. ends_with ( '>' ) {
587+ if cpp_like_names && output. ends_with ( '>' ) {
590588 output. push ( ' ' )
591589 } ;
592590
593591 output. push ( '>' ) ;
594592}
595593
596594fn pop_close_angle_bracket ( output : & mut String ) {
597- assert ! ( output. ends_with( '>' ) ) ;
595+ assert ! ( output. ends_with( '>' ) , "'output' does not end with '>': {}" , output ) ;
598596 output. pop ( ) ;
599597 if output. ends_with ( ' ' ) {
600598 output. pop ( ) ;
601599 }
602600}
603601
602+ fn push_arg_separator ( cpp_like_names : bool , output : & mut String ) {
603+ // Natvis does not always like having spaces between parts of the type name
604+ // and this causes issues when we need to write a typename in natvis, for example
605+ // as part of a cast like the `HashMap` visualizer does.
606+ if cpp_like_names {
607+ output. push ( ',' ) ;
608+ } else {
609+ output. push_str ( ", " ) ;
610+ } ;
611+ }
612+
613+ fn pop_arg_separator ( output : & mut String ) {
614+ if output. ends_with ( ' ' ) {
615+ output. pop ( ) ;
616+ }
617+
618+ assert ! ( output. ends_with( ',' ) ) ;
619+
620+ output. pop ( ) ;
621+ }
622+
604623fn cpp_like_names ( tcx : TyCtxt < ' _ > ) -> bool {
605624 tcx. sess . target . is_like_msvc
606625}
0 commit comments