Skip to content

Clean up implicit const promotion behavior #124328

Open

Description

In #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::Variant gets promoted even if other enum variants contain UnsafeCell, 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. Cargo itself doesn't even build any more so we did not get numbers.) 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.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    A-const-propArea: Constant propagationA-maybe-future-editionSomething we may consider for a future edition.C-enhancementCategory: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team, which will review and decide on the PR/issue.WG-const-evalWorking group: Const evaluation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions