1
1
use super :: { error_to_const_error, CompileTimeEvalContext , CompileTimeInterpreter , MemoryExtra } ;
2
2
use crate :: interpret:: eval_nullary_intrinsic;
3
3
use crate :: interpret:: {
4
- intern_const_alloc_recursive, Allocation , ConstValue , GlobalId , Immediate , InternKind ,
5
- InterpCx , InterpResult , MPlaceTy , MemoryKind , OpTy , RawConst , RefTracking , Scalar ,
6
- ScalarMaybeUndef , StackPopCleanup ,
4
+ intern_const_alloc_recursive, AllocId , Allocation , ConstValue , GlobalAlloc , GlobalId ,
5
+ Immediate , InternKind , InterpCx , InterpResult , MPlaceTy , MemoryKind , OpTy , RawConst ,
6
+ RefTracking , Scalar , ScalarMaybeUndef , StackPopCleanup ,
7
7
} ;
8
8
use rustc_hir:: def:: DefKind ;
9
9
use rustc_middle:: mir;
@@ -94,10 +94,13 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
94
94
)
95
95
}
96
96
97
- pub ( super ) fn op_to_const < ' tcx > (
97
+ #[ derive( Debug ) ]
98
+ pub ( super ) struct RefersToStatic ;
99
+
100
+ pub ( super ) fn try_op_to_const < ' tcx > (
98
101
ecx : & CompileTimeEvalContext < ' _ , ' tcx > ,
99
102
op : OpTy < ' tcx > ,
100
- ) -> ConstValue < ' tcx > {
103
+ ) -> Result < ConstValue < ' tcx > , RefersToStatic > {
101
104
// We do not have value optimizations for everything.
102
105
// Only scalars and slices, since they are very common.
103
106
// Note that further down we turn scalars of undefined bits back to `ByRef`. These can result
@@ -128,10 +131,16 @@ pub(super) fn op_to_const<'tcx>(
128
131
op. try_as_mplace ( ecx)
129
132
} ;
130
133
134
+ let alloc_map = ecx. tcx . alloc_map . lock ( ) ;
135
+ let try_unwrap_memory = |alloc_id : AllocId | match alloc_map. get ( alloc_id) {
136
+ Some ( GlobalAlloc :: Memory ( mem) ) => Ok ( mem) ,
137
+ Some ( GlobalAlloc :: Static ( _) ) => Err ( RefersToStatic ) ,
138
+ _ => bug ! ( "expected allocation ID {} to point to memory" , alloc_id) ,
139
+ } ;
131
140
let to_const_value = |mplace : MPlaceTy < ' _ > | match mplace. ptr {
132
141
Scalar :: Ptr ( ptr) => {
133
- let alloc = ecx . tcx . alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) ;
134
- ConstValue :: ByRef { alloc, offset : ptr. offset }
142
+ let alloc = try_unwrap_memory ( ptr. alloc_id ) ? ;
143
+ Ok ( ConstValue :: ByRef { alloc, offset : ptr. offset } )
135
144
}
136
145
Scalar :: Raw { data, .. } => {
137
146
assert ! ( mplace. layout. is_zst( ) ) ;
@@ -141,22 +150,20 @@ pub(super) fn op_to_const<'tcx>(
141
150
"this MPlaceTy must come from `try_as_mplace` being used on a zst, so we know what
142
151
value this integer address must have" ,
143
152
) ;
144
- ConstValue :: Scalar ( Scalar :: zst ( ) )
153
+ Ok ( ConstValue :: Scalar ( Scalar :: zst ( ) ) )
145
154
}
146
155
} ;
147
156
match immediate {
148
- Ok ( mplace) => to_const_value ( mplace) ,
157
+ Ok ( mplace) => Ok ( to_const_value ( mplace) ? ) ,
149
158
// see comment on `let try_as_immediate` above
150
159
Err ( imm) => match * imm {
151
160
Immediate :: Scalar ( x) => match x {
152
- ScalarMaybeUndef :: Scalar ( s) => ConstValue :: Scalar ( s) ,
153
- ScalarMaybeUndef :: Undef => to_const_value ( op. assert_mem_place ( ecx) ) ,
161
+ ScalarMaybeUndef :: Scalar ( s) => Ok ( ConstValue :: Scalar ( s) ) ,
162
+ ScalarMaybeUndef :: Undef => Ok ( to_const_value ( op. assert_mem_place ( ecx) ) ? ) ,
154
163
} ,
155
164
Immediate :: ScalarPair ( a, b) => {
156
165
let ( data, start) = match a. not_undef ( ) . unwrap ( ) {
157
- Scalar :: Ptr ( ptr) => {
158
- ( ecx. tcx . alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) , ptr. offset . bytes ( ) )
159
- }
166
+ Scalar :: Ptr ( ptr) => ( try_unwrap_memory ( ptr. alloc_id ) ?, ptr. offset . bytes ( ) ) ,
160
167
Scalar :: Raw { .. } => (
161
168
ecx. tcx
162
169
. intern_const_alloc ( Allocation :: from_byte_aligned_bytes ( b"" as & [ u8 ] ) ) ,
@@ -166,7 +173,7 @@ pub(super) fn op_to_const<'tcx>(
166
173
let len = b. to_machine_usize ( & ecx. tcx . tcx ) . unwrap ( ) ;
167
174
let start = start. try_into ( ) . unwrap ( ) ;
168
175
let len: usize = len. try_into ( ) . unwrap ( ) ;
169
- ConstValue :: Slice { data, start, end : start + len }
176
+ Ok ( ConstValue :: Slice { data, start, end : start + len } )
170
177
}
171
178
} ,
172
179
}
@@ -198,17 +205,20 @@ fn validate_and_turn_into_const<'tcx>(
198
205
}
199
206
}
200
207
// Now that we validated, turn this into a proper constant.
201
- // Statics/promoteds are always `ByRef`, for the rest `op_to_const` decides
202
- // whether they become immediates.
203
- if is_static || cid. promoted . is_some ( ) {
208
+ // Statics/promoteds are always `ByRef`, for the rest `try_op_to_const`
209
+ // decides whether they become immediates.
210
+ let value = if !is_static && !cid. promoted . is_some ( ) {
211
+ try_op_to_const ( & ecx, mplace. into ( ) )
212
+ } else {
213
+ Err ( RefersToStatic )
214
+ } ;
215
+ Ok ( value. unwrap_or_else ( |RefersToStatic | {
204
216
let ptr = mplace. ptr . assert_ptr ( ) ;
205
- Ok ( ConstValue :: ByRef {
217
+ ConstValue :: ByRef {
206
218
alloc : ecx. tcx . alloc_map . lock ( ) . unwrap_memory ( ptr. alloc_id ) ,
207
219
offset : ptr. offset ,
208
- } )
209
- } else {
210
- Ok ( op_to_const ( & ecx, mplace. into ( ) ) )
211
- }
220
+ }
221
+ } ) )
212
222
} ) ( ) ;
213
223
214
224
val. map_err ( |error| {
0 commit comments