@@ -9,7 +9,10 @@ use rustc_apfloat::{
9
9
use rustc_macros:: HashStable ;
10
10
use rustc_target:: abi:: { HasDataLayout , Size } ;
11
11
12
- use crate :: ty:: { ParamEnv , ScalarInt , Ty , TyCtxt } ;
12
+ use crate :: {
13
+ mir:: interpret:: alloc_range,
14
+ ty:: { ParamEnv , ScalarInt , Ty , TyCtxt } ,
15
+ } ;
13
16
14
17
use super :: {
15
18
AllocId , ConstAllocation , InterpResult , Pointer , PointerArithmetic , Provenance ,
@@ -114,6 +117,54 @@ impl<'tcx> ConstValue<'tcx> {
114
117
pub fn from_target_usize ( i : u64 , cx : & impl HasDataLayout ) -> Self {
115
118
ConstValue :: Scalar ( Scalar :: from_target_usize ( i, cx) )
116
119
}
120
+
121
+ /// Must only be called on constants of type `&str` or `&[u8]`!
122
+ pub fn try_get_slice_bytes_for_diagnostics ( & self , tcx : TyCtxt < ' tcx > ) -> Option < & ' tcx [ u8 ] > {
123
+ let ( data, start, end) = match self {
124
+ ConstValue :: Scalar ( _) | ConstValue :: ZeroSized => {
125
+ bug ! ( "`try_get_slice_bytes` on non-slice constant" )
126
+ }
127
+ & ConstValue :: Slice { data, start, end } => ( data, start, end) ,
128
+ & ConstValue :: Indirect { alloc_id, offset } => {
129
+ // The reference itself is stored behind an indirection.
130
+ // Load the reference, and then load the actual slice contents.
131
+ let a = tcx. global_alloc ( alloc_id) . unwrap_memory ( ) . inner ( ) ;
132
+ let ptr_size = tcx. data_layout . pointer_size ;
133
+ if a. size ( ) < offset + 2 * ptr_size {
134
+ // (partially) dangling reference
135
+ return None ;
136
+ }
137
+ // Read the wide pointer components.
138
+ let ptr = a
139
+ . read_scalar (
140
+ & tcx,
141
+ alloc_range ( offset, ptr_size) ,
142
+ /* read_provenance */ true ,
143
+ )
144
+ . ok ( ) ?;
145
+ let ptr = ptr. to_pointer ( & tcx) . ok ( ) ?;
146
+ let len = a
147
+ . read_scalar (
148
+ & tcx,
149
+ alloc_range ( offset + ptr_size, ptr_size) ,
150
+ /* read_provenance */ false ,
151
+ )
152
+ . ok ( ) ?;
153
+ let len = len. to_target_usize ( & tcx) . ok ( ) ?;
154
+ let len: usize = len. try_into ( ) . ok ( ) ?;
155
+ if len == 0 {
156
+ return Some ( & [ ] ) ;
157
+ }
158
+ // Non-empty slice, must have memory. We know this is a relative pointer.
159
+ let ( inner_alloc_id, offset) = ptr. into_parts ( ) ;
160
+ let data = tcx. global_alloc ( inner_alloc_id?) . unwrap_memory ( ) ;
161
+ ( data, offset. bytes_usize ( ) , offset. bytes_usize ( ) + len)
162
+ }
163
+ } ;
164
+
165
+ // This is for diagnostics only, so we are okay to use `inspect_with_uninit_and_ptr_outside_interpreter`.
166
+ Some ( data. inner ( ) . inspect_with_uninit_and_ptr_outside_interpreter ( start..end) )
167
+ }
117
168
}
118
169
119
170
/// A `Scalar` represents an immediate, primitive value existing outside of a
0 commit comments