@@ -19,8 +19,9 @@ use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathD
19
19
use rustc_middle:: ich:: NodeIdHashingMode ;
20
20
use rustc_middle:: ty:: layout:: IntegerExt ;
21
21
use rustc_middle:: ty:: subst:: { GenericArgKind , SubstsRef } ;
22
- use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt } ;
22
+ use rustc_middle:: ty:: { self , AdtDef , ExistentialProjection , Ty , TyCtxt } ;
23
23
use rustc_target:: abi:: { Integer , TagEncoding , Variants } ;
24
+ use smallvec:: SmallVec ;
24
25
25
26
use std:: fmt:: Write ;
26
27
@@ -188,63 +189,86 @@ pub fn push_debuginfo_type_name<'tcx>(
188
189
}
189
190
}
190
191
ty:: Dynamic ( ref trait_data, ..) => {
191
- if cpp_like_names {
192
+ let auto_traits: SmallVec < [ DefId ; 4 ] > = trait_data. auto_traits ( ) . collect ( ) ;
193
+
194
+ let has_enclosing_parens = if cpp_like_names {
192
195
output. push_str ( "dyn$<" ) ;
196
+ false
193
197
} else {
194
- output. push_str ( "dyn " ) ;
195
- }
198
+ if trait_data. len ( ) > 1 && auto_traits. len ( ) != 0 {
199
+ // We need enclosing parens
200
+ output. push_str ( "(dyn " ) ;
201
+ true
202
+ } else {
203
+ output. push_str ( "dyn " ) ;
204
+ false
205
+ }
206
+ } ;
196
207
197
208
if let Some ( principal) = trait_data. principal ( ) {
198
209
let principal =
199
210
tcx. normalize_erasing_late_bound_regions ( ty:: ParamEnv :: reveal_all ( ) , principal) ;
200
211
push_item_name ( tcx, principal. def_id , qualified, output) ;
201
212
push_generic_params_internal ( tcx, principal. substs , output, visited) ;
202
- } else {
203
- // The auto traits come ordered by `DefPathHash`, which guarantees stability if the
204
- // environment is stable (e.g., incremental builds) but not otherwise (e.g.,
205
- // updated compiler version, different target).
206
- //
207
- // To avoid that causing instabilities in test output, sort the auto-traits
208
- // alphabetically.
209
- let mut auto_traits: Vec < _ > = trait_data
210
- . iter ( )
211
- . filter_map ( |predicate| {
212
- match tcx. normalize_erasing_late_bound_regions (
213
- ty:: ParamEnv :: reveal_all ( ) ,
214
- predicate,
215
- ) {
216
- ty:: ExistentialPredicate :: AutoTrait ( def_id) => {
217
- let mut name = String :: new ( ) ;
218
- push_item_name ( tcx, def_id, true , & mut name) ;
219
- Some ( name)
220
- }
221
- _ => None ,
222
- }
213
+
214
+ let projection_bounds: SmallVec < [ _ ; 4 ] > = trait_data
215
+ . projection_bounds ( )
216
+ . map ( |bound| {
217
+ let ExistentialProjection { item_def_id, ty, .. } = bound. skip_binder ( ) ;
218
+ ( item_def_id, ty)
223
219
} )
224
220
. collect ( ) ;
225
- auto_traits. sort ( ) ;
226
221
227
- for name in auto_traits {
228
- output . push_str ( & name ) ;
222
+ if projection_bounds . len ( ) != 0 {
223
+ pop_close_angle_bracket ( output ) ;
229
224
230
- if cpp_like_names {
225
+ for ( item_def_id , ty ) in projection_bounds {
231
226
output. push_str ( ", " ) ;
232
- } else {
233
- output. push_str ( " + " ) ;
227
+
228
+ if cpp_like_names {
229
+ output. push_str ( "assoc$<" ) ;
230
+ push_item_name ( tcx, item_def_id, false , output) ;
231
+ output. push_str ( ", " ) ;
232
+ push_debuginfo_type_name ( tcx, ty, true , output, visited) ;
233
+ push_close_angle_bracket ( tcx, output) ;
234
+ } else {
235
+ push_item_name ( tcx, item_def_id, false , output) ;
236
+ output. push ( '=' ) ;
237
+ push_debuginfo_type_name ( tcx, ty, true , output, visited) ;
238
+ }
234
239
}
240
+
241
+ push_close_angle_bracket ( tcx, output) ;
235
242
}
236
243
237
- // Remove the trailing joining characters. For cpp_like_names
238
- // this is `, ` otherwise ` + `.
239
- output. pop ( ) ;
240
- output. pop ( ) ;
241
- if !cpp_like_names {
242
- output. pop ( ) ;
244
+ if auto_traits. len ( ) != 0 {
245
+ push_auto_trait_separator ( cpp_like_names, output) ;
246
+ }
247
+ }
248
+
249
+ if auto_traits. len ( ) != 0 {
250
+ let mut auto_traits: SmallVec < [ String ; 4 ] > = auto_traits
251
+ . into_iter ( )
252
+ . map ( |def_id| {
253
+ let mut name = String :: with_capacity ( 20 ) ;
254
+ push_item_name ( tcx, def_id, true , & mut name) ;
255
+ name
256
+ } )
257
+ . collect ( ) ;
258
+ auto_traits. sort_unstable ( ) ;
259
+
260
+ for auto_trait in auto_traits {
261
+ output. push_str ( & auto_trait) ;
262
+ push_auto_trait_separator ( cpp_like_names, output) ;
243
263
}
264
+
265
+ pop_auto_trait_separator ( cpp_like_names, output) ;
244
266
}
245
267
246
268
if cpp_like_names {
247
269
push_close_angle_bracket ( tcx, output) ;
270
+ } else if has_enclosing_parens {
271
+ output. push ( ')' ) ;
248
272
}
249
273
}
250
274
ty:: FnDef ( ..) | ty:: FnPtr ( _) => {
@@ -407,6 +431,20 @@ pub fn push_debuginfo_type_name<'tcx>(
407
431
}
408
432
push_close_angle_bracket ( tcx, output) ;
409
433
}
434
+
435
+ fn auto_trait_separator ( cpp_like_names : bool ) -> & ' static str {
436
+ if cpp_like_names { ", " } else { " + " }
437
+ }
438
+
439
+ fn push_auto_trait_separator ( cpp_like_names : bool , output : & mut String ) {
440
+ output. push_str ( auto_trait_separator ( cpp_like_names) ) ;
441
+ }
442
+
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 ( ) ) ;
447
+ }
410
448
}
411
449
412
450
pub fn push_item_name ( tcx : TyCtxt < ' tcx > , def_id : DefId , qualified : bool , output : & mut String ) {
@@ -555,6 +593,14 @@ fn push_close_angle_bracket<'tcx>(tcx: TyCtxt<'tcx>, output: &mut String) {
555
593
output. push ( '>' ) ;
556
594
}
557
595
596
+ fn pop_close_angle_bracket ( output : & mut String ) {
597
+ assert ! ( output. ends_with( '>' ) ) ;
598
+ output. pop ( ) ;
599
+ if output. ends_with ( ' ' ) {
600
+ output. pop ( ) ;
601
+ }
602
+ }
603
+
558
604
fn cpp_like_names ( tcx : TyCtxt < ' _ > ) -> bool {
559
605
tcx. sess . target . is_like_msvc
560
606
}
0 commit comments