1
Fork 0

unstably allow constants to refer to statics and read from immutable statics

This commit is contained in:
Ralf Jung 2024-01-05 12:18:11 +01:00
parent 5f40394baa
commit 4e77e368eb
50 changed files with 548 additions and 530 deletions

View file

@ -30,7 +30,9 @@ const_eval_closure_non_const =
cannot call non-const closure in {const_eval_const_context}s
const_eval_consider_dereferencing =
consider dereferencing here
const_eval_const_accesses_static = constant accesses static
const_eval_const_accesses_mut_global =
constant accesses mutable global memory
const_eval_const_context = {$kind ->
[const] constant
@ -213,6 +215,9 @@ const_eval_modified_global =
const_eval_mut_deref =
mutation through a reference is not allowed in {const_eval_const_context}s
const_eval_mutable_data_in_const =
constant refers to mutable data
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
const_eval_non_const_fmt_macro_call =
@ -319,12 +324,6 @@ const_eval_size_overflow =
const_eval_stack_frame_limit_reached =
reached the configured maximum number of stack frames
const_eval_static_access =
{const_eval_const_context}s cannot refer to statics
.help = consider extracting the value of the `static` to a `const`, and referring to that
.teach_note = `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable.
.teach_help = To fix this, the value can be extracted to a `const` and then used.
const_eval_thread_local_access =
thread-local statics cannot be accessed at compile-time

View file

@ -17,7 +17,7 @@ use crate::interpret::{ErrorHandled, InterpError, InterpErrorInfo, MachineStopTy
/// The CTFE machine has some custom error kinds.
#[derive(Clone, Debug)]
pub enum ConstEvalErrKind {
ConstAccessesStatic,
ConstAccessesMutGlobal,
ModifiedGlobal,
AssertFailure(AssertKind<ConstInt>),
Panic { msg: Symbol, line: u32, col: u32, file: Symbol },
@ -28,7 +28,7 @@ impl MachineStopType for ConstEvalErrKind {
use crate::fluent_generated::*;
use ConstEvalErrKind::*;
match self {
ConstAccessesStatic => const_eval_const_accesses_static,
ConstAccessesMutGlobal => const_eval_const_accesses_mut_global,
ModifiedGlobal => const_eval_modified_global,
Panic { .. } => const_eval_panic,
AssertFailure(x) => x.diagnostic_message(),
@ -37,7 +37,7 @@ impl MachineStopType for ConstEvalErrKind {
fn add_args(self: Box<Self>, adder: &mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue)) {
use ConstEvalErrKind::*;
match *self {
ConstAccessesStatic | ModifiedGlobal => {}
ConstAccessesMutGlobal | ModifiedGlobal => {}
AssertFailure(kind) => kind.add_args(adder),
Panic { msg, line, col, file } => {
adder("msg".into(), msg.into_diagnostic_arg());

View file

@ -11,7 +11,7 @@ use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Span;
use rustc_target::abi::{self, Abi};
use super::{CanAccessStatics, CompileTimeEvalContext, CompileTimeInterpreter};
use super::{CanAccessMutGlobal, CompileTimeEvalContext, CompileTimeInterpreter};
use crate::const_eval::CheckAlignment;
use crate::errors;
use crate::errors::ConstEvalError;
@ -90,14 +90,14 @@ pub(crate) fn mk_eval_cx<'mir, 'tcx>(
tcx: TyCtxt<'tcx>,
root_span: Span,
param_env: ty::ParamEnv<'tcx>,
can_access_statics: CanAccessStatics,
can_access_mut_global: CanAccessMutGlobal,
) -> CompileTimeEvalContext<'mir, 'tcx> {
debug!("mk_eval_cx: {:?}", param_env);
InterpCx::new(
tcx,
root_span,
param_env,
CompileTimeInterpreter::new(can_access_statics, CheckAlignment::No),
CompileTimeInterpreter::new(can_access_mut_global, CheckAlignment::No),
)
}
@ -200,7 +200,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
tcx,
tcx.def_span(key.value.instance.def_id()),
key.param_env,
CanAccessStatics::from(is_static),
CanAccessMutGlobal::from(is_static),
);
let mplace = ecx.raw_const_to_mplace(constant).expect(
@ -277,9 +277,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
tcx,
tcx.def_span(def),
key.param_env,
// Statics (and promoteds inside statics) may access other statics, because unlike consts
// Statics (and promoteds inside statics) may access mutable global memory, because unlike consts
// they do not have to behave "as if" they were evaluated at runtime.
CompileTimeInterpreter::new(CanAccessStatics::from(is_static), CheckAlignment::Error),
// For consts however we want to ensure they behave "as if" they were evaluated at runtime,
// so we have to reject reading mutable global memory.
CompileTimeInterpreter::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
);
eval_in_interpreter(ecx, cid, is_static)
}

View file

@ -51,13 +51,10 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
/// The virtual call stack.
pub(super) stack: Vec<Frame<'mir, 'tcx>>,
/// We need to make sure consts never point to anything mutable, even recursively. That is
/// relied on for pattern matching on consts with references.
/// To achieve this, two pieces have to work together:
/// * Interning makes everything outside of statics immutable.
/// * Pointers to allocations inside of statics can never leak outside, to a non-static global.
/// This boolean here controls the second part.
pub(super) can_access_statics: CanAccessStatics,
/// Pattern matching on consts with references would be unsound if those references
/// could point to anything mutable. Therefore, when evaluating consts and when constructing valtrees,
/// we ensure that only immutable global memory can be accessed.
pub(super) can_access_mut_global: CanAccessMutGlobal,
/// Whether to check alignment during evaluation.
pub(super) check_alignment: CheckAlignment,
@ -73,12 +70,12 @@ pub enum CheckAlignment {
}
#[derive(Copy, Clone, PartialEq)]
pub(crate) enum CanAccessStatics {
pub(crate) enum CanAccessMutGlobal {
No,
Yes,
}
impl From<bool> for CanAccessStatics {
impl From<bool> for CanAccessMutGlobal {
fn from(value: bool) -> Self {
if value { Self::Yes } else { Self::No }
}
@ -86,13 +83,13 @@ impl From<bool> for CanAccessStatics {
impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
pub(crate) fn new(
can_access_statics: CanAccessStatics,
can_access_mut_global: CanAccessMutGlobal,
check_alignment: CheckAlignment,
) -> Self {
CompileTimeInterpreter {
num_evaluated_steps: 0,
stack: Vec::new(),
can_access_statics,
can_access_mut_global,
check_alignment,
}
}
@ -680,7 +677,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
machine: &Self,
alloc_id: AllocId,
alloc: ConstAllocation<'tcx>,
static_def_id: Option<DefId>,
_static_def_id: Option<DefId>,
is_write: bool,
) -> InterpResult<'tcx> {
let alloc = alloc.inner();
@ -692,22 +689,15 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
}
} else {
// Read access. These are usually allowed, with some exceptions.
if machine.can_access_statics == CanAccessStatics::Yes {
if machine.can_access_mut_global == CanAccessMutGlobal::Yes {
// Machine configuration allows us read from anything (e.g., `static` initializer).
Ok(())
} else if static_def_id.is_some() {
// Machine configuration does not allow us to read statics
// (e.g., `const` initializer).
// See const_eval::machine::MemoryExtra::can_access_statics for why
// this check is so important: if we could read statics, we could read pointers
// to mutable allocations *inside* statics. These allocations are not themselves
// statics, so pointers to them can get around the check in `validity.rs`.
Err(ConstEvalErrKind::ConstAccessesStatic.into())
} else if alloc.mutability == Mutability::Mut {
// Machine configuration does not allow us to read statics (e.g., `const`
// initializer).
Err(ConstEvalErrKind::ConstAccessesMutGlobal.into())
} else {
// Immutable global, this read is fine.
// But make sure we never accept a read from something mutable, that would be
// unsound. The reason is that as the content of this allocation may be different
// now and at run-time, so if we permit reading now we might return the wrong value.
assert_eq!(alloc.mutability, Mutability::Not);
Ok(())
}

View file

@ -1,12 +1,10 @@
// Not in interpret to make sure we do not use private implementation details
use crate::errors::MaxNumNodesInConstErr;
use crate::interpret::InterpCx;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::mir::interpret::{InterpError, InterpErrorInfo};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::DUMMY_SP;
use rustc_middle::ty::{self, Ty};
mod error;
mod eval_queries;
@ -18,55 +16,32 @@ pub use error::*;
pub use eval_queries::*;
pub use fn_queries::*;
pub use machine::*;
pub(crate) use valtrees::{const_to_valtree_inner, valtree_to_const_value};
pub(crate) use valtrees::{eval_to_valtree, valtree_to_const_value};
// We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
const VALTREE_MAX_NODES: usize = 100000;
pub(crate) enum ValTreeCreationError {
NodesOverflow,
/// Values of this type, or this particular value, are not supported as valtrees.
NonSupportedType,
/// The value pointed to non-read-only memory, so we cannot make it a valtree.
NotReadOnly,
Other,
}
pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>;
/// Evaluates a constant and turns it into a type-level constant value.
pub(crate) fn eval_to_valtree<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
cid: GlobalId<'tcx>,
) -> EvalToValTreeResult<'tcx> {
let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?;
// FIXME Need to provide a span to `eval_to_valtree`
let ecx = mk_eval_cx(
tcx,
DUMMY_SP,
param_env,
// It is absolutely crucial for soundness that
// we do not read from static items or other mutable memory.
CanAccessStatics::No,
);
let place = ecx.raw_const_to_mplace(const_alloc).unwrap();
debug!(?place);
let mut num_nodes = 0;
let valtree_result = const_to_valtree_inner(&ecx, &place, &mut num_nodes);
match valtree_result {
Ok(valtree) => Ok(Some(valtree)),
Err(err) => {
let did = cid.instance.def_id();
let global_const_id = cid.display(tcx);
match err {
ValTreeCreationError::NodesOverflow => {
let span = tcx.hir().span_if_local(did);
tcx.dcx().emit_err(MaxNumNodesInConstErr { span, global_const_id });
Ok(None)
impl From<InterpErrorInfo<'_>> for ValTreeCreationError {
fn from(err: InterpErrorInfo<'_>) -> Self {
match err.kind() {
InterpError::MachineStop(err) => {
let err = err.downcast_ref::<ConstEvalErrKind>().unwrap();
match err {
ConstEvalErrKind::ConstAccessesMutGlobal => ValTreeCreationError::NotReadOnly,
_ => ValTreeCreationError::Other,
}
ValTreeCreationError::NonSupportedType | ValTreeCreationError::Other => Ok(None),
}
_ => ValTreeCreationError::Other,
}
}
}
@ -78,7 +53,7 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
ty: Ty<'tcx>,
) -> Option<mir::DestructuredConstant<'tcx>> {
let param_env = ty::ParamEnv::reveal_all();
let ecx = mk_eval_cx(tcx.tcx, tcx.span, param_env, CanAccessStatics::No);
let ecx = mk_eval_cx(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No);
let op = ecx.const_val_to_op(val, ty, None).ok()?;
// We go to `usize` as we cannot allocate anything bigger anyway.

View file

@ -1,17 +1,20 @@
use rustc_middle::mir;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
use rustc_span::DUMMY_SP;
use rustc_target::abi::{Abi, VariantIdx};
use super::eval_queries::{mk_eval_cx, op_to_const};
use super::machine::CompileTimeEvalContext;
use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
use crate::const_eval::CanAccessStatics;
use crate::const_eval::CanAccessMutGlobal;
use crate::errors::{MaxNumNodesInConstErr, MutableDataInConstErr};
use crate::interpret::MPlaceTy;
use crate::interpret::{
intern_const_alloc_recursive, ImmTy, Immediate, InternKind, MemPlaceMeta, MemoryKind, PlaceTy,
Projectable, Scalar,
};
use rustc_middle::mir;
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
use rustc_span::DUMMY_SP;
use rustc_target::abi::{Abi, VariantIdx};
#[instrument(skip(ecx), level = "debug")]
fn branches<'tcx>(
@ -70,7 +73,7 @@ fn slice_branches<'tcx>(
}
#[instrument(skip(ecx), level = "debug")]
pub(crate) fn const_to_valtree_inner<'tcx>(
fn const_to_valtree_inner<'tcx>(
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
place: &MPlaceTy<'tcx>,
num_nodes: &mut usize,
@ -88,9 +91,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
Ok(ty::ValTree::zst())
}
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
let Ok(val) = ecx.read_immediate(place) else {
return Err(ValTreeCreationError::Other);
};
let val = ecx.read_immediate(place)?;
let val = val.to_scalar();
*num_nodes += 1;
@ -102,19 +103,17 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
// equality at compile-time (see `ptr_guaranteed_cmp`).
// However we allow those that are just integers in disguise.
// First, get the pointer. Remember it might be wide!
let Ok(val) = ecx.read_immediate(place) else {
return Err(ValTreeCreationError::Other);
};
let val = ecx.read_immediate(place)?;
// We could allow wide raw pointers where both sides are integers in the future,
// but for now we reject them.
if matches!(val.layout.abi, Abi::ScalarPair(..)) {
return Err(ValTreeCreationError::Other);
return Err(ValTreeCreationError::NonSupportedType);
}
let val = val.to_scalar();
// We are in the CTFE machine, so ptr-to-int casts will fail.
// This can only be `Ok` if `val` already is an integer.
let Ok(val) = val.try_to_int() else {
return Err(ValTreeCreationError::Other);
return Err(ValTreeCreationError::NonSupportedType);
};
// It's just a ScalarInt!
Ok(ty::ValTree::Leaf(val))
@ -125,11 +124,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
ty::FnPtr(_) => Err(ValTreeCreationError::NonSupportedType),
ty::Ref(_, _, _) => {
let Ok(derefd_place)= ecx.deref_pointer(place) else {
return Err(ValTreeCreationError::Other);
};
debug!(?derefd_place);
let derefd_place = ecx.deref_pointer(place)?;
const_to_valtree_inner(ecx, &derefd_place, num_nodes)
}
@ -153,9 +148,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
bug!("uninhabited types should have errored and never gotten converted to valtree")
}
let Ok(variant) = ecx.read_discriminant(place) else {
return Err(ValTreeCreationError::Other);
};
let variant = ecx.read_discriminant(place)?;
branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes)
}
@ -221,6 +214,59 @@ fn create_valtree_place<'tcx>(
ecx.allocate_dyn(layout, MemoryKind::Stack, meta).unwrap()
}
/// Evaluates a constant and turns it into a type-level constant value.
pub(crate) fn eval_to_valtree<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
cid: GlobalId<'tcx>,
) -> EvalToValTreeResult<'tcx> {
let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?;
// FIXME Need to provide a span to `eval_to_valtree`
let ecx = mk_eval_cx(
tcx,
DUMMY_SP,
param_env,
// It is absolutely crucial for soundness that
// we do not read from mutable memory.
CanAccessMutGlobal::No,
);
let place = ecx.raw_const_to_mplace(const_alloc).unwrap();
debug!(?place);
let mut num_nodes = 0;
let valtree_result = const_to_valtree_inner(&ecx, &place, &mut num_nodes);
match valtree_result {
Ok(valtree) => Ok(Some(valtree)),
Err(err) => {
let did = cid.instance.def_id();
let global_const_id = cid.display(tcx);
let span = tcx.hir().span_if_local(did);
match err {
ValTreeCreationError::NodesOverflow => {
let handled =
tcx.dcx().emit_err(MaxNumNodesInConstErr { span, global_const_id });
Err(handled.into())
}
ValTreeCreationError::NotReadOnly => {
let handled =
tcx.dcx().emit_err(MutableDataInConstErr { span, global_const_id });
Err(handled.into())
}
ValTreeCreationError::Other => {
let handled = tcx.dcx().span_delayed_bug(
span.unwrap_or(DUMMY_SP),
"unexpected error during valtree construction",
);
Err(handled.into())
}
ValTreeCreationError::NonSupportedType => Ok(None),
}
}
}
}
/// Converts a `ValTree` to a `ConstValue`, which is needed after mir
/// construction has finished.
// FIXME Merge `valtree_to_const_value` and `valtree_into_mplace` into one function
@ -253,7 +299,7 @@ pub fn valtree_to_const_value<'tcx>(
}
}
ty::Ref(_, inner_ty, _) => {
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No);
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
let imm = valtree_to_ref(&mut ecx, valtree, *inner_ty);
let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap());
op_to_const(&ecx, &imm.into(), /* for diagnostics */ false)
@ -280,7 +326,7 @@ pub fn valtree_to_const_value<'tcx>(
bug!("could not find non-ZST field during in {layout:#?}");
}
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No);
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No);
// Need to create a place for this valtree.
let place = create_valtree_place(&mut ecx, layout, valtree);

View file

@ -56,23 +56,11 @@ pub(crate) struct UnstableInStable {
#[derive(Diagnostic)]
#[diag(const_eval_thread_local_access, code = E0625)]
pub(crate) struct NonConstOpErr {
pub(crate) struct ThreadLocalAccessErr {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(const_eval_static_access, code = E0013)]
#[help]
pub(crate) struct StaticAccessErr {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
#[note(const_eval_teach_note)]
#[help(const_eval_teach_help)]
pub teach: Option<()>,
}
#[derive(Diagnostic)]
#[diag(const_eval_raw_ptr_to_int)]
#[note]
@ -129,6 +117,14 @@ pub(crate) struct MaxNumNodesInConstErr {
pub global_const_id: String,
}
#[derive(Diagnostic)]
#[diag(const_eval_mutable_data_in_const)]
pub(crate) struct MutableDataInConstErr {
#[primary_span]
pub span: Option<Span>,
pub global_const_id: String,
}
#[derive(Diagnostic)]
#[diag(const_eval_unallowed_fn_pointer_call)]
pub(crate) struct UnallowedFnPointerCall {

View file

@ -132,7 +132,6 @@ pub enum CtfeValidationMode {
/// `allow_immutable_unsafe_cell` says whether we allow `UnsafeCell` in immutable memory (which is the
/// case for the top-level allocation of a `const`, where this is fine because the allocation will be
/// copied at each use site).
/// `allow_static_ptrs` says if pointers to statics are permitted (which is the case for promoteds in statics).
Const { allow_immutable_unsafe_cell: bool, allow_static_ptrs: bool },
}
@ -146,13 +145,6 @@ impl CtfeValidationMode {
}
}
fn allow_static_ptrs(self) -> bool {
match self {
CtfeValidationMode::Static { .. } => true, // statics can point to statics
CtfeValidationMode::Const { allow_static_ptrs, .. } => allow_static_ptrs,
}
}
fn may_contain_mutable_ref(self) -> bool {
match self {
CtfeValidationMode::Static { mutbl } => mutbl == Mutability::Mut,
@ -468,13 +460,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// Special handling for pointers to statics (irrespective of their type).
assert!(!self.ecx.tcx.is_thread_local_static(did));
assert!(self.ecx.tcx.is_static(did));
if self.ctfe_mode.is_some_and(|c| !c.allow_static_ptrs()) {
// See const_eval::machine::MemoryExtra::can_access_statics for why
// this check is so important.
// This check is reachable when the const just referenced the static,
// but never read it (so we never entered `before_access_global`).
throw_validation_failure!(self.path, PtrToStatic { ptr_kind });
}
// Mutability check.
if ptr_expected_mutbl == Mutability::Mut {
if matches!(

View file

@ -580,16 +580,21 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
if let hir::ConstContext::Static(_) = ccx.const_kind() {
Status::Allowed
} else {
Status::Forbidden
Status::Unstable(sym::const_refs_to_static)
}
}
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.dcx().create_err(errors::StaticAccessErr {
let mut err = feature_err(
&ccx.tcx.sess,
sym::const_refs_to_static,
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(E0013).then_some(()),
})
format!("referencing statics in {}s is unstable", ccx.const_kind(),),
);
err
.note("`static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable.")
.help("to fix this, the value can be extracted to a `const` and then used.");
err
}
}
@ -598,7 +603,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
pub struct ThreadLocalAccess;
impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.dcx().create_err(errors::NonConstOpErr { span })
ccx.dcx().create_err(errors::ThreadLocalAccessErr { span })
}
}

