Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decide on guarantees for evaluation of associated consts and const blocks #124971

Closed
RalfJung opened this issue May 10, 2024 · 7 comments
Closed
Labels
A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@RalfJung
Copy link
Member

RalfJung commented May 10, 2024

The point of this issue is to ask t-lang to decide on our guarantees for which constants will definitely be evaluated by the compiler: rust-lang/reference#1497. There's no I-lang-nominated in the reference repo so we need this companion issue.

The text added to the reference should be self-explaining: we guarantee that if a const block expression, or path expression denoting an associated const, is executed at runtime, then the corresponding constant has successfully evaluated, even if their value is entirely ignored by the following code. We do not say anything about constants occurring in dead code.

This is weaker than the guarantee we have been promoting so far, where all constants in a function were guaranteed to be evaluated if the function gets called, even if they occur in dead code. However, there is desire for something like const if which only evaluates constants in the branch that was actually taken, so long-term we probably don't want to guarantee all constants in a function to be evaluated. But when a const block / associated const occurs in live code, surely we want to guarantee that it is evaluated, and we don't want the compiler to optimize away the const entirely (including the panics it contains) just because their return value is not used.

If it turns out we need a stronger guarantee that applies to all constants, even in dead code, we can always strengthen this again in the future. But this minimal first guarantee should be fairly uncontroversial I hope.

@joshlf since you were asking about this guarantee, I hope this is strong enough for your needs. Looking at your example in #112090 I think it should be fine.
Cc @rust-lang/opsem @rust-lang/wg-const-eval

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 10, 2024
@RalfJung RalfJung added T-lang Relevant to the language team, which will review and decide on the PR/issue. I-lang-nominated Nominated for discussion during a lang team meeting. labels May 10, 2024
@RalfJung RalfJung added A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels May 10, 2024
@joshlf
Copy link
Contributor

joshlf commented May 10, 2024

This should be enough for our needs. Thanks for your work on this!

cc @jswrenn

@ChayimFriedman2
Copy link
Contributor

I don't understand: isn't the entire purpose of const if that even though constants in dead code are evaluated, this branch won't be evaluated if not taken?

@RalfJung
Copy link
Member Author

Those two statements are in contradiction, aren't they?

const if false {
  const { panic!(); } // this is in dead code
}

So we can't just say "const in dead code are evaluated". We have to say "const in dead code are evaluated, except ...". It's not okay to make a blanket statement and then restrict it elsewhere -- that makes the blanket statement just false.

@CAD97
Copy link
Contributor

CAD97 commented May 13, 2024

Theoretically a const if could be specified to do something stronger than making the untaken branch "dead code" and thus get behavior more like if the branch is outlined in a separate function and thus (potentially) never monomorphized. The language that C++'s constexpr if uses is roughly that the statement is discarded without ever being instantiated. The difference between "if expression where the condition is evaluated at const time" and "conditional compilation selection of expression blocks controlled by const time evaluation" is why I typically discuss the relevant feature as "static if" rather than as "const if".

However, it is still the case that "syntactically mentioned" is determined before any const evaluation is done by any reasonable interpretation. #[cfg] and macro expansion get intertwined with syntax, but const is definitively after. At least while type associated syntax macros continue to not exist.

I'd personally be quite happy to see a written guarantee that if a const expression is "evaluated" at runtime then that requires that the backing const item must have been evaluated at compile time regardless of what is (or isn't) done with the result of that evaluation at runtime. It's both an obvious rule and entirely independent of any details of the compilation model.

What I'd prefer not to see (yet) is any (new) guarantees of when const items are guaranteed to not be evaluated. While I concede to reality, I still strongly prefer consts being more eagerly required to be well-formed.

@RalfJung
Copy link
Member Author

I'd personally be quite happy to see a written guarantee that if a const expression is "evaluated" at runtime then that requires that the backing const item must have been evaluated at compile time regardless of what is (or isn't) done with the result of that evaluation at runtime. It's both an obvious rule and entirely independent of any details of the compilation model.

Yeah that was my thinking as well, which is why proposed exactly that.

What I'd prefer not to see (yet) is any (new) guarantees of when const items are guaranteed to not be evaluated. While I concede to reality, I still strongly prefer consts being more eagerly required to be well-formed.

Agreed as well, which is why my proposal does not make any such guarantees.

@traviscross
Copy link
Contributor

@rustbot labels -I-lang-nominated

We discussed this today in lang triage. People agreed that this is a reasonable and minimal first step, and rust-lang/reference#1497 is now in FCP.

@rustbot rustbot removed the I-lang-nominated Nominated for discussion during a lang team meeting. label May 15, 2024
@RalfJung
Copy link
Member Author

rust-lang/reference#1497 landed so this can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-const-eval Area: Constant evaluation, covers all const contexts (static, const fn, ...) T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants