@@ -85,25 +85,14 @@ pub fn push_debuginfo_type_name<'tcx>(
85
85
86
86
for component_type in component_types {
87
87
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) ;
96
89
}
97
90
if !component_types. is_empty ( ) {
98
- output. pop ( ) ;
99
-
100
- if !cpp_like_names {
101
- output. pop ( ) ;
102
- }
91
+ pop_arg_separator ( output) ;
103
92
}
104
93
105
94
if cpp_like_names {
106
- push_close_angle_bracket ( tcx , output) ;
95
+ push_close_angle_bracket ( cpp_like_names , output) ;
107
96
} else {
108
97
output. push ( ')' ) ;
109
98
}
@@ -125,7 +114,7 @@ pub fn push_debuginfo_type_name<'tcx>(
125
114
push_debuginfo_type_name ( tcx, inner_type, qualified, output, visited) ;
126
115
127
116
if cpp_like_names {
128
- push_close_angle_bracket ( tcx , output) ;
117
+ push_close_angle_bracket ( cpp_like_names , output) ;
129
118
}
130
119
}
131
120
ty:: Ref ( _, inner_type, mutbl) => {
@@ -151,7 +140,7 @@ pub fn push_debuginfo_type_name<'tcx>(
151
140
push_debuginfo_type_name ( tcx, inner_type, qualified, output, visited) ;
152
141
153
142
if cpp_like_names && !is_slice_or_str {
154
- push_close_angle_bracket ( tcx , output) ;
143
+ push_close_angle_bracket ( cpp_like_names , output) ;
155
144
}
156
145
}
157
146
ty:: Array ( inner_type, len) => {
@@ -183,7 +172,7 @@ pub fn push_debuginfo_type_name<'tcx>(
183
172
push_debuginfo_type_name ( tcx, inner_type, true , output, visited) ;
184
173
185
174
if cpp_like_names {
186
- push_close_angle_bracket ( tcx , output) ;
175
+ push_close_angle_bracket ( cpp_like_names , output) ;
187
176
} else {
188
177
output. push ( ']' ) ;
189
178
}
@@ -196,7 +185,7 @@ pub fn push_debuginfo_type_name<'tcx>(
196
185
false
197
186
} else {
198
187
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
200
189
output. push_str ( "(dyn " ) ;
201
190
true
202
191
} else {
@@ -209,7 +198,8 @@ pub fn push_debuginfo_type_name<'tcx>(
209
198
let principal =
210
199
tcx. normalize_erasing_late_bound_regions ( ty:: ParamEnv :: reveal_all ( ) , principal) ;
211
200
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) ;
213
203
214
204
let projection_bounds: SmallVec < [ _ ; 4 ] > = trait_data
215
205
. projection_bounds ( )
@@ -220,25 +210,29 @@ pub fn push_debuginfo_type_name<'tcx>(
220
210
. collect ( ) ;
221
211
222
212
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
+ }
224
218
225
219
for ( item_def_id, ty) in projection_bounds {
226
- output . push_str ( ", " ) ;
220
+ push_arg_separator ( cpp_like_names , output ) ;
227
221
228
222
if cpp_like_names {
229
223
output. push_str ( "assoc$<" ) ;
230
224
push_item_name ( tcx, item_def_id, false , output) ;
231
- output . push_str ( ", " ) ;
225
+ push_arg_separator ( cpp_like_names , output ) ;
232
226
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) ;
234
228
} else {
235
229
push_item_name ( tcx, item_def_id, false , output) ;
236
230
output. push ( '=' ) ;
237
231
push_debuginfo_type_name ( tcx, ty, true , output, visited) ;
238
232
}
239
233
}
240
234
241
- push_close_angle_bracket ( tcx , output) ;
235
+ push_close_angle_bracket ( cpp_like_names , output) ;
242
236
}
243
237
244
238
if auto_traits. len ( ) != 0 {
@@ -262,11 +256,11 @@ pub fn push_debuginfo_type_name<'tcx>(
262
256
push_auto_trait_separator ( cpp_like_names, output) ;
263
257
}
264
258
265
- pop_auto_trait_separator ( cpp_like_names , output) ;
259
+ pop_auto_trait_separator ( output) ;
266
260
}
267
261
268
262
if cpp_like_names {
269
- push_close_angle_bracket ( tcx , output) ;
263
+ push_close_angle_bracket ( cpp_like_names , output) ;
270
264
} else if has_enclosing_parens {
271
265
output. push ( ')' ) ;
272
266
}
@@ -320,10 +314,9 @@ pub fn push_debuginfo_type_name<'tcx>(
320
314
if !sig. inputs ( ) . is_empty ( ) {
321
315
for & parameter_type in sig. inputs ( ) {
322
316
push_debuginfo_type_name ( tcx, parameter_type, true , output, visited) ;
323
- output . push_str ( ", " ) ;
317
+ push_arg_separator ( cpp_like_names , output ) ;
324
318
}
325
- output. pop ( ) ;
326
- output. pop ( ) ;
319
+ pop_arg_separator ( output) ;
327
320
}
328
321
329
322
if sig. c_variadic {
@@ -429,21 +422,25 @@ pub fn push_debuginfo_type_name<'tcx>(
429
422
output. push_str ( & format ! ( ", {}" , variant) ) ;
430
423
}
431
424
}
432
- push_close_angle_bracket ( tcx , output) ;
425
+ push_close_angle_bracket ( true , output) ;
433
426
}
434
427
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 = " + " ;
438
429
439
430
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
+ }
441
436
}
442
437
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
+ }
447
444
}
448
445
}
449
446
@@ -504,13 +501,15 @@ fn push_generic_params_internal<'tcx>(
504
501
substs : SubstsRef < ' tcx > ,
505
502
output : & mut String ,
506
503
visited : & mut FxHashSet < Ty < ' tcx > > ,
507
- ) {
504
+ ) -> bool {
508
505
if substs. non_erasable_generics ( ) . next ( ) . is_none ( ) {
509
- return ;
506
+ return false ;
510
507
}
511
508
512
509
debug_assert_eq ! ( substs, tcx. normalize_erasing_regions( ty:: ParamEnv :: reveal_all( ) , substs) ) ;
513
510
511
+ let cpp_like_names = cpp_like_names ( tcx) ;
512
+
514
513
output. push ( '<' ) ;
515
514
516
515
for type_parameter in substs. non_erasable_generics ( ) {
@@ -524,13 +523,12 @@ fn push_generic_params_internal<'tcx>(
524
523
other => bug ! ( "Unexpected non-erasable generic: {:?}" , other) ,
525
524
}
526
525
527
- output . push_str ( ", " ) ;
526
+ push_arg_separator ( cpp_like_names , output ) ;
528
527
}
528
+ pop_arg_separator ( output) ;
529
+ push_close_angle_bracket ( cpp_like_names, output) ;
529
530
530
- output. pop ( ) ;
531
- output. pop ( ) ;
532
-
533
- push_close_angle_bracket ( tcx, output) ;
531
+ true
534
532
}
535
533
536
534
fn 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
583
581
push_generic_params_internal ( tcx, substs, output, & mut visited) ;
584
582
}
585
583
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 ) {
587
585
// MSVC debugger always treats `>>` as a shift, even when parsing templates,
588
586
// so add a space to avoid confusion.
589
- if cpp_like_names ( tcx ) && output. ends_with ( '>' ) {
587
+ if cpp_like_names && output. ends_with ( '>' ) {
590
588
output. push ( ' ' )
591
589
} ;
592
590
593
591
output. push ( '>' ) ;
594
592
}
595
593
596
594
fn pop_close_angle_bracket ( output : & mut String ) {
597
- assert ! ( output. ends_with( '>' ) ) ;
595
+ assert ! ( output. ends_with( '>' ) , "'output' does not end with '>': {}" , output ) ;
598
596
output. pop ( ) ;
599
597
if output. ends_with ( ' ' ) {
600
598
output. pop ( ) ;
601
599
}
602
600
}
603
601
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
+
604
623
fn cpp_like_names ( tcx : TyCtxt < ' _ > ) -> bool {
605
624
tcx. sess . target . is_like_msvc
606
625
}
0 commit comments