Skip to content

Commit f7b89da

Browse files
committed
Catch and fix explicit promotions that fail to actually promote
1 parent a4e551e commit f7b89da

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

src/librustc_mir/transform/promote_consts.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,26 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
207207
Rvalue::Ref(..) => {
208208
self.candidates.push(Candidate::Ref(location));
209209
}
210-
Rvalue::Repeat(elem, _)
210+
Rvalue::Repeat(elem, n)
211211
if self.ccx.tcx.features().const_in_array_repeat_expressions =>
212212
{
213-
if !elem.ty(&self.ccx.body.local_decls, self.ccx.tcx).is_copy_modulo_regions(
213+
let is_copy = elem.ty(&self.ccx.body.local_decls, self.ccx.tcx).is_copy_modulo_regions(
214214
self.ccx.tcx,
215215
self.ccx.param_env,
216216
self.span,
217-
) {
217+
);
218+
let n = n.try_eval_usize(self.ccx.tcx, self.ccx.param_env);
219+
let length_requires_copy_or_promotion = match n {
220+
// Unevaluable (e.g. too generic) -> assume > 1.
221+
None => true,
222+
// A single element does not need copying, we can just use the given element.
223+
// Zero elements don't even need that one element.
224+
Some(0..=1) => false,
225+
// All other lengths require copying (or promotion-"copying" by creating a
226+
// a constant and using that many times).
227+
Some(_) => true,
228+
};
229+
if !is_copy && length_requires_copy_or_promotion {
218230
self.candidates.push(Candidate::Repeat(location));
219231
}
220232
}
@@ -741,6 +753,14 @@ pub fn validate_candidates(
741753
// and `#[rustc_args_required_const]` arguments here.
742754

743755
let is_promotable = validator.validate_candidate(candidate).is_ok();
756+
757+
if validator.explicit && !is_promotable {
758+
ccx.tcx.sess.delay_span_bug(
759+
ccx.body.span,
760+
"Explicit promotion requested, but failed to promote",
761+
);
762+
}
763+
744764
match candidate {
745765
Candidate::Argument { bb, index } if !is_promotable => {
746766
let span = ccx.body[bb].terminator().source_info.span;

0 commit comments

Comments
 (0)