@@ -1304,31 +1304,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1304
1304
element_ty : Ty < ' tcx > ,
1305
1305
) {
1306
1306
let tcx = self . tcx ;
1307
- let is_const = match & element. kind {
1308
- hir:: ExprKind :: ConstBlock ( ..) => true ,
1307
+ // Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy.
1308
+ match & element. kind {
1309
+ hir:: ExprKind :: ConstBlock ( ..) => return ,
1309
1310
hir:: ExprKind :: Path ( qpath) => {
1310
1311
let res = self . typeck_results . borrow ( ) . qpath_res ( qpath, element. hir_id ) ;
1311
- matches ! (
1312
- res ,
1313
- Res :: Def ( DefKind :: Const | DefKind :: AssocConst | DefKind :: AnonConst , _ )
1314
- )
1312
+ if let Res :: Def ( DefKind :: Const | DefKind :: AssocConst | DefKind :: AnonConst , _ ) = res
1313
+ {
1314
+ return ;
1315
+ }
1315
1316
}
1317
+ _ => { }
1318
+ }
1319
+ // If someone calls a const fn, they can extract that call out into a separate constant (or a const
1320
+ // block in the future), so we check that to tell them that in the diagnostic. Does not affect typeck.
1321
+ let is_const_fn = match element. kind {
1322
+ hir:: ExprKind :: Call ( func, _args) => match * self . node_ty ( func. hir_id ) . kind ( ) {
1323
+ ty:: FnDef ( def_id, _) => tcx. is_const_fn ( def_id) ,
1324
+ _ => false ,
1325
+ } ,
1316
1326
_ => false ,
1317
1327
} ;
1318
- if !is_const {
1319
- let is_const_fn = match element. kind {
1320
- hir:: ExprKind :: Call ( func, _args) => match * self . node_ty ( func. hir_id ) . kind ( ) {
1321
- ty:: FnDef ( def_id, _) => tcx. is_const_fn ( def_id) ,
1322
- _ => false ,
1323
- } ,
1324
- _ => false ,
1325
- } ;
1326
1328
1327
- if count. try_eval_usize ( tcx, self . param_env ) . map_or ( true , |len| len > 1 ) {
1328
- let lang_item = self . tcx . require_lang_item ( LangItem :: Copy , None ) ;
1329
- let code = traits:: ObligationCauseCode :: RepeatElementCopy { is_const_fn } ;
1330
- self . require_type_meets ( element_ty, element. span , code, lang_item) ;
1331
- }
1329
+ // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
1330
+ // don't copy that one element, we move it. Only check for Copy if the length is larger.
1331
+ if count. try_eval_usize ( tcx, self . param_env ) . map_or ( true , |len| len > 1 ) {
1332
+ let lang_item = self . tcx . require_lang_item ( LangItem :: Copy , None ) ;
1333
+ let code = traits:: ObligationCauseCode :: RepeatElementCopy { is_const_fn } ;
1334
+ self . require_type_meets ( element_ty, element. span , code, lang_item) ;
1332
1335
}
1333
1336
}
1334
1337
0 commit comments