1
1
use rustc_data_structures:: base_n;
2
2
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
3
3
use rustc_hir as hir;
4
+ use rustc_hir:: def:: CtorKind ;
4
5
use rustc_hir:: def_id:: { CrateNum , DefId } ;
5
6
use rustc_hir:: definitions:: { DefPathData , DisambiguatedDefPathData } ;
7
+ use rustc_middle:: mir:: interpret:: ConstValue ;
6
8
use rustc_middle:: ty:: layout:: IntegerExt ;
7
9
use rustc_middle:: ty:: print:: { Print , Printer } ;
8
10
use rustc_middle:: ty:: subst:: { GenericArg , GenericArgKind , Subst } ;
@@ -11,6 +13,7 @@ use rustc_target::abi::Integer;
11
13
use rustc_target:: spec:: abi:: Abi ;
12
14
13
15
use std:: fmt:: Write ;
16
+ use std:: iter;
14
17
use std:: ops:: Range ;
15
18
16
19
pub ( super ) fn mangle (
@@ -589,6 +592,103 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
589
592
590
593
let _ = write ! ( self . out, "{:x}_" , bits) ;
591
594
}
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
+
592
692
_ => {
593
693
bug ! ( "symbol_names: unsupported constant of type `{}` ({:?})" , ct. ty, ct) ;
594
694
}
0 commit comments