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 (
@@ -578,6 +581,106 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> {
578
581
579
582
let _ = write ! ( self . out, "{:x}_" , bits) ;
580
583
}
584
+
585
+ // HACK(eddyb) because `ty::Const` only supports sized values (for now),
586
+ // we can't use `deref_const` + supporting `str`, we have to specially
587
+ // handle `&str` and include both `&` ("R") and `str` ("e") prefixes.
588
+ ty:: Ref ( _, ty, hir:: Mutability :: Not ) if * ty == self . tcx . types . str_ => {
589
+ self . push ( "R" ) ;
590
+ match ct. val {
591
+ ty:: ConstKind :: Value ( ConstValue :: Slice { data, start, end } ) => {
592
+ // NOTE(eddyb) the following comment was kept from `ty::print::pretty`:
593
+ // The `inspect` here is okay since we checked the bounds, and there are no
594
+ // relocations (we have an active `str` reference here). We don't use this
595
+ // result to affect interpreter execution.
596
+ let slice =
597
+ data. inspect_with_uninit_and_ptr_outside_interpreter ( start..end) ;
598
+ let s = std:: str:: from_utf8 ( slice) . expect ( "non utf8 str from miri" ) ;
599
+
600
+ self . push ( "e" ) ;
601
+ // FIXME(eddyb) use a specialized hex-encoding loop.
602
+ for byte in s. bytes ( ) {
603
+ let _ = write ! ( self . out, "{:02x}" , byte) ;
604
+ }
605
+ self . push ( "_" ) ;
606
+ }
607
+
608
+ _ => {
609
+ bug ! ( "symbol_names: unsupported `&str` constant: {:?}" , ct) ;
610
+ }
611
+ }
612
+ }
613
+
614
+ ty:: Ref ( _, _, mutbl) => {
615
+ self . push ( match mutbl {
616
+ hir:: Mutability :: Not => "R" ,
617
+ hir:: Mutability :: Mut => "Q" ,
618
+ } ) ;
619
+ self = self . tcx . deref_const ( ty:: ParamEnv :: reveal_all ( ) . and ( ct) ) . print ( self ) ?;
620
+ }
621
+
622
+ ty:: Array ( ..) | ty:: Tuple ( ..) | ty:: Adt ( ..) => {
623
+ let contents = self . tcx . destructure_const ( ty:: ParamEnv :: reveal_all ( ) . and ( ct) ) ;
624
+ let fields = contents. fields . iter ( ) . copied ( ) ;
625
+
626
+ let print_field_list = |mut this : Self | {
627
+ for field in fields. clone ( ) {
628
+ this = field. print ( this) ?;
629
+ }
630
+ this. push ( "E" ) ;
631
+ Ok ( this)
632
+ } ;
633
+
634
+ match * ct. ty . kind ( ) {
635
+ ty:: Array ( ..) => {
636
+ self . push ( "A" ) ;
637
+ self = print_field_list ( self ) ?;
638
+ }
639
+ ty:: Tuple ( ..) => {
640
+ self . push ( "T" ) ;
641
+ self = print_field_list ( self ) ?;
642
+ }
643
+ ty:: Adt ( def, substs) => {
644
+ let variant_idx =
645
+ contents. variant . expect ( "destructed const of adt without variant idx" ) ;
646
+ let variant_def = & def. variants [ variant_idx] ;
647
+
648
+ self . push ( "V" ) ;
649
+ self = self . print_def_path ( variant_def. def_id , substs) ?;
650
+
651
+ match variant_def. ctor_kind {
652
+ CtorKind :: Const => {
653
+ self . push ( "U" ) ;
654
+ }
655
+ CtorKind :: Fn => {
656
+ self . push ( "T" ) ;
657
+ self = print_field_list ( self ) ?;
658
+ }
659
+ CtorKind :: Fictive => {
660
+ self . push ( "S" ) ;
661
+ for ( field_def, field) in iter:: zip ( & variant_def. fields , fields) {
662
+ // HACK(eddyb) this mimics `path_append`,
663
+ // instead of simply using `field_def.ident`,
664
+ // just to be able to handle disambiguators.
665
+ let disambiguated_field =
666
+ self . tcx . def_key ( field_def. did ) . disambiguated_data ;
667
+ let field_name =
668
+ disambiguated_field. data . get_opt_name ( ) . map ( |s| s. as_str ( ) ) ;
669
+ self . push_disambiguator (
670
+ disambiguated_field. disambiguator as u64 ,
671
+ ) ;
672
+ self . push_ident ( & field_name. as_ref ( ) . map_or ( "" , |s| & s[ ..] ) ) ;
673
+
674
+ self = field. print ( self ) ?;
675
+ }
676
+ self . push ( "E" ) ;
677
+ }
678
+ }
679
+ }
680
+ _ => unreachable ! ( ) ,
681
+ }
682
+ }
683
+
581
684
_ => {
582
685
bug ! ( "symbol_names: unsupported constant of type `{}` ({:?})" , ct. ty, ct) ;
583
686
}
0 commit comments