about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-04-29 18:56:57 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-04-29 18:56:57 +0000
commit67ce547f474fbe34e8aafe4bfc284c3856673744 (patch)
tree38459ecf7bafe509a1a337abd330ec03b10ce1f5
parentbe54947315b6d2892ed09281a7770e1f09c673e7 (diff)
downloadrust-67ce547f474fbe34e8aafe4bfc284c3856673744.tar.gz
rust-67ce547f474fbe34e8aafe4bfc284c3856673744.zip
Refactor and document the repeat length check
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs41
1 files changed, 22 insertions, 19 deletions
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 8dd288e5555..a1e8d2040dd 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -1304,31 +1304,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         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);
         }
     }