12
12
// * `"` is treated as the start of a string.
13
13
14
14
use rustc_data_structures:: fx:: FxHashSet ;
15
+ use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
15
16
use rustc_hir as hir;
16
17
use rustc_hir:: def_id:: DefId ;
17
18
use rustc_hir:: definitions:: { DefPathData , DefPathDataName , DisambiguatedDefPathData } ;
19
+ use rustc_middle:: ich:: NodeIdHashingMode ;
20
+ use rustc_middle:: ty:: layout:: IntegerExt ;
18
21
use rustc_middle:: ty:: subst:: { GenericArgKind , SubstsRef } ;
19
22
use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt } ;
20
- use rustc_target:: abi:: { TagEncoding , Variants } ;
23
+ use rustc_target:: abi:: { Integer , TagEncoding , Variants } ;
21
24
22
25
use std:: fmt:: Write ;
23
26
@@ -47,7 +50,7 @@ pub fn push_debuginfo_type_name<'tcx>(
47
50
) {
48
51
// When targeting MSVC, emit C++ style type names for compatibility with
49
52
// .natvis visualizers (and perhaps other existing native debuggers?)
50
- let cpp_like_names = tcx. sess . target . is_like_msvc ;
53
+ let cpp_like_names = cpp_like_names ( tcx) ;
51
54
52
55
match * t. kind ( ) {
53
56
ty:: Bool => output. push_str ( "bool" ) ,
@@ -424,16 +427,14 @@ fn push_unqualified_item_name(
424
427
disambiguated_data : DisambiguatedDefPathData ,
425
428
output : & mut String ,
426
429
) {
427
- let cpp_like_names = tcx. sess . target . is_like_msvc ;
428
-
429
430
match disambiguated_data. data {
430
431
DefPathData :: CrateRoot => {
431
432
output. push_str ( & tcx. crate_name ( def_id. krate ) . as_str ( ) ) ;
432
433
}
433
434
DefPathData :: ClosureExpr if tcx. generator_kind ( def_id) . is_some ( ) => {
434
435
// Generators look like closures, but we want to treat them differently
435
436
// in the debug info.
436
- if cpp_like_names {
437
+ if cpp_like_names ( tcx ) {
437
438
write ! ( output, "generator${}" , disambiguated_data. disambiguator) . unwrap ( ) ;
438
439
} else {
439
440
write ! ( output, "{{generator#{}}}" , disambiguated_data. disambiguator) . unwrap ( ) ;
@@ -444,7 +445,7 @@ fn push_unqualified_item_name(
444
445
output. push_str ( & name. as_str ( ) ) ;
445
446
}
446
447
DefPathDataName :: Anon { namespace } => {
447
- if cpp_like_names {
448
+ if cpp_like_names ( tcx ) {
448
449
write ! ( output, "{}${}" , namespace, disambiguated_data. disambiguator) . unwrap ( ) ;
449
450
} else {
450
451
write ! ( output, "{{{}#{}}}" , namespace, disambiguated_data. disambiguator)
@@ -478,19 +479,14 @@ fn push_generic_params_internal<'tcx>(
478
479
match type_parameter {
479
480
GenericArgKind :: Type ( type_parameter) => {
480
481
push_debuginfo_type_name ( tcx, type_parameter, true , output, visited) ;
481
- output. push_str ( ", " ) ;
482
- }
483
- GenericArgKind :: Const ( const_parameter) => match const_parameter. val {
484
- ty:: ConstKind :: Param ( param) => write ! ( output, "{}, " , param. name) . unwrap ( ) ,
485
- _ => write ! (
486
- output,
487
- "0x{:x}, " ,
488
- const_parameter. eval_bits( tcx, ty:: ParamEnv :: reveal_all( ) , const_parameter. ty)
489
- )
490
- . unwrap ( ) ,
491
- } ,
482
+ }
483
+ GenericArgKind :: Const ( ct) => {
484
+ push_const_param ( tcx, ct, output) ;
485
+ }
492
486
other => bug ! ( "Unexpected non-erasable generic: {:?}" , other) ,
493
487
}
488
+
489
+ output. push_str ( ", " ) ;
494
490
}
495
491
496
492
output. pop ( ) ;
@@ -499,6 +495,51 @@ fn push_generic_params_internal<'tcx>(
499
495
push_close_angle_bracket ( tcx, output) ;
500
496
}
501
497
498
+ fn push_const_param < ' tcx > ( tcx : TyCtxt < ' tcx > , ct : & ' tcx ty:: Const < ' tcx > , output : & mut String ) {
499
+ match ct. val {
500
+ ty:: ConstKind :: Param ( param) => {
501
+ write ! ( output, "{}" , param. name)
502
+ }
503
+ _ => match ct. ty . kind ( ) {
504
+ ty:: Int ( ity) => {
505
+ let bits = ct. eval_bits ( tcx, ty:: ParamEnv :: reveal_all ( ) , ct. ty ) ;
506
+ let val = Integer :: from_int_ty ( & tcx, * ity) . size ( ) . sign_extend ( bits) as i128 ;
507
+ write ! ( output, "{}" , val)
508
+ }
509
+ ty:: Uint ( _) => {
510
+ let val = ct. eval_bits ( tcx, ty:: ParamEnv :: reveal_all ( ) , ct. ty ) ;
511
+ write ! ( output, "{}" , val)
512
+ }
513
+ ty:: Bool => {
514
+ let val = ct. try_eval_bool ( tcx, ty:: ParamEnv :: reveal_all ( ) ) . unwrap ( ) ;
515
+ write ! ( output, "{}" , val)
516
+ }
517
+ _ => {
518
+ // If we cannot evaluate the constant to a known type, we fall back
519
+ // to emitting a stable hash value of the constant. This isn't very pretty
520
+ // but we get a deterministic, virtually unique value for the constant.
521
+ let hcx = & mut tcx. create_stable_hashing_context ( ) ;
522
+ let mut hasher = StableHasher :: new ( ) ;
523
+ hcx. while_hashing_spans ( false , |hcx| {
524
+ hcx. with_node_id_hashing_mode ( NodeIdHashingMode :: HashDefPath , |hcx| {
525
+ ct. val . hash_stable ( hcx, & mut hasher) ;
526
+ } ) ;
527
+ } ) ;
528
+ // Let's only emit 64 bits of the hash value. That should be plenty for
529
+ // avoiding collisions and will make the emitted type names shorter.
530
+ let hash: u64 = hasher. finish ( ) ;
531
+
532
+ if cpp_like_names ( tcx) {
533
+ write ! ( output, "CONST${:x}" , hash)
534
+ } else {
535
+ write ! ( output, "{{CONST#{:x}}}" , hash)
536
+ }
537
+ }
538
+ } ,
539
+ }
540
+ . unwrap ( ) ;
541
+ }
542
+
502
543
pub fn push_generic_params < ' tcx > ( tcx : TyCtxt < ' tcx > , substs : SubstsRef < ' tcx > , output : & mut String ) {
503
544
let mut visited = FxHashSet :: default ( ) ;
504
545
push_generic_params_internal ( tcx, substs, output, & mut visited) ;
@@ -507,9 +548,13 @@ pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, out
507
548
fn push_close_angle_bracket < ' tcx > ( tcx : TyCtxt < ' tcx > , output : & mut String ) {
508
549
// MSVC debugger always treats `>>` as a shift, even when parsing templates,
509
550
// so add a space to avoid confusion.
510
- if tcx. sess . target . is_like_msvc && output. ends_with ( '>' ) {
551
+ if cpp_like_names ( tcx) && output. ends_with ( '>' ) {
511
552
output. push ( ' ' )
512
553
} ;
513
554
514
555
output. push ( '>' ) ;
515
556
}
557
+
558
+ fn cpp_like_names ( tcx : TyCtxt < ' _ > ) -> bool {
559
+ tcx. sess . target . is_like_msvc
560
+ }
0 commit comments