View file

@ -6,7 +6,7 @@ use rustc_middle::ty::layout::LayoutOf;
use rustc_span::symbol::Symbol;
use rustc_type_ir::Mutability;
use crate::const_eval::{mk_eval_cx, CanAccessStatics, CompileTimeEvalContext};
use crate::const_eval::{mk_eval_cx, CanAccessMutGlobal, CompileTimeEvalContext};
use crate::interpret::*;
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
@ -57,7 +57,7 @@ pub(crate) fn const_caller_location_provider(
col: u32,
) -> mir::ConstValue<'_> {
trace!("const_caller_location: {}:{}:{}", file, line, col);
let mut ecx = mk_eval_cx(tcx.tcx, tcx.span, ty::ParamEnv::reveal_all(), CanAccessStatics::No);
let mut ecx = mk_eval_cx(tcx.tcx, tcx.span, ty::ParamEnv::reveal_all(), CanAccessMutGlobal::No);
let loc_place = alloc_caller_location(&mut ecx, file, line, col);
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {

View file

@ -2,7 +2,7 @@ use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, Val
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
use crate::const_eval::{CanAccessStatics, CheckAlignment, CompileTimeInterpreter};
use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeInterpreter};
use crate::interpret::{InterpCx, MemoryKind, OpTy};
/// Determines if this type permits "raw" initialization by just transmuting some memory into an
@ -44,7 +44,7 @@ fn might_permit_raw_init_strict<'tcx>(
tcx: TyCtxt<'tcx>,
kind: ValidityRequirement,
) -> Result<bool, &'tcx LayoutError<'tcx>> {
let machine = CompileTimeInterpreter::new(CanAccessStatics::No, CheckAlignment::Error);
let machine = CompileTimeInterpreter::new(CanAccessMutGlobal::No, CheckAlignment::Error);
let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);