]> git.lizzy.rs Git - rust.git/commitdiff
Refactor and document the repeat length check
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Fri, 29 Apr 2022 18:56:57 +0000 (18:56 +0000)
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Fri, 29 Apr 2022 18:56:57 +0000 (18:56 +0000)
compiler/rustc_typeck/src/check/expr.rs

index 8dd288e5555f0ab97131e4a15ca102f17fdbfd7a..a1e8d2040dd80d82429fa9b4984a656fb3145ef6 100644 (file)
@@ -1304,31 +1304,34 @@ fn check_repeat_element_needs_copy_bound(
         element_ty: Ty<'tcx>,
     ) {
         let tcx = self.tcx;
-        let is_const = match &element.kind {
-            hir::ExprKind::ConstBlock(..) => true,
+        // Actual constants as the repeat element get inserted repeatedly instead of getting copied via Copy.
+        match &element.kind {
+            hir::ExprKind::ConstBlock(..) => return,
             hir::ExprKind::Path(qpath) => {
                 let res = self.typeck_results.borrow().qpath_res(qpath, element.hir_id);
-                matches!(
-                    res,
-                    Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::AnonConst, _)
-                )
+                if let Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::AnonConst, _) = res
+                {
+                    return;
+                }
             }
+            _ => {}
+        }
+        // If someone calls a const fn, they can extract that call out into a separate constant (or a const
+        // block in the future), so we check that to tell them that in the diagnostic. Does not affect typeck.
+        let is_const_fn = match element.kind {
+            hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
+                ty::FnDef(def_id, _) => tcx.is_const_fn(def_id),
+                _ => false,
+            },
             _ => false,
         };
-        if !is_const {
-            let is_const_fn = match element.kind {
-                hir::ExprKind::Call(func, _args) => match *self.node_ty(func.hir_id).kind() {
-                    ty::FnDef(def_id, _) => tcx.is_const_fn(def_id),
-                    _ => false,
-                },
-                _ => false,
-            };
 
-            if count.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
-                let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
-                let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn };
-                self.require_type_meets(element_ty, element.span, code, lang_item);
-            }
+        // If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
+        // don't copy that one element, we move it. Only check for Copy if the length is larger.
+        if count.try_eval_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
+            let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
+            let code = traits::ObligationCauseCode::RepeatElementCopy { is_const_fn };
+            self.require_type_meets(element_ty, element.span, code, lang_item);
         }
     }