Clean up implicit const promotion behavior
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
In https://github.com/rust-lang/rust/issues/80619 we tamed promotion to no longer cause fundamental problems around whether and when const-evaluation is allowed to fail. All our promoteds are now either infallible, or in guaranteed-live code.
However, as part of this, the rules for what we promote when became "a bit" obscure:
&(1/1)gets promoted, but&(1/(1+0))does not. This is because when the RHS of the division is not a constant, it may be 0, and computing the promoted value would fail, so we can't promote this.- Inside the initializer expression of a const/static,
&myfunction()gets promoted only if the control flow graph of the initializer is a straight line until it reaches this point. (See here for examples.) This is to ensure that we do not promote function calls in dead code. &Enum::Variantgets promoted even if other enum variants containUnsafeCell, which is borderline unsound.
We should probably clean that up, by not promoting function calls or division/modulo ever (requiring a const block instead), and also not doing value-based reasoning for interior mutability during promotion. I assume this requires an edition transition. (Here is a crater run that just tried to not promote function calls ever. ) Edition transitions for promotions are non-trivial; they would have to work something like this:
- Do not promote these things.
- Run borrowck.
- If that fails, try promoting them and see if that makes borrowck pass. If yes, issue a forward-compat lint. If there's more than one candidate that could be promoted, try all of them one after the other... (or accept that we would add more
const { ... }blocks than are actually needed)
That's non-trivial but would also help clean up a very organically grown (and hence confusingly-shaped) part of the language, and resolve some cases that are at least borderline unsound.
FWIW, for division/modulo, there is in theory an alternative -- we could treat them similar to what we do with overflows in add/sub/mul. This requires having a version of these operators that always succeeds. Then we can promote &(a/b) to using that kind of division, and additionally include a runtime check (outside the promoted) for division-by-0 (and for overflow due to division-by-int-min).
Cc @rust-lang/wg-const-eval
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading issue #80619 and the examples in PR #121557 to understand the current promotion rules. Review PR #148952 and its crater report for the impact of not promoting function calls. Done requires an agreed promotion design, including edition-transition behavior and handling of division, modulo, and interior mutability.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100