-
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
Changes from 1 commit
44e8a9a
85e2c32
77345cc
ee868e0
29aebf4
a4e551e
f7b89da
1530fe0
d41c8d3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -207,14 +207,26 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { | |
Rvalue::Ref(..) => { | ||
self.candidates.push(Candidate::Ref(location)); | ||
} | ||
Rvalue::Repeat(elem, _) | ||
Rvalue::Repeat(elem, n) | ||
if self.ccx.tcx.features().const_in_array_repeat_expressions => | ||
{ | ||
if !elem.ty(&self.ccx.body.local_decls, self.ccx.tcx).is_copy_modulo_regions( | ||
let is_copy = elem.ty(&self.ccx.body.local_decls, self.ccx.tcx).is_copy_modulo_regions( | ||
self.ccx.tcx, | ||
self.ccx.param_env, | ||
self.span, | ||
) { | ||
); | ||
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, | ||
// A single element does not need copying, we can just use the given element. | ||
// Zero elements don't even need that one element. | ||
Some(0..=1) => false, | ||
oli-obk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// All other lengths require copying (or promotion-"copying" by creating a | ||
// a constant and using that many times). | ||
Some(_) => true, | ||
}; | ||
if !is_copy && length_requires_copy_or_promotion { | ||
self.candidates.push(Candidate::Repeat(location)); | ||
} | ||
} | ||
|
@@ -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 commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a comment explaining why this check is absolutely important? The
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more.
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 commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I believe your comment is incorrect
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. (This is the |
||
ccx.body.span, | ||
"Explicit promotion requested, but failed to promote", | ||
); | ||
} | ||
|
||
match candidate { | ||
Candidate::Argument { bb, index } if !is_promotable => { | ||
let span = ccx.body[bb].terminator().source_info.span; | ||
|
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 be1
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.