@@ -268,19 +268,27 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx
268
268
}
269
269
}
270
270
271
+ pub enum InternKind {
272
+ /// The `mutability` of the static, ignoring the type which may have interior mutability.
273
+ Static ( hir:: Mutability ) ,
274
+ Constant ,
275
+ Promoted ,
276
+ ConstProp ,
277
+ }
278
+
271
279
pub fn intern_const_alloc_recursive < M : CompileTimeMachine < ' mir , ' tcx > > (
272
280
ecx : & mut InterpCx < ' mir , ' tcx , M > ,
273
- // The `mutability` of the place, ignoring the type.
274
- place_mut : Option < hir:: Mutability > ,
281
+ intern_kind : InternKind ,
275
282
ret : MPlaceTy < ' tcx > ,
276
283
ignore_interior_mut_in_const_validation : bool ,
277
284
) -> InterpResult < ' tcx > {
278
285
let tcx = ecx. tcx ;
279
- let ( base_mutability, base_intern_mode) = match place_mut {
286
+ let ( base_mutability, base_intern_mode) = match intern_kind {
280
287
// `static mut` doesn't care about interior mutability, it's mutable anyway
281
- Some ( mutbl) => ( mutbl, InternMode :: Static ) ,
282
- // consts, promoteds. FIXME: what about array lengths, array initializers?
283
- None => ( Mutability :: Not , InternMode :: ConstBase ) ,
288
+ InternKind :: Static ( mutbl) => ( mutbl, InternMode :: Static ) ,
289
+ // FIXME: what about array lengths, array initializers?
290
+ InternKind :: Constant | InternKind :: ConstProp => ( Mutability :: Not , InternMode :: ConstBase ) ,
291
+ InternKind :: Promoted => ( Mutability :: Not , InternMode :: ConstBase ) ,
284
292
} ;
285
293
286
294
// Type based interning.
@@ -338,10 +346,23 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
338
346
// We can't call the `intern_shallow` method here, as its logic is tailored to safe
339
347
// references and a `leftover_allocations` set (where we only have a todo-list here).
340
348
// So we hand-roll the interning logic here again.
341
- match base_intern_mode {
342
- InternMode :: Static => { }
343
- InternMode :: Const | InternMode :: ConstBase => {
344
- // If it's not a static, it *must* be immutable.
349
+ match intern_kind {
350
+ // Mutable statics may contain mutable allocations even behind relocations
351
+ InternKind :: Static ( hir:: Mutability :: Mut ) => { }
352
+ // Once we get heap allocations we need to revisit whether immutable statics can
353
+ // refer to mutable (e.g. via interior mutability) allocations.
354
+ InternKind :: Static ( hir:: Mutability :: Not ) => {
355
+ alloc. mutability = Mutability :: Not ;
356
+ }
357
+ // Raw pointers in promoteds may only point to immutable things so we mark
358
+ // everything as immutable. Creating a promoted with interior mutability is UB, but
359
+ // there's no way we can check whether the user is using raw pointers correctly.
360
+ // So all we can do is mark this as immutable here.
361
+ InternKind :: Promoted => {
362
+ alloc. mutability = Mutability :: Not ;
363
+ }
364
+ InternKind :: Constant | InternKind :: ConstProp => {
365
+ // If it's a constant, it *must* be immutable.
345
366
// We cannot have mutable memory inside a constant.
346
367
// We use `delay_span_bug` here, because this can be reached in the presence
347
368
// of fancy transmutes.
@@ -363,7 +384,10 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
363
384
} else if ecx. memory . dead_alloc_map . contains_key ( & alloc_id) {
364
385
// dangling pointer
365
386
throw_unsup ! ( ValidationFailure ( "encountered dangling pointer in final constant" . into( ) ) )
366
- } else if ecx. tcx . alloc_map . lock ( ) . get ( alloc_id) . is_none ( ) {
387
+ } else if let Some ( _) = ecx. tcx . alloc_map . lock ( ) . get ( alloc_id) {
388
+ // FIXME: check if the allocation is ok as per the interning rules as if we interned
389
+ // it right here.
390
+ } else {
367
391
span_bug ! ( ecx. tcx. span, "encountered unknown alloc id {:?}" , alloc_id) ;
368
392
}
369
393
}
0 commit comments