@@ -1304,31 +1304,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13041304 element_ty : Ty < ' tcx > ,
13051305 ) {
13061306 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 ,
13091310 hir:: ExprKind :: Path ( qpath) => {
13101311 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+ }
13151316 }
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+ } ,
13161326 _ => false ,
13171327 } ;
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- } ;
13261328
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) ;
13321335 }
13331336 }
13341337
0 commit comments