@@ -18,9 +18,9 @@ use super::{CanAccessStatics, CompileTimeEvalContext, CompileTimeInterpreter};
18
18
use crate :: errors;
19
19
use crate :: interpret:: eval_nullary_intrinsic;
20
20
use crate :: interpret:: {
21
- intern_const_alloc_recursive, Allocation , ConstAlloc , ConstValue , CtfeValidationMode , GlobalId ,
22
- Immediate , InternKind , InterpCx , InterpError , InterpResult , MPlaceTy , MemoryKind , OpTy ,
23
- RefTracking , StackPopCleanup ,
21
+ intern_const_alloc_recursive, ConstAlloc , ConstValue , CtfeValidationMode , GlobalId , Immediate ,
22
+ InternKind , InterpCx , InterpError , InterpResult , MPlaceTy , MemoryKind , OpTy , RefTracking ,
23
+ StackPopCleanup ,
24
24
} ;
25
25
26
26
// Returns a pointer to where the result lives
@@ -119,26 +119,17 @@ pub(super) fn op_to_const<'tcx>(
119
119
120
120
// We do not have value optimizations for everything.
121
121
// Only scalars and slices, since they are very common.
122
- let try_as_immediate = match op. layout . abi {
122
+ let force_as_immediate = match op. layout . abi {
123
123
Abi :: Scalar ( abi:: Scalar :: Initialized { .. } ) => true ,
124
- Abi :: ScalarPair ( ..) => match op. layout . ty . kind ( ) {
125
- ty:: Ref ( _, inner, _) => match * inner. kind ( ) {
126
- ty:: Slice ( elem) => elem == ecx. tcx . types . u8 ,
127
- ty:: Str => true ,
128
- _ => false ,
129
- } ,
130
- _ => false ,
131
- } ,
124
+ // We don't *force* `ConstValue::Slice` for `ScalarPair`. This has the advantage that if the
125
+ // input `op` is a place, then turning it into a `ConstValue` and back into a `OpTy` will
126
+ // not have to generate any duplicate allocations (we preserve the original `AllocId` in
127
+ // `ConstValue::Indirect`).
132
128
_ => false ,
133
129
} ;
134
- let immediate = if try_as_immediate {
130
+ let immediate = if force_as_immediate {
135
131
Right ( ecx. read_immediate ( op) . expect ( "normalization works on validated constants" ) )
136
132
} else {
137
- // It is guaranteed that any non-slice scalar pair is actually `Indirect` here.
138
- // When we come back from raw const eval, we are always by-ref. The only way our op here is
139
- // by-val is if we are in destructure_mir_constant, i.e., if this is (a field of) something that we
140
- // "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
141
- // structs containing such.
142
133
op. as_mplace_or_imm ( )
143
134
} ;
144
135
@@ -151,25 +142,22 @@ pub(super) fn op_to_const<'tcx>(
151
142
let alloc_id = alloc_id. expect ( "cannot have `fake` place fot non-ZST type" ) ;
152
143
ConstValue :: Indirect { alloc_id, offset }
153
144
}
154
- // see comment on `let try_as_immediate ` above
145
+ // see comment on `let force_as_immediate ` above
155
146
Right ( imm) => match * imm {
156
147
Immediate :: Scalar ( x) => ConstValue :: Scalar ( x) ,
157
148
Immediate :: ScalarPair ( a, b) => {
158
149
debug ! ( "ScalarPair(a: {:?}, b: {:?})" , a, b) ;
150
+ // FIXME: assert that this has an appropriate type.
151
+ // Currently we actually get here for non-[u8] slices during valtree construction!
152
+ let msg = "`op_to_const` on an immediate scalar pair must only be used on slice references to actually allocated memory" ;
159
153
// We know `offset` is relative to the allocation, so we can use `into_parts`.
160
- let ( data, start) = match a. to_pointer ( ecx) . unwrap ( ) . into_parts ( ) {
161
- ( Some ( alloc_id) , offset) => {
162
- ( ecx. tcx . global_alloc ( alloc_id) . unwrap_memory ( ) , offset. bytes ( ) )
163
- }
164
- ( None , _offset) => (
165
- ecx. tcx . mk_const_alloc ( Allocation :: from_bytes_byte_aligned_immutable (
166
- b"" as & [ u8 ] ,
167
- ) ) ,
168
- 0 ,
169
- ) ,
170
- } ;
171
- let len = b. to_target_usize ( ecx) . unwrap ( ) ;
172
- let start = start. try_into ( ) . unwrap ( ) ;
154
+ // We use `ConstValue::Slice` so that we don't have to generate an allocation for
155
+ // `ConstValue::Indirect` here.
156
+ let ( alloc_id, offset) = a. to_pointer ( ecx) . expect ( msg) . into_parts ( ) ;
157
+ let alloc_id = alloc_id. expect ( msg) ;
158
+ let data = ecx. tcx . global_alloc ( alloc_id) . unwrap_memory ( ) ;
159
+ let start = offset. bytes_usize ( ) ;
160
+ let len = b. to_target_usize ( ecx) . expect ( msg) ;
173
161
let len: usize = len. try_into ( ) . unwrap ( ) ;
174
162
ConstValue :: Slice { data, start, end : start + len }
175
163
}
0 commit comments