@@ -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