11use rustc_data_structures:: base_n;
22use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
33use rustc_hir as hir;
4+ use rustc_hir:: def:: CtorKind ;
45use rustc_hir:: def_id:: { CrateNum , DefId } ;
56use rustc_hir:: definitions:: { DefPathData , DisambiguatedDefPathData } ;
7+ use rustc_middle:: mir:: interpret:: ConstValue ;
68use rustc_middle:: ty:: layout:: IntegerExt ;
79use rustc_middle:: ty:: print:: { Print , Printer } ;
810use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , Subst } ;
@@ -11,6 +13,7 @@ use rustc_target::abi::Integer;
1113use rustc_target:: spec:: abi:: Abi ;
1214
1315use std:: fmt:: Write ;
16+ use std:: iter;
1417use std:: ops:: Range ;
1518
1619pub ( super ) fn mangle (
@@ -589,6 +592,103 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
589592
590593 let _ = write ! ( self . out, "{:x}_" , bits) ;
591594 }
595+
596+ // HACK(eddyb) because `ty::Const` only supports sized values (for now),
597+ // we can't use `deref_const` + supporting `str`, we have to specially
598+ // handle `&str` and include both `&` ("R") and `str` ("e") prefixes.
599+ ty:: Ref ( _, ty, hir:: Mutability :: Not ) if * ty == self . tcx . types . str_ => {
600+ self . push ( "R" ) ;
601+ match ct. val {
602+ ty:: ConstKind :: Value ( ConstValue :: Slice { data, start, end } ) => {
603+ // NOTE(eddyb) the following comment was kept from `ty::print::pretty`:
604+ // The `inspect` here is okay since we checked the bounds, and there are no
605+ // relocations (we have an active `str` reference here). We don't use this
606+ // result to affect interpreter execution.
607+ let slice =
608+ data. inspect_with_uninit_and_ptr_outside_interpreter ( start..end) ;
609+ let s = std:: str:: from_utf8 ( slice) . expect ( "non utf8 str from miri" ) ;
610+
611+ self . push ( "e" ) ;
612+ // FIXME(eddyb) use a specialized hex-encoding loop.
613+ for byte in s. bytes ( ) {
614+ let _ = write ! ( self . out, "{:02x}" , byte) ;
615+ }
616+ self . push ( "_" ) ;
617+ }
618+
619+ _ => {
620+ bug ! ( "symbol_names: unsupported `&str` constant: {:?}" , ct) ;
621+ }
622+ }
623+ }
624+
625+ ty:: Ref ( _, _, mutbl) => {
626+ self . push ( match mutbl {
627+ hir:: Mutability :: Not => "R" ,
628+ hir:: Mutability :: Mut => "Q" ,
629+ } ) ;
630+ self = self . tcx . deref_const ( ty:: ParamEnv :: reveal_all ( ) . and ( ct) ) . print ( self ) ?;
631+ }
632+
633+ ty:: Array ( ..) | ty:: Tuple ( ..) | ty:: Adt ( ..) => {
634+ let contents = self . tcx . destructure_const ( ty:: ParamEnv :: reveal_all ( ) . and ( ct) ) ;
635+ let fields = contents. fields . iter ( ) . copied ( ) ;
636+
637+ let print_field_list = |mut this : Self , prefix| {
638+ this. push ( prefix) ;
639+ for field in fields. clone ( ) {
640+ this = field. print ( this) ?;
641+ }
642+ this. push ( "E" ) ;
643+ Ok ( this)
644+ } ;
645+
646+ match * ct. ty . kind ( ) {
647+ ty:: Array ( ..) => {
648+ self = print_field_list ( self , "A" ) ?;
649+ }
650+ ty:: Tuple ( ..) => {
651+ self = print_field_list ( self , "T" ) ?;
652+ }
653+ ty:: Adt ( def, substs) => {
654+ let variant_idx =
655+ contents. variant . expect ( "destructed const of adt without variant idx" ) ;
656+ let variant_def = & def. variants [ variant_idx] ;
657+
658+ self . push ( "V" ) ;
659+ self = self . print_def_path ( variant_def. def_id , substs) ?;
660+
661+ match variant_def. ctor_kind {
662+ CtorKind :: Const => {
663+ self . push ( "u" ) ;
664+ }
665+ CtorKind :: Fn => {
666+ self = print_field_list ( self , "T" ) ?;
667+ }
668+ CtorKind :: Fictive => {
669+ for ( field_def, field) in iter:: zip ( & variant_def. fields , fields) {
670+ // HACK(eddyb) this mimics `path_append`,
671+ // instead of simply using `field_def.ident`,
672+ // just to be able to handle disambiguators.
673+ let disambiguated_field =
674+ self . tcx . def_key ( field_def. did ) . disambiguated_data ;
675+ let field_name =
676+ disambiguated_field. data . get_opt_name ( ) . map ( |s| s. as_str ( ) ) ;
677+ self . push_disambiguator (
678+ disambiguated_field. disambiguator as u64 ,
679+ ) ;
680+ self . push_ident ( & field_name. as_ref ( ) . map_or ( "" , |s| & s[ ..] ) ) ;
681+
682+ self = field. print ( self ) ?;
683+ }
684+ self . push ( "E" ) ;
685+ }
686+ }
687+ }
688+ _ => unreachable ! ( ) ,
689+ }
690+ }
691+
592692 _ => {
593693 bug ! ( "symbol_names: unsupported constant of type `{}` ({:?})" , ct. ty, ct) ;
594694 }
0 commit comments