1212// * `"` is treated as the start of a string.
1313
1414use rustc_data_structures:: fx:: FxHashSet ;
15+ use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
1516use rustc_hir as hir;
1617use rustc_hir:: def_id:: DefId ;
1718use rustc_hir:: definitions:: { DefPathData , DefPathDataName , DisambiguatedDefPathData } ;
19+ use rustc_middle:: ich:: NodeIdHashingMode ;
20+ use rustc_middle:: ty:: layout:: IntegerExt ;
1821use rustc_middle:: ty:: subst:: { GenericArgKind , SubstsRef } ;
1922use rustc_middle:: ty:: { self , AdtDef , Ty , TyCtxt } ;
20- use rustc_target:: abi:: { TagEncoding , Variants } ;
23+ use rustc_target:: abi:: { Integer , TagEncoding , Variants } ;
2124
2225use std:: fmt:: Write ;
2326
@@ -47,7 +50,7 @@ pub fn push_debuginfo_type_name<'tcx>(
4750) {
4851 // When targeting MSVC, emit C++ style type names for compatibility with
4952 // .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) ;
5154
5255 match * t. kind ( ) {
5356 ty:: Bool => output. push_str ( "bool" ) ,
@@ -424,16 +427,14 @@ fn push_unqualified_item_name(
424427 disambiguated_data : DisambiguatedDefPathData ,
425428 output : & mut String ,
426429) {
427- let cpp_like_names = tcx. sess . target . is_like_msvc ;
428-
429430 match disambiguated_data. data {
430431 DefPathData :: CrateRoot => {
431432 output. push_str ( & tcx. crate_name ( def_id. krate ) . as_str ( ) ) ;
432433 }
433434 DefPathData :: ClosureExpr if tcx. generator_kind ( def_id) . is_some ( ) => {
434435 // Generators look like closures, but we want to treat them differently
435436 // in the debug info.
436- if cpp_like_names {
437+ if cpp_like_names ( tcx ) {
437438 write ! ( output, "generator${}" , disambiguated_data. disambiguator) . unwrap ( ) ;
438439 } else {
439440 write ! ( output, "{{generator#{}}}" , disambiguated_data. disambiguator) . unwrap ( ) ;
@@ -444,7 +445,7 @@ fn push_unqualified_item_name(
444445 output. push_str ( & name. as_str ( ) ) ;
445446 }
446447 DefPathDataName :: Anon { namespace } => {
447- if cpp_like_names {
448+ if cpp_like_names ( tcx ) {
448449 write ! ( output, "{}${}" , namespace, disambiguated_data. disambiguator) . unwrap ( ) ;
449450 } else {
450451 write ! ( output, "{{{}#{}}}" , namespace, disambiguated_data. disambiguator)
@@ -478,19 +479,14 @@ fn push_generic_params_internal<'tcx>(
478479 match type_parameter {
479480 GenericArgKind :: Type ( type_parameter) => {
480481 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+ }
492486 other => bug ! ( "Unexpected non-erasable generic: {:?}" , other) ,
493487 }
488+
489+ output. push_str ( ", " ) ;
494490 }
495491
496492 output. pop ( ) ;
@@ -499,6 +495,51 @@ fn push_generic_params_internal<'tcx>(
499495 push_close_angle_bracket ( tcx, output) ;
500496}
501497
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+
502543pub fn push_generic_params < ' tcx > ( tcx : TyCtxt < ' tcx > , substs : SubstsRef < ' tcx > , output : & mut String ) {
503544 let mut visited = FxHashSet :: default ( ) ;
504545 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
507548fn push_close_angle_bracket < ' tcx > ( tcx : TyCtxt < ' tcx > , output : & mut String ) {
508549 // MSVC debugger always treats `>>` as a shift, even when parsing templates,
509550 // 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 ( '>' ) {
511552 output. push ( ' ' )
512553 } ;
513554
514555 output. push ( '>' ) ;
515556}
557+
558+ fn cpp_like_names ( tcx : TyCtxt < ' _ > ) -> bool {
559+ tcx. sess . target . is_like_msvc
560+ }
0 commit comments