@@ -7,7 +7,7 @@ use super::validity::RefTracking;
7
7
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
8
8
use rustc_hir as hir;
9
9
use rustc_middle:: mir:: interpret:: InterpResult ;
10
- use rustc_middle:: ty:: { self , layout:: TyAndLayout , query :: TyCtxtAt , Ty } ;
10
+ use rustc_middle:: ty:: { self , layout:: TyAndLayout , Ty } ;
11
11
use rustc_target:: abi:: Size ;
12
12
13
13
use rustc_ast:: Mutability ;
@@ -40,11 +40,6 @@ struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> {
40
40
/// This field stores whether we are *currently* inside an `UnsafeCell`. This can affect
41
41
/// the intern mode of references we encounter.
42
42
inside_unsafe_cell: bool ,
43
-
44
- /// This flag is to avoid triggering UnsafeCells are not allowed behind references in constants
45
- /// for promoteds.
46
- /// It's a copy of `mir::Body`'s ignore_interior_mut_in_const_validation field
47
- ignore_interior_mut_in_const: bool ,
48
43
}
49
44
50
45
#[ derive( Copy , Clone , Debug , PartialEq , Hash , Eq ) ]
@@ -53,22 +48,14 @@ enum InternMode {
53
48
/// this is *immutable*, and below mutable references inside an `UnsafeCell`, this
54
49
/// is *mutable*.
55
50
Static ( hir:: Mutability ) ,
56
- /// The "base value" of a const, which can have `UnsafeCell` (as in `const FOO: Cell<i32>`),
57
- /// but that interior mutability is simply ignored.
58
- ConstBase ,
59
- /// The "inner values" of a const with references, where `UnsafeCell` is an error.
60
- ConstInner ,
51
+ /// A `const`.
52
+ Const ,
61
53
}
62
54
63
55
/// Signalling data structure to ensure we don't recurse
64
56
/// into the memory of other constants or statics
65
57
struct IsStaticOrFn ;
66
58
67
- fn mutable_memory_in_const ( tcx : TyCtxtAt < ' _ > , kind : & str ) {
68
- // FIXME: show this in validation instead so we can point at where in the value the error is?
69
- tcx. sess . span_err ( tcx. span , & format ! ( "mutable memory ({}) is not allowed in constant" , kind) ) ;
70
- }
71
-
72
59
/// Intern an allocation without looking at its children.
73
60
/// `mode` is the mode of the environment where we found this pointer.
74
61
/// `mutablity` is the mutability of the place to be interned; even if that says
@@ -165,17 +152,13 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
165
152
mplace : MPlaceTy < ' tcx > ,
166
153
fields : impl Iterator < Item = InterpResult < ' tcx , Self :: V > > ,
167
154
) -> InterpResult < ' tcx > {
155
+ // ZSTs cannot contain pointers, so we can skip them.
156
+ if mplace. layout . is_zst ( ) {
157
+ return Ok ( ( ) ) ;
158
+ }
159
+
168
160
if let Some ( def) = mplace. layout . ty . ty_adt_def ( ) {
169
161
if Some ( def. did ) == self . ecx . tcx . lang_items ( ) . unsafe_cell_type ( ) {
170
- if self . mode == InternMode :: ConstInner && !self . ignore_interior_mut_in_const {
171
- // We do not actually make this memory mutable. But in case the user
172
- // *expected* it to be mutable, make sure we error. This is just a
173
- // sanity check to prevent users from accidentally exploiting the UB
174
- // they caused. It also helps us to find cases where const-checking
175
- // failed to prevent an `UnsafeCell` (but as `ignore_interior_mut_in_const`
176
- // shows that part is not airtight).
177
- //mutable_memory_in_const(self.ecx.tcx, "`UnsafeCell`");
178
- }
179
162
// We are crossing over an `UnsafeCell`, we can mutate again. This means that
180
163
// References we encounter inside here are interned as pointing to mutable
181
164
// allocations.
@@ -187,11 +170,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
187
170
}
188
171
}
189
172
190
- // ZSTs cannot contain pointers, so we can skip them.
191
- if mplace. layout . is_zst ( ) {
192
- return Ok ( ( ) ) ;
193
- }
194
-
195
173
self . walk_aggregate ( mplace, fields)
196
174
}
197
175
@@ -211,7 +189,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
211
189
if let Scalar :: Ptr ( vtable) = mplace. meta . unwrap_meta ( ) {
212
190
// Explicitly choose const mode here, since vtables are immutable, even
213
191
// if the reference of the fat pointer is mutable.
214
- self . intern_shallow ( vtable. alloc_id , InternMode :: ConstInner , None ) ;
192
+ self . intern_shallow ( vtable. alloc_id , InternMode :: Const , None ) ;
215
193
} else {
216
194
// Validation will error (with a better message) on an invalid vtable pointer.
217
195
// Let validation show the error message, but make sure it *does* error.
@@ -223,7 +201,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
223
201
// Only recurse for allocation-backed pointers.
224
202
if let Scalar :: Ptr ( ptr) = mplace. ptr {
225
203
// Compute the mode with which we intern this. Our goal here is to make as many
226
- // statics as we can immutable so they can be placed in const memory by LLVM.
204
+ // statics as we can immutable so they can be placed in read-only memory by LLVM.
227
205
let ref_mode = match self . mode {
228
206
InternMode :: Static ( mutbl) => {
229
207
// In statics, merge outer mutability with reference mutability and
@@ -257,27 +235,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
257
235
}
258
236
}
259
237
}
260
- InternMode :: ConstBase | InternMode :: ConstInner => {
261
- // Ignore `UnsafeCell`, everything is immutable. Do some sanity checking
262
- // for mutable references that we encounter -- they must all be ZST.
263
- // This helps to prevent users from accidentally exploiting UB that they
264
- // caused (by somehow getting a mutable reference in a `const`).
265
- if ref_mutability == Mutability :: Mut {
266
- /*match referenced_ty.kind() {
267
- ty::Array(_, n) if n.eval_usize(*tcx, self.ecx.param_env) == 0 => {}
268
- ty::Slice(_)
269
- if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)?
270
- == 0 => {}
271
- _ => mutable_memory_in_const(tcx, "`&mut`"),
272
- }*/
273
- } else {
274
- // A shared reference. We cannot check `freeze` here due to references
275
- // like `&dyn Trait` that are actually immutable. We do check for
276
- // concrete `UnsafeCell` when traversing the pointee though (if it is
277
- // a new allocation, not yet interned).
278
- }
279
- // Go on with the "inner" rules.
280
- InternMode :: ConstInner
238
+ InternMode :: Const => {
239
+ // Ignore `UnsafeCell`, everything is immutable. Validity does some sanity
240
+ // checking for mutable references that we encounter -- they must all be
241
+ // ZST.
242
+ InternMode :: Const
281
243
}
282
244
} ;
283
245
match self . intern_shallow ( ptr. alloc_id , ref_mode, Some ( referenced_ty) ) {
@@ -316,7 +278,6 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
316
278
ecx : & mut InterpCx < ' mir , ' tcx , M > ,
317
279
intern_kind : InternKind ,
318
280
ret : MPlaceTy < ' tcx > ,
319
- ignore_interior_mut_in_const : bool ,
320
281
) where
321
282
' tcx : ' mir ,
322
283
{
@@ -325,7 +286,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
325
286
InternKind :: Static ( mutbl) => InternMode :: Static ( mutbl) ,
326
287
// `Constant` includes array lengths.
327
288
// `Promoted` includes non-`Copy` array initializers and `rustc_args_required_const` arguments.
328
- InternKind :: Constant | InternKind :: Promoted => InternMode :: ConstBase ,
289
+ InternKind :: Constant | InternKind :: Promoted => InternMode :: Const ,
329
290
} ;
330
291
331
292
// Type based interning.
@@ -355,7 +316,6 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
355
316
ecx,
356
317
mode,
357
318
leftover_allocations,
358
- ignore_interior_mut_in_const,
359
319
inside_unsafe_cell : false ,
360
320
}
361
321
. visit_value ( mplace) ;
0 commit comments