question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Restrict promotion to infallible operations

See original GitHub issue

Proposal

Summary and problem statement

I propose to resolve the “promotion mess” by only promoting code that we know will not fail to const-evaluate.

Motivation, use-cases, and solution sketches

Promotion of code to a const has been a constant source of “challenges” (aka problems) and surprises over the years. The first I saw is this soundness issue and since then we kept accumulating special cases in various parts of the compiler. Also see why we cannot promote arbitrary const fn calls, and this “meta issue”.

I think we can solve this problem once and for all by ensuring that we only promote code that cannot fail to const-evaluate. Then we can get rid of all the code in rustc that has to somehow do something when evaluating a promoted failed. If we also make const_err a hard error we can in fact assume that const-evaluation errors are always directly reported to the user, which leads to even further simplifications and enables us to fix some diagnostics issues.

Technical note: it might seem that we have to rule out promotion of arithmetic in debug mode as overflows would cause evaluation failure. That is however not the case. An addition in release mode is compiled to a CheckedAdd MIR operation that never fails, which returns an (<int>, bool), and is followed by a check of said bool to possibly raise a panic. We only ever promote the CheckedAdd, so evaluation of the promoted will never fail, even if the operation overflows.

So I think we should work towards making all CTFE failures hard errors, and I started putting down some notes for that. However, this will require some breaking changes around promotion:

  • We should no longer promote things like &(1/0) or &[2][12]. When promoting fallible operations like division, modulo, and indexing (and I think those are all the fallible operations we promote, but I might have missed something), then we have to make sure that this concrete promoted will not fail – we need to check for div-by-0 and do the bounds check before accepting an expression for promotion. I propose we check if the index/divisor are constants, in which case the analysis is trivial, and just reject promotion for non-constant indices/divisors. If that is too breaking, a backup plan might be to somehow treat this more like CheckedAdd, where we promote the addition but not the assertion, which does ensure that the promoted never fails to evaluate even on overflow. (But I think that only works for divison/modulo, where we could return a “dummy value”; it doesn’t work for indexing in general.)
  • To achieve full “promoteds never fail”, we have to severely dial back promotion inside const/static initializers – basically to the same level as promotion inside fn and const fn. Currently there are two ways in which promotion inside const/static initializers is special here: first of all union field accesses are promoted (I am trying to take that back in https://github.com/rust-lang/rust/pull/77526), and secondly calls to all const fn are promoted. If we cannot take back both of these, we will instead need to treat MIR that originates from const/static initializers more carefully than other MIR – even in code that ought to compile, there might be constants in there which fail to evaluate, so MIR optimizations and MIR evaluation (aka Miri) need to be careful to not evaluate such consts. This would be some unfortunate technical debt, but in my opinion still way better than the situation we currently find ourselves in.

Alternative: restrict promotion to patterns

I have in the past raised support for restricting promotion even further, namely to only those expressions that would also be legal as patterns. @ecstatic-morse has also expressed support for this goal. However, I now think that this is unnecessarily restrictive – I do not see any further benefit that we would gain by ruling out expressions that will always succeed, but would not be legal as patterns. In any case, even if we want to go for pattern-only promotion in the future, that would only mean ruling out even more promotion than what I am proposing, so this proposal should still be a reasonable first step in that direction.

Prioritization

I guess this falls under the “Const generics and constant evaluation” priority.

Links and related work

Initial people involved

@ecstatic-morse, @oli-obk and me (aka the const-eval WG) have been talking about this and slowly chipping away at const promotion to make it less ill-behaved. The state described above is the result of as much cleanup as we felt comfortable doing just based on crater runs and the “accidental stabilization” argument.

What happens now?

This issue is part of the experimental MCP process described in RFC 2936. Once this issue is filed, a Zulip topic will be opened for discussion, and the lang-team will review open MCPs in its weekly triage meetings. You should receive feedback within a week or two.

This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:13 (8 by maintainers)

github_iconTop GitHub Comments

2reactions
RalfJungcommented, Oct 7, 2020

Yes, we’ll definitely use crater on each PR that could break something, and we’ll get T-lang involved in the discussion should there be notable amounts of regressions. (The PRs we landed so far had 0 stable regressions in crater.)

1reaction
rfcbotcommented, Oct 8, 2020

🔔 This is now entering its final comment period, as per the review above. 🔔

psst @joshtriplett, I wasn’t able to add the final-comment-period label, please do so.

Read more comments on GitHub >

github_iconTop Results From Across the Web

3027-infallible-promotion - The Rust RFC Book
Restrict (implicit) promotion, such as lifetime extension of rvalues, to infallible operations. Motivation. Background on promotion and lifetime extension.
Read more >
7.0 Restricted Content, Products and Services - Amazon Ads
Amazon prohibits campaigns from third-party alcohol retailers. Ads must promote the responsible consumption of alcoholic beverages. Ads must not: Be directed ...
Read more >
Restrict promotions, only one per entry? - Optimizely World
Is it possible to restrict promotions so that you can only have one per entry? For example, if you have a active promotion...
Read more >
Promotion Of Line Officers Of The Navy | Proceedings - October ...
Lieutenant Commander Vossler in his article, "Promotion in the Navy" (U.S. ... have some means to prevent every physically fit officer from remaining...
Read more >
Chapter 4-Security Management, from Safeguarding Your ...
A time frame for starting initial operations after a security incident ... taken at the onset of an undesirable event to limit damage,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found