-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Use explicit promotion for constants in repeat expressions #70042
Conversation
This comment has been minimized.
This comment has been minimized.
r? @RalfJung I guess? |
This comment has been minimized.
This comment has been minimized.
Uh, I don't actually understand most of the code you are touching here -- the glue code that connects const-eval with the rest of the compiler. I could rubber-stamp it as it looks simple enough, but maybe we can think of someone who can do a meaningful review? @eddyb? (They have a lot on their plate though.) However, taking a step back... this is actually a pretty big decision, I feel. Last time we talked, it was still the case that rustc first checked if the repeat expression could be promoted, and only if that failed, it checked the And even with that principle upheld, there is still the issue that it might be hard to predict whether this code runs at run-time or at compile-time (because that depends on whether the
That doesn't have to happen here, it could be part of a stabilization FCP, but it should come up explicitly. |
I am working on a prototype for this since a few days, it seems like something we want independently of this PR |
This is exactly what this PR does (and what it was doing with implicit promo. If the type is
I believe we are already testing it, but I can add comments to those tests so if some day in the future something changes there, ppl know what we want to happen.
We can probably make the codegen code around |
This PR doesn't change the order in which Back then I was first told
I feel it would be more direct and more local to have a |
Oh that makes a lot of sense. Let's do that (or just report the tailored error right there) |
9f751fe
to
0ded830
Compare
…g had content there before the current changes
This renaming was already done in some modules via import renaming. It's strictly used as a context, and it contains a `TyCtxt`.
0ded830
to
a4e551e
Compare
r? @eddyb I split the PR into commits where each commit passes tests. The last commit (the only one actually changing any behavior) is now super small. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r=me on the changes themselves, but I don't know if we want to land the last commit without some process? I don't remember what the status of this was, did we decide already?
@Centril does this need an FCP or is an FCP for stabilization at some point enough? |
@@ -741,6 +753,14 @@ pub fn validate_candidates( | |||
// and `#[rustc_args_required_const]` arguments here. | |||
|
|||
let is_promotable = validator.validate_candidate(candidate).is_ok(); | |||
|
|||
if validator.explicit && !is_promotable { | |||
ccx.tcx.sess.delay_span_bug( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment explaining why this check is absolutely important?
I want to be sure someone doesn't just remove it when it seems convenient.^^
The explicit
field's doc comment already says a few things, so here's a proposal:
// If we use explicit validation, we carry the risk of turning a legitimate run-time
// operation into a failing compile-time operation. Make sure that does not happen
// by asserting that there is no possible run-time behavior here in case promotion fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What actually happens is not that we turn it into a failing compile-time op, it's that we don't promote at all, thus keeping the runtime operation, which happened to be the right thing in the cases that the assertion caught.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keeping the runtime operation
We do that because we don't even try. But the branch here is for after we tried, so we cannot be in the case where we want to keep the runtime operation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we are, this checks whether we can promote and if not, we remove it from the list. Then we process this list in promote_candidates
, which can only fail to promote without ICEing in case of nested promotion candidates, where promoting one candidate eliminated the other candidate because the other candidate is part of the already promoted one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am entirely confused now.
Going back a step -- did you want to say above that my proposed comment was incorrect, and suggest a better one? I don't understand what is is you are trying to say here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I believe your comment is incorrect
// If we use explicit validation, we expect promotion to succeed.
// If an explicit promotion candidate were to get "unpromoted" here,
// that means we keep an operation that we expect to happen at compile-time
// at runtime. In case of repeat elements, this would just cause an error
// later in compilation (due to multiple moves out of a `!Copy` value), but
// for `rustc_arg_required_const` function arguments, where a constant is
// required, ending up with a runtime value would likely ICE the compiler
// during codegen, or silently cause undocumented and undesired LLVM features
// to be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RalfJung What do you think about the above comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we are having different views of the same thing here.
Re: your comment, I am not worried about the case where, if promotion analysis here fails, we ICE the compiler later. I am worried about the case where we do not ICE later. Because that means that, no matter whether promotion succeeds or fails, we produce a program, but the programs may do different things because we use the less conservative, "explicit promotion" rules. That is what I think this comment should explain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This is the delay_span_bug
that I meant in my other comment, that we should add nevertheless.)
This comment has been minimized.
This comment has been minimized.
The PR feels too much in-flux for me to say one way or another. A summary with the rationale, pros, and cons would be helpful. |
This PR changes our behaviour in repeat expressions, turning the repeat element into a full (anonymous) constant if the type is const FOO: Vec<i32> = Vec::new();
[FOO; 42] because the repeat element was using the rules for promoteds instead of those for constants. @scottmcm worries that
source: #49147 (comment) Additionally on the tracking issue @RalfJung worried (#49147 (comment)) that it may be suprising to users as to what code is accepted and what isn't, since the This change is forward compatible with #49147 (comment) which suggests to permit |
This comment has been minimized.
This comment has been minimized.
19b3239
to
d41c8d3
Compare
let n = n.try_eval_usize(self.ccx.tcx, self.ccx.param_env); | ||
let length_requires_copy_or_promotion = match n { | ||
// Unevaluable (e.g. too generic) -> assume > 1. | ||
None => true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So could this lead to a problem if we later figure out that actually, the constant is 1
, and then we compile the program after a failed attempt to explicitly promote? (That would trigger the delayed_span_bug now.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the alternative is to fail to compile (!Copy
types treat generic lengths as > 1
, so if it later happens to be 1
that's irrelevant). While we could permit that, we'd be adding a new source of post monomorphization errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean I am fine with this as long as it is guaranteed that this cannot ICE due to the safety net delay_span_bug
this PR also adds.
I want to be sure that we do not draw ourselves into a corner where, or backwards compatibility reasons, we have to remove that safety net to fix an ICE.
We discussed this at Thursday's language team meeting (2020-04-09). Due to nervousness regarding extending promotion to more places, the rough consensus of those present at the meeting were that we should first consider something like We'll also add a checkbox to the tracking issue #49147 to make sure that we consider whether |
@oli-obk at least the |
#71198 is that follow-up. Thanks! |
…Jung Const check/promotion cleanup and sanity assertion r? @RalfJung This is just the part of rust-lang#70042 (comment) that does not change behaviour
…Jung Const check/promotion cleanup and sanity assertion r? @RalfJung This is just the part of rust-lang#70042 (comment) that does not change behaviour
As per #49147 (comment)
cc @rust-lang/wg-const-eval