11use crate :: hir:: map:: { DefPathData , DisambiguatedDefPathData } ;
22use crate :: middle:: cstore:: { ExternCrate , ExternCrateSource } ;
33use crate :: middle:: region;
4- use crate :: mir:: interpret:: { sign_extend, truncate, ConstValue , Scalar } ;
4+ use crate :: mir:: interpret:: { sign_extend, truncate, AllocId , ConstValue , Pointer , Scalar } ;
55use crate :: ty:: layout:: { Integer , IntegerExt , Size } ;
66use crate :: ty:: subst:: { GenericArg , GenericArgKind , Subst } ;
77use crate :: ty:: { self , DefIdTree , ParamConst , Ty , TyCtxt , TypeFoldable } ;
@@ -457,6 +457,22 @@ pub trait PrettyPrinter<'tcx>:
457457 } )
458458 }
459459
460+ fn print_type_ascribed (
461+ mut self ,
462+ f : impl FnOnce ( Self ) -> Result < Self , Self :: Error > ,
463+ ty : Ty < ' tcx > ,
464+ print_ty : bool ,
465+ ) -> Result < Self :: Const , Self :: Error > {
466+ self . write_str ( "{" ) ?;
467+ self = f ( self ) ?;
468+ if print_ty {
469+ self . write_str ( ": " ) ?;
470+ self = self . print_type ( ty) ?;
471+ }
472+ self . write_str ( "}" ) ?;
473+ Ok ( self )
474+ }
475+
460476 fn pretty_print_type ( mut self , ty : Ty < ' tcx > ) -> Result < Self :: Type , Self :: Error > {
461477 define_scoped_cx ! ( self ) ;
462478
@@ -893,32 +909,49 @@ pub trait PrettyPrinter<'tcx>:
893909 Ok ( self )
894910 }
895911
896- fn pretty_print_const_value (
912+ fn pretty_print_const_scalar (
897913 mut self ,
898- ct : ConstValue < ' tcx > ,
914+ scalar : Scalar ,
899915 ty : Ty < ' tcx > ,
900916 print_ty : bool ,
901917 ) -> Result < Self :: Const , Self :: Error > {
902918 define_scoped_cx ! ( self ) ;
903919
904- if self . tcx ( ) . sess . verbose ( ) {
905- p ! ( write( "ConstValue({:?}: {:?})" , ct, ty) ) ;
906- return Ok ( self ) ;
907- }
908-
909- let u8 = self . tcx ( ) . types . u8 ;
910-
911- match ( ct, & ty. kind ) {
912- ( ConstValue :: Scalar ( Scalar :: Raw { data, .. } ) , ty:: Bool ) => {
913- p ! ( write( "{}" , if data == 0 { "false" } else { "true" } ) )
914- }
915- ( ConstValue :: Scalar ( Scalar :: Raw { data, .. } ) , ty:: Float ( ast:: FloatTy :: F32 ) ) => {
920+ match ( scalar, & ty. kind ) {
921+ // Single element arrays print their element (they are `#[transparent]`) enclosed in
922+ // square brackets.
923+ ( _, ty:: Array ( t, n) ) if n. eval_usize ( self . tcx ( ) , ty:: ParamEnv :: empty ( ) ) == 1 => {
924+ p ! ( write( "[" ) ) ;
925+ self = self . pretty_print_const_scalar ( scalar, t, print_ty) ?;
926+ p ! ( write( "]" ) ) ;
927+ }
928+ // Byte strings (&[u8; N])
929+ ( Scalar :: Ptr ( ptr) , ty:: Ref ( _, ty:: TyS { kind : ty:: Array ( t, n) , .. } , _) )
930+ if * t == self . tcx ( ) . types . u8 =>
931+ {
932+ let n = n. eval_usize ( self . tcx ( ) , ty:: ParamEnv :: empty ( ) ) ;
933+ let byte_str = self
934+ . tcx ( )
935+ . alloc_map
936+ . lock ( )
937+ . unwrap_memory ( ptr. alloc_id )
938+ . get_bytes ( & self . tcx ( ) , ptr, Size :: from_bytes ( n) )
939+ . unwrap ( ) ;
940+ p ! ( pretty_print_byte_str( byte_str) ) ;
941+ }
942+ // Bool
943+ ( Scalar :: Raw { data : 0 , .. } , ty:: Bool ) => p ! ( write( "false" ) ) ,
944+ ( Scalar :: Raw { data : 1 , .. } , ty:: Bool ) => p ! ( write( "true" ) ) ,
945+ ( Scalar :: Raw { data, .. } , ty:: Bool ) => p ! ( write( "{}_bool" , data) ) ,
946+ // Float
947+ ( Scalar :: Raw { data, .. } , ty:: Float ( ast:: FloatTy :: F32 ) ) => {
916948 p ! ( write( "{}f32" , Single :: from_bits( data) ) )
917949 }
918- ( ConstValue :: Scalar ( Scalar :: Raw { data, .. } ) , ty:: Float ( ast:: FloatTy :: F64 ) ) => {
950+ ( Scalar :: Raw { data, .. } , ty:: Float ( ast:: FloatTy :: F64 ) ) => {
919951 p ! ( write( "{}f64" , Double :: from_bits( data) ) )
920952 }
921- ( ConstValue :: Scalar ( Scalar :: Raw { data, .. } ) , ty:: Uint ( ui) ) => {
953+ // Int
954+ ( Scalar :: Raw { data, .. } , ty:: Uint ( ui) ) => {
922955 let bit_size = Integer :: from_attr ( & self . tcx ( ) , UnsignedInt ( * ui) ) . size ( ) ;
923956 let max = truncate ( u128:: MAX , bit_size) ;
924957
@@ -929,7 +962,7 @@ pub trait PrettyPrinter<'tcx>:
929962 p ! ( write( "{}{}" , data, ui_str) )
930963 } ;
931964 }
932- ( ConstValue :: Scalar ( Scalar :: Raw { data, .. } ) , ty:: Int ( i) ) => {
965+ ( Scalar :: Raw { data, .. } , ty:: Int ( i) ) => {
933966 let bit_size = Integer :: from_attr ( & self . tcx ( ) , SignedInt ( * i) ) . size ( ) . bits ( ) as u128 ;
934967 let min = 1u128 << ( bit_size - 1 ) ;
935968 let max = min - 1 ;
@@ -943,76 +976,140 @@ pub trait PrettyPrinter<'tcx>:
943976 _ => p ! ( write( "{}{}" , sign_extend( data, size) as i128 , i_str) ) ,
944977 }
945978 }
946- ( ConstValue :: Scalar ( Scalar :: Raw { data, .. } ) , ty:: Char ) => {
947- p ! ( write( "{:?}" , :: std:: char :: from_u32( data as u32 ) . unwrap( ) ) )
979+ // Char
980+ ( Scalar :: Raw { data, .. } , ty:: Char ) => match :: std:: char:: from_u32 ( data as u32 ) {
981+ Some ( c) => p ! ( write( "{:?}" , c) ) ,
982+ None => p ! ( write( "{}_char" , data) ) ,
983+ } ,
984+ // References and pointers
985+ ( Scalar :: Raw { data : 0 , .. } , ty:: RawPtr ( _) ) => p ! ( write( "{{null pointer}}" ) ) ,
986+ // This is UB, but we still print it
987+ ( Scalar :: Raw { data : 0 , .. } , ty:: Ref ( _, ty, _) ) => {
988+ p ! ( write( "{{null reference to " ) , print( ty) , write( "}}" ) )
948989 }
949- ( ConstValue :: Scalar ( _) , ty:: RawPtr ( _) ) => p ! ( write( "{{pointer}}" ) ) ,
950- ( ConstValue :: Scalar ( Scalar :: Ptr ( ptr) ) , ty:: FnPtr ( _) ) => {
990+ ( Scalar :: Raw { data, .. } , ty:: Ref ( ..) ) | ( Scalar :: Raw { data, .. } , ty:: RawPtr ( _) ) => {
991+ let pointer_width = self . tcx ( ) . data_layout . pointer_size . bytes ( ) ;
992+ p ! ( write( "0x{:01$x}" , data, pointer_width as usize * 2 ) )
993+ }
994+ ( Scalar :: Ptr ( ptr) , ty:: FnPtr ( _) ) => {
951995 let instance = {
952996 let alloc_map = self . tcx ( ) . alloc_map . lock ( ) ;
953997 alloc_map. unwrap_fn ( ptr. alloc_id )
954998 } ;
955999 p ! ( print_value_path( instance. def_id( ) , instance. substs) ) ;
9561000 }
957- _ => {
958- let printed = if let ty:: Ref ( _, ref_ty, _) = ty. kind {
959- let byte_str = match ( ct, & ref_ty. kind ) {
960- ( ConstValue :: Scalar ( Scalar :: Ptr ( ptr) ) , ty:: Array ( t, n) ) if * t == u8 => {
961- let n = n. eval_usize ( self . tcx ( ) , ty:: ParamEnv :: empty ( ) ) ;
962- Some (
963- self . tcx ( )
964- . alloc_map
965- . lock ( )
966- . unwrap_memory ( ptr. alloc_id )
967- . get_bytes ( & self . tcx ( ) , ptr, Size :: from_bytes ( n) )
968- . unwrap ( ) ,
969- )
970- }
971- ( ConstValue :: Slice { data, start, end } , ty:: Slice ( t) ) if * t == u8 => {
972- // The `inspect` here is okay since we checked the bounds, and there are
973- // no relocations (we have an active slice reference here). We don't use
974- // this result to affect interpreter execution.
975- Some ( data. inspect_with_undef_and_ptr_outside_interpreter ( start..end) )
976- }
977- _ => None ,
978- } ;
1001+ // For zsts just print their type as their value gives no extra information
1002+ ( Scalar :: Raw { size : 0 , .. } , _) => p ! ( print( ty) ) ,
1003+ // Nontrivial types with scalar bit representation
1004+ ( Scalar :: Raw { data, size } , _) => {
1005+ self = self . print_type_ascribed (
1006+ |mut this| {
1007+ write ! ( this, "0x{:01$x}" , data, size as usize * 2 ) ?;
1008+ Ok ( this)
1009+ } ,
1010+ ty,
1011+ print_ty,
1012+ ) ?
1013+ }
1014+ // Any pointer values not covered by a branch above
1015+ ( Scalar :: Ptr ( p) , _) => {
1016+ self = self . pretty_print_const_pointer ( p, ty, print_ty) ?;
1017+ }
1018+ }
1019+ Ok ( self )
1020+ }
9791021
980- if let Some ( byte_str) = byte_str {
981- p ! ( write( "b\" " ) ) ;
982- for & c in byte_str {
983- for e in std:: ascii:: escape_default ( c) {
984- self . write_char ( e as char ) ?;
985- }
986- }
987- p ! ( write( "\" " ) ) ;
988- true
989- } else if let ( ConstValue :: Slice { data, start, end } , ty:: Str ) =
990- ( ct, & ref_ty. kind )
991- {
992- // The `inspect` here is okay since we checked the bounds, and there are no
993- // relocations (we have an active `str` reference here). We don't use this
994- // result to affect interpreter execution.
995- let slice = data. inspect_with_undef_and_ptr_outside_interpreter ( start..end) ;
996- let s = :: std:: str:: from_utf8 ( slice) . expect ( "non utf8 str from miri" ) ;
997- p ! ( write( "{:?}" , s) ) ;
998- true
999- } else {
1000- false
1001- }
1002- } else {
1003- false
1004- } ;
1005- if !printed {
1006- // fallback
1007- p ! ( write( "{:?}" , ct) ) ;
1008- if print_ty {
1009- p ! ( write( ": " ) , print( ty) ) ;
1010- }
1011- }
1022+ /// This is overridden for MIR printing because we only want to hide alloc ids from users, not
1023+ /// from MIR where it is actually useful.
1024+ fn pretty_print_const_pointer (
1025+ self ,
1026+ _: Pointer ,
1027+ ty : Ty < ' tcx > ,
1028+ print_ty : bool ,
1029+ ) -> Result < Self :: Const , Self :: Error > {
1030+ self . print_type_ascribed (
1031+ |mut this| {
1032+ this. write_str ( "pointer" ) ?;
1033+ Ok ( this)
1034+ } ,
1035+ ty,
1036+ print_ty,
1037+ )
1038+ }
1039+
1040+ fn pretty_print_byte_str ( mut self , byte_str : & ' tcx [ u8 ] ) -> Result < Self :: Const , Self :: Error > {
1041+ define_scoped_cx ! ( self ) ;
1042+ p ! ( write( "b\" " ) ) ;
1043+ for & c in byte_str {
1044+ for e in std:: ascii:: escape_default ( c) {
1045+ self . write_char ( e as char ) ?;
10121046 }
1013- } ;
1047+ }
1048+ p ! ( write( "\" " ) ) ;
10141049 Ok ( self )
10151050 }
1051+
1052+ fn pretty_print_const_value (
1053+ mut self ,
1054+ ct : ConstValue < ' tcx > ,
1055+ ty : Ty < ' tcx > ,
1056+ print_ty : bool ,
1057+ ) -> Result < Self :: Const , Self :: Error > {
1058+ define_scoped_cx ! ( self ) ;
1059+
1060+ if self . tcx ( ) . sess . verbose ( ) {
1061+ p ! ( write( "ConstValue({:?}: {:?})" , ct, ty) ) ;
1062+ return Ok ( self ) ;
1063+ }
1064+
1065+ let u8_type = self . tcx ( ) . types . u8 ;
1066+
1067+ match ( ct, & ty. kind ) {
1068+ ( ConstValue :: Scalar ( scalar) , _) => self . pretty_print_const_scalar ( scalar, ty, print_ty) ,
1069+ (
1070+ ConstValue :: Slice { data, start, end } ,
1071+ ty:: Ref ( _, ty:: TyS { kind : ty:: Slice ( t) , .. } , _) ,
1072+ ) if * t == u8_type => {
1073+ // The `inspect` here is okay since we checked the bounds, and there are
1074+ // no relocations (we have an active slice reference here). We don't use
1075+ // this result to affect interpreter execution.
1076+ let byte_str = data. inspect_with_undef_and_ptr_outside_interpreter ( start..end) ;
1077+ self . pretty_print_byte_str ( byte_str)
1078+ }
1079+ (
1080+ ConstValue :: Slice { data, start, end } ,
1081+ ty:: Ref ( _, ty:: TyS { kind : ty:: Str , .. } , _) ,
1082+ ) => {
1083+ // The `inspect` here is okay since we checked the bounds, and there are no
1084+ // relocations (we have an active `str` reference here). We don't use this
1085+ // result to affect interpreter execution.
1086+ let slice = data. inspect_with_undef_and_ptr_outside_interpreter ( start..end) ;
1087+ let s = :: std:: str:: from_utf8 ( slice) . expect ( "non utf8 str from miri" ) ;
1088+ p ! ( write( "{:?}" , s) ) ;
1089+ Ok ( self )
1090+ }
1091+ ( ConstValue :: ByRef { alloc, offset } , ty:: Array ( t, n) ) if * t == u8_type => {
1092+ let n = n. eval_usize ( self . tcx ( ) , ty:: ParamEnv :: empty ( ) ) ;
1093+ let n = Size :: from_bytes ( n) ;
1094+ let ptr = Pointer :: new ( AllocId ( 0 ) , offset) ;
1095+
1096+ let byte_str = alloc. get_bytes ( & self . tcx ( ) , ptr, n) . unwrap ( ) ;
1097+ p ! ( write( "*" ) ) ;
1098+ p ! ( pretty_print_byte_str( byte_str) ) ;
1099+ Ok ( self )
1100+ }
1101+ // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
1102+ // their fields instead of just dumping the memory.
1103+ _ => {
1104+ // fallback
1105+ p ! ( write( "{:?}" , ct) ) ;
1106+ if print_ty {
1107+ p ! ( write( ": " ) , print( ty) ) ;
1108+ }
1109+ Ok ( self )
1110+ }
1111+ }
1112+ }
10161113}
10171114
10181115// HACK(eddyb) boxed to avoid moving around a large struct by-value.
@@ -1024,6 +1121,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> {
10241121
10251122 empty_path : bool ,
10261123 in_value : bool ,
1124+ pub print_alloc_ids : bool ,
10271125
10281126 used_region_names : FxHashSet < Symbol > ,
10291127 region_index : usize ,
@@ -1054,6 +1152,7 @@ impl<F> FmtPrinter<'a, 'tcx, F> {
10541152 fmt,
10551153 empty_path : false ,
10561154 in_value : ns == Namespace :: ValueNS ,
1155+ print_alloc_ids : false ,
10571156 used_region_names : Default :: default ( ) ,
10581157 region_index : 0 ,
10591158 binder_depth : 0 ,
@@ -1382,6 +1481,45 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
13821481 ty:: ReStatic | ty:: ReEmpty ( _) | ty:: ReClosureBound ( _) => true ,
13831482 }
13841483 }
1484+
1485+ fn pretty_print_const_pointer (
1486+ self ,
1487+ p : Pointer ,
1488+ ty : Ty < ' tcx > ,
1489+ print_ty : bool ,
1490+ ) -> Result < Self :: Const , Self :: Error > {
1491+ self . print_type_ascribed (
1492+ |mut this| {
1493+ define_scoped_cx ! ( this) ;
1494+ if this. print_alloc_ids {
1495+ p ! ( write( "{:?}" , p) ) ;
1496+ } else {
1497+ p ! ( write( "pointer" ) ) ;
1498+ }
1499+ Ok ( this)
1500+ } ,
1501+ ty,
1502+ print_ty,
1503+ )
1504+ }
1505+
1506+ fn print_type_ascribed (
1507+ mut self ,
1508+ f : impl FnOnce ( Self ) -> Result < Self , Self :: Error > ,
1509+ ty : Ty < ' tcx > ,
1510+ print_ty : bool ,
1511+ ) -> Result < Self :: Const , Self :: Error > {
1512+ self . write_str ( "{" ) ?;
1513+ self = f ( self ) ?;
1514+ if print_ty {
1515+ self . write_str ( ": " ) ?;
1516+ let was_in_value = std:: mem:: replace ( & mut self . in_value , false ) ;
1517+ self = self . print_type ( ty) ?;
1518+ self . in_value = was_in_value;
1519+ }
1520+ self . write_str ( "}" ) ?;
1521+ Ok ( self )
1522+ }
13851523}
13861524
13871525// HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
0 commit comments