Skip to content

Commit 97cae9c

Browse files
committed
promoteds in statics may refer to statics
1 parent 06ca7b7 commit 97cae9c

File tree

2 files changed

+18
-10
lines changed

2 files changed

+18
-10
lines changed

compiler/rustc_mir/src/const_eval/eval_queries.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,12 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
387387
let mut inner = false;
388388
while let Some((mplace, path)) = ref_tracking.todo.pop() {
389389
let mode = match tcx.static_mutability(cid.instance.def_id()) {
390-
Some(_) if cid.promoted.is_none() => CtfeValidationMode::Regular, // a `static`
391-
_ => CtfeValidationMode::Const { inner },
390+
Some(_) if cid.promoted.is_some() => {
391+
// Promoteds in statics are allowed to point to statics.
392+
CtfeValidationMode::Const { inner, allow_static_ptrs: true }
393+
}
394+
Some(_) => CtfeValidationMode::Regular, // a `static`
395+
None => CtfeValidationMode::Const { inner, allow_static_ptrs: false },
392396
};
393397
ecx.const_validate_operand(mplace.into(), path, &mut ref_tracking, mode)?;
394398
inner = true;

compiler/rustc_mir/src/interpret/validity.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,12 @@ pub enum PathElem {
117117
pub enum CtfeValidationMode {
118118
/// Regular validation, nothing special happening.
119119
Regular,
120-
/// Validation of a `const`. `inner` says if this is an inner, indirect allocation (as opposed
121-
/// to the top-level const allocation).
122-
/// Being an inner allocation makes a difference because the top-level allocation of a `const`
123-
/// is copied for each use, but the inner allocations are implicitly shared.
124-
Const { inner: bool },
120+
/// Validation of a `const`.
121+
/// `inner` says if this is an inner, indirect allocation (as opposed to the top-level const
122+
/// allocation). Being an inner allocation makes a difference because the top-level allocation
123+
/// of a `const` is copied for each use, but the inner allocations are implicitly shared.
124+
/// `allow_static_ptrs` says if pointers to statics are permitted (which is the case for promoteds in statics).
125+
Const { inner: bool, allow_static_ptrs: bool },
125126
}
126127

127128
/// State for tracking recursive validation of references
@@ -437,7 +438,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
437438
if let Some(GlobalAlloc::Static(did)) = alloc_kind {
438439
assert!(!self.ecx.tcx.is_thread_local_static(did));
439440
assert!(self.ecx.tcx.is_static(did));
440-
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) {
441+
if matches!(
442+
self.ctfe_mode,
443+
Some(CtfeValidationMode::Const { allow_static_ptrs: false, .. })
444+
) {
441445
// See const_eval::machine::MemoryExtra::can_access_statics for why
442446
// this check is so important.
443447
// This check is reachable when the const just referenced the static,
@@ -742,9 +746,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
742746
// Sanity check: `builtin_deref` does not know any pointers that are not primitive.
743747
assert!(op.layout.ty.builtin_deref(true).is_none());
744748

745-
// Special check preventing `UnsafeCell` in constants
749+
// Special check preventing `UnsafeCell` in the inner part of constants
746750
if let Some(def) = op.layout.ty.ty_adt_def() {
747-
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true }))
751+
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. }))
748752
&& Some(def.did) == self.ecx.tcx.lang_items().unsafe_cell_type()
749753
{
750754
throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" });

0 commit comments

Comments
 (0)