Skip to content

Commit 10f439a

Browse files
committed
Promoteds can contain raw pointers, but these must still only point to immutable allocations
1 parent 632387f commit 10f439a

File tree

6 files changed

+56
-22
lines changed

6 files changed

+56
-22
lines changed

src/librustc_mir/const_eval.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc::ty::layout::VariantIdx;
55
use rustc::ty::{self, TyCtxt};
66
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
77

8-
use crate::interpret::{intern_const_alloc_recursive, ConstValue, InterpCx};
8+
use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx};
99

1010
mod error;
1111
mod eval_queries;
@@ -52,7 +52,7 @@ pub(crate) fn const_caller_location<'tcx>(
5252

5353
let loc_ty = tcx.caller_location_ty();
5454
let loc_place = ecx.alloc_caller_location(file, line, col);
55-
intern_const_alloc_recursive(&mut ecx, None, loc_place, false).unwrap();
55+
intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false).unwrap();
5656
let loc_const = ty::Const {
5757
ty: loc_ty,
5858
val: ty::ConstKind::Value(ConstValue::Scalar(loc_place.ptr.into())),

src/librustc_mir/const_eval/eval_queries.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use super::{error_to_const_error, CompileTimeEvalContext, CompileTimeInterpreter, MemoryExtra};
22
use crate::interpret::eval_nullary_intrinsic;
33
use crate::interpret::{
4-
intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, ImmTy, Immediate, InterpCx,
5-
InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar, ScalarMaybeUndef,
6-
StackPopCleanup,
4+
intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, ImmTy, Immediate, InternKind,
5+
InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar,
6+
ScalarMaybeUndef, StackPopCleanup,
77
};
88
use rustc::mir;
99
use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
@@ -56,9 +56,14 @@ fn eval_body_using_ecx<'mir, 'tcx>(
5656
ecx.run()?;
5757

5858
// Intern the result
59+
let intern_kind = match tcx.static_mutability(cid.instance.def_id()) {
60+
Some(m) => InternKind::Static(m),
61+
None if cid.promoted.is_some() => InternKind::Promoted,
62+
_ => InternKind::Constant,
63+
};
5964
intern_const_alloc_recursive(
6065
ecx,
61-
tcx.static_mutability(cid.instance.def_id()),
66+
intern_kind,
6267
ret,
6368
body.ignore_interior_mut_in_const_validation,
6469
)?;

src/librustc_mir/interpret/intern.rs

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -268,19 +268,27 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx
268268
}
269269
}
270270

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+
271279
pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
272280
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,
275282
ret: MPlaceTy<'tcx>,
276283
ignore_interior_mut_in_const_validation: bool,
277284
) -> InterpResult<'tcx> {
278285
let tcx = ecx.tcx;
279-
let (base_mutability, base_intern_mode) = match place_mut {
286+
let (base_mutability, base_intern_mode) = match intern_kind {
280287
// `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),
284292
};
285293

286294
// Type based interning.
@@ -338,10 +346,23 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
338346
// We can't call the `intern_shallow` method here, as its logic is tailored to safe
339347
// references and a `leftover_allocations` set (where we only have a todo-list here).
340348
// 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.
345366
// We cannot have mutable memory inside a constant.
346367
// We use `delay_span_bug` here, because this can be reached in the presence
347368
// of fancy transmutes.
@@ -363,7 +384,10 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
363384
} else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
364385
// dangling pointer
365386
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 {
367391
span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id);
368392
}
369393
}

src/librustc_mir/interpret/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ pub use self::visitor::{MutValueVisitor, ValueVisitor};
3232

3333
pub use self::validity::RefTracking;
3434

35-
pub use self::intern::intern_const_alloc_recursive;
35+
pub use self::intern::{intern_const_alloc_recursive, InternKind};
3636

3737
crate use self::intrinsics::eval_nullary_intrinsic;

src/librustc_mir/transform/const_prop.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ use syntax::ast::Mutability;
2929

3030
use crate::const_eval::error_to_const_error;
3131
use crate::interpret::{
32-
self, intern_const_alloc_recursive, AllocId, Allocation, Frame, ImmTy, Immediate, InterpCx,
33-
LocalState, LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer,
34-
ScalarMaybeUndef, StackPopCleanup,
32+
self, intern_const_alloc_recursive, AllocId, Allocation, Frame, ImmTy, Immediate, InternKind,
33+
InterpCx, LocalState, LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy,
34+
Pointer, ScalarMaybeUndef, StackPopCleanup,
3535
};
3636
use crate::transform::{MirPass, MirSource};
3737

@@ -726,7 +726,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
726726
)) => l.is_bits() && r.is_bits(),
727727
interpret::Operand::Indirect(_) if mir_opt_level >= 2 => {
728728
let mplace = op.assert_mem_place(&self.ecx);
729-
intern_const_alloc_recursive(&mut self.ecx, None, mplace, false)
729+
intern_const_alloc_recursive(&mut self.ecx, InternKind::ConstProp, mplace, false)
730730
.expect("failed to intern alloc");
731731
true
732732
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// check-pass
2+
3+
pub const FOO: &'static *const i32 = &(&0 as _);
4+
5+
fn main() {}

0 commit comments

Comments
 (0)