Description
If a const
(item or expression) contains references and pointers, then what is their mutability (or more generally, their status in the aliasing model)?
It seems fairly clear that we want them to be immutable. It's called "const(ant)" after all, and also constants are values but we deduplicate the underlying storage, which would be bad news if anything is mutable.
Currently we're doing our best to make this an implementation detail: const-eval tracks the actual mutability of a pointer, and interning bails out if a mutable pointer makes it into the final value. That means all the pointers in the final value are anyway already immutable.
But there's an alternative: we can say that the transition from a const result to a value embedded in other computations (that may themselves be const computations, or they may happen at runtime) makes all pointers (or, equivalently, the memory they point to) immutable.
This has several advantages:
- regression: encountered mutable pointer in final value when "outer scope" rule applies in const/static with interior mutability rust#121610 is resolved, since we could just remove the check that triggers the regression.
- Promotion introduces UB into otherwise well-defined code #493 has a path forward, if we can figure out how to do an edition transition where the problematic promoteds are turned into inline const expressions.
const_allocate
results can more easily be used to create constants without running into issues like this.
It also has several downsides:
- We have a second source of immutability constraints, aside from shared references. So if people don't expect that they may cause UB. (A mitigating factor here is that writing to the memory that contains a const should segfault pretty reliably on most targets, as that memory is typically mapped read-only. So this UB will often be detected.)
- The check we'd have to remove was meant as a safety net for
&mut
values in consts. If an&mut
value ends up in the result of a const, the new rules would say that despite it being a mutable reference, it actually is an immutable pointer. We can catch some cases where that happens, but if people get creative and e.g. smuggle out an&mut
inside aMaybeUninit
, there's a chance to cause UB.
The downsides are why I added these checks in the first place, and they make me hesitant to un-do all that work. OTOH I did not see #493 coming, and it's undeniably useful to be able to do const { &None }
even when this is an Option<Cell<T>>
.
Cc @rust-lang/wg-const-eval, this issue is an the intersection of opsem and const-eval.