Skip to content

Clean up implicit const promotion behavior #124328

Open
@RalfJung

Description

@RalfJung
Member

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

Activity

added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Apr 24, 2024
changed the title [-]Clean up const promotion behavior[/-] [+]Clean up implicit const promotion behavior[/+] on Apr 24, 2024
added
T-langRelevant to the language team
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
A-const-propArea: Constant propagation
C-enhancementCategory: An issue proposing an enhancement or a PR with one.
WG-const-evalWorking group: Const evaluation
and removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Apr 24, 2024
dlight

dlight commented on Mar 7, 2025

@dlight
  • &(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.

Could constant folding be performed before this promotion?

It makes sense that promotion won't be performed for, say, &(1/(1+i)) if i is not constant; but for &(1/(1+0)), the 1+0 should actually be constant.

RalfJung

RalfJung commented on Mar 7, 2025

@RalfJung
MemberAuthor

That would be too fragile, const folding should not affect whether your program compiles.

Just write &const { 1 / (1+0) } to explicitly ask for promotion.

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

Metadata

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 teamWG-const-evalWorking group: Const evaluation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @dlight@RalfJung@bstrie@fmease@rustbot

        Issue actions

          Clean up implicit const promotion behavior · Issue #124328 · rust-lang/rust