See the following snippet: (currently ICEs)
#![feature(core_intrinsics)]
#![feature(const_heap)]
use std::mem::{align_of, size_of};
use std::intrinsics;
struct SelfReferential {
me: *const SelfReferential,
}
const Y: &'static SelfReferential = unsafe {
let size = size_of::<SelfReferential>();
let align = align_of::<SelfReferential>();
let ptr_raw = intrinsics::const_allocate(size, align);
let ptr = ptr_raw as *mut SelfReferential;
let me_addr = &raw mut (*ptr).me;
*me_addr = ptr;
intrinsics::const_make_global(ptr_raw, size, align);
&*ptr
};
fn main() {}
me's provenance says it wasn't derived from an immutable reference. We can't really change that because it can't be mutated after we call const_make_global.
- The fact above hits "accepted a mutable pointer that should not have accepted" at
|
// Ensure that this is derived from a shared reference. Crucially, we check this *before* |
|
// checking whether the `alloc_id` has already been interned. The point of this check is to |
|
// ensure that when there are multiple pointers to the same allocation, they are *all* |
|
// derived from a shared reference. Therefore it would be bad if we only checked the first |
|
// pointer to any given allocation. |
|
// (It is likely not possible to actually have multiple pointers to the same allocation, |
|
// so alternatively we could also check that and ICE if there are multiple such pointers.) |
|
// See <https://github.com/rust-lang/rust/pull/128543> for why we are checking for "shared |
|
// reference" and not "immutable", i.e., for why we are allowing interior-mutable shared |
|
// references: they can actually be created in safe code while pointing to apparently |
|
// "immutable" values, via promotion or tail expression lifetime extension of |
|
// `&None::<Cell<T>>`. |
|
// We also exclude promoteds from this as `&mut []` can be promoted, which is a mutable |
|
// reference pointing to an immutable (zero-sized) allocation. We rely on the promotion |
|
// analysis not screwing up to ensure that it is sound to intern promoteds as immutable. |
|
if intern_kind != InternKind::Promoted |
|
&& inner_mutability == Mutability::Not |
|
&& !prov.shared_ref() |
|
{ |
- We can check if
alloc_id has kind Heap { was_made_immut: true } and skip the error that way.
intern_shallow will keep returning alloc2 adding to our todo list being weird left and right. I added a .filter in
|
match intern_shallow(ecx, alloc_id, inner_mutability, Some(&mut disambiguator)) { |
|
Ok(nested) => todo.extend(nested), |
to skip provs that are in just_interned.
- Apparently that wasn't enough and rustc hits an infinite loop at some point. The stack trace isn't helpful enough and I didn't have enough time to find a way to debug the stack overflow.
Originally posted by @fee1-dead in #143595 (comment)
See the following snippet: (currently ICEs)
me's provenance says it wasn't derived from an immutable reference. We can't really change that because it can't be mutated after we callconst_make_global.rust/compiler/rustc_const_eval/src/interpret/intern.rs
Lines 247 to 265 in 040e2f8
alloc_idhas kindHeap { was_made_immut: true }and skip the error that way.intern_shallowwill keep returning alloc2 adding to our todo list being weird left and right. I added a.filterinrust/compiler/rustc_const_eval/src/interpret/intern.rs
Lines 311 to 312 in 040e2f8
just_interned.Originally posted by @fee1-dead in #143595 (comment)