From: Mazdak Farrokhzad Date: Tue, 11 Jun 2019 15:14:04 +0000 (+0200) Subject: Rollup merge of #61698 - davidtwco:ice-const-generic-length, r=varkor X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=bd57c187fbcc55afc214120e26b2fb81ccecf68a;hp=b3169552e2bf6ba8f9d3a8898acdcbd8f6aa3ac6;p=rust.git Rollup merge of #61698 - davidtwco:ice-const-generic-length, r=varkor typeck: Fix const generic in repeat param ICE. Fixes #61336. Turns out this wasn't related to #49147 after all. r? @varkor --- diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 63d9f0920cc..5a46c9d440b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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 { + 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_) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2e53b380cb7..e35df6cd494 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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 { + 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 index 00000000000..5b5e431bf2f --- /dev/null +++ b/src/test/ui/const-generics/issue-61336-1.rs @@ -0,0 +1,12 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn f(x: T) -> [T; N] { + [x; N] + //~^ ERROR array lengths can't depend on generic parameters +} + +fn main() { + let x: [u32; 5] = f::(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 index 00000000000..1a5bb9f763b --- /dev/null +++ b/src/test/ui/const-generics/issue-61336-1.stderr @@ -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 index 00000000000..95930371d59 --- /dev/null +++ b/src/test/ui/const-generics/issue-61336.rs @@ -0,0 +1,16 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn f(x: T) -> [T; N] { + [x; N] +} + +fn g(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::(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 index 00000000000..9939a599834 --- /dev/null +++ b/src/test/ui/const-generics/issue-61336.stderr @@ -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`.