]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #61698 - davidtwco:ice-const-generic-length, r=varkor
authorMazdak Farrokhzad <twingoow@gmail.com>
Tue, 11 Jun 2019 15:14:04 +0000 (17:14 +0200)
committerGitHub <noreply@github.com>
Tue, 11 Jun 2019 15:14:04 +0000 (17:14 +0200)
typeck: Fix const generic in repeat param ICE.

Fixes #61336. Turns out this wasn't related to #49147 after all.

r? @varkor

src/librustc_typeck/astconv.rs
src/librustc_typeck/check/mod.rs
src/test/ui/const-generics/issue-61336-1.rs [new file with mode: 0644]
src/test/ui/const-generics/issue-61336-1.stderr [new file with mode: 0644]
src/test/ui/const-generics/issue-61336.rs [new file with mode: 0644]
src/test/ui/const-generics/issue-61336.stderr [new file with mode: 0644]

index 63d9f0920cc7b3f7a88afd0fb839b7ed970c0a6f..5a46c9d440b5d82bb1378d636ed8fc8201409b93 100644 (file)
@@ -2155,6 +2155,17 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
         result_ty
     }
 
+    /// Returns the `DefId` of the constant parameter that the provided expression is a path to.
+    pub fn const_param_def_id(&self, expr: &hir::Expr) -> Option<DefId> {
+        match &expr.node {
+            ExprKind::Path(hir::QPath::Resolved(_, path)) => match path.res {
+                Res::Def(DefKind::ConstParam, did) => Some(did),
+                _ => None,
+            },
+            _ => None,
+        }
+    }
+
     pub fn ast_const_to_const(
         &self,
         ast_const: &hir::AnonConst,
@@ -2185,19 +2196,17 @@ pub fn ast_const_to_const(
             }
         }
 
-        if let ExprKind::Path(ref qpath) = expr.node {
-            if let hir::QPath::Resolved(_, ref path) = qpath {
-                if let Res::Def(DefKind::ConstParam, def_id) = path.res {
-                    let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
-                    let item_id = tcx.hir().get_parent_node(node_id);
-                    let item_def_id = tcx.hir().local_def_id(item_id);
-                    let generics = tcx.generics_of(item_def_id);
-                    let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
-                    let name = tcx.hir().name(node_id).as_interned_str();
-                    const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
-                }
-            }
-        };
+        if let Some(def_id) = self.const_param_def_id(expr) {
+            // Find the name and index of the const parameter by indexing the generics of the
+            // parent item and construct a `ParamConst`.
+            let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
+            let item_id = tcx.hir().get_parent_node(node_id);
+            let item_def_id = tcx.hir().local_def_id(item_id);
+            let generics = tcx.generics_of(item_def_id);
+            let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
+            let name = tcx.hir().name(node_id).as_interned_str();
+            const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
+        }
 
         tcx.mk_const(const_)
     }
index 2e53b380cb71a6b8441b4db009c22d0b424be192..e35df6cd494a2fbfbb8a251d4d0c10b0eb0573e5 100644 (file)
@@ -2504,6 +2504,11 @@ pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
         ty
     }
 
+    /// Returns the `DefId` of the constant parameter that the provided expression is a path to.
+    pub fn const_param_def_id(&self, hir_c: &hir::AnonConst) -> Option<DefId> {
+        AstConv::const_param_def_id(self, &self.tcx.hir().body(hir_c.body).value)
+    }
+
     pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
         AstConv::ast_const_to_const(self, ast_c, ty)
     }
@@ -4479,19 +4484,24 @@ fn check_expr_kind(
             }
             ExprKind::Repeat(ref element, ref count) => {
                 let count_def_id = tcx.hir().local_def_id_from_hir_id(count.hir_id);
-                let param_env = ty::ParamEnv::empty();
-                let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), count_def_id);
-                let instance = ty::Instance::resolve(
-                    tcx.global_tcx(),
-                    param_env,
-                    count_def_id,
-                    substs,
-                ).unwrap();
-                let global_id = GlobalId {
-                    instance,
-                    promoted: None
+                let count = if self.const_param_def_id(count).is_some() {
+                    Ok(self.to_const(count, self.tcx.type_of(count_def_id)))
+                } else {
+                    let param_env = ty::ParamEnv::empty();
+                    let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), count_def_id);
+                    let instance = ty::Instance::resolve(
+                        tcx.global_tcx(),
+                        param_env,
+                        count_def_id,
+                        substs,
+                    ).unwrap();
+                    let global_id = GlobalId {
+                        instance,
+                        promoted: None
+                    };
+
+                    tcx.const_eval(param_env.and(global_id))
                 };
-                let count = tcx.const_eval(param_env.and(global_id));
 
                 let uty = match expected {
                     ExpectHasType(uty) => {
diff --git a/src/test/ui/const-generics/issue-61336-1.rs b/src/test/ui/const-generics/issue-61336-1.rs
new file mode 100644 (file)
index 0000000..5b5e431
--- /dev/null
@@ -0,0 +1,12 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
+    [x; N]
+    //~^ ERROR array lengths can't depend on generic parameters
+}
+
+fn main() {
+    let x: [u32; 5] = f::<u32, 5>(3);
+    assert_eq!(x, [3u32; 5]);
+}
diff --git a/src/test/ui/const-generics/issue-61336-1.stderr b/src/test/ui/const-generics/issue-61336-1.stderr
new file mode 100644 (file)
index 0000000..1a5bb9f
--- /dev/null
@@ -0,0 +1,14 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-61336-1.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error: array lengths can't depend on generic parameters
+  --> $DIR/issue-61336-1.rs:5:9
+   |
+LL |     [x; N]
+   |         ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issue-61336.rs b/src/test/ui/const-generics/issue-61336.rs
new file mode 100644 (file)
index 0000000..9593037
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
+    [x; N]
+}
+
+fn g<T, const N: usize>(x: T) -> [T; N] {
+    [x; N]
+    //~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied [E0277]
+}
+
+fn main() {
+    let x: [u32; 5] = f::<u32, 5>(3);
+    assert_eq!(x, [3u32; 5]);
+}
diff --git a/src/test/ui/const-generics/issue-61336.stderr b/src/test/ui/const-generics/issue-61336.stderr
new file mode 100644 (file)
index 0000000..9939a59
--- /dev/null
@@ -0,0 +1,18 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-61336.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/issue-61336.rs:9:5
+   |
+LL |     [x; N]
+   |     ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+   = note: the `Copy` trait is required because the repeated element will be copied
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.