typeck: Fix const generic in repeat param ICE.
Fixes #61336. Turns out this wasn't related to #49147 after all.
r? @varkor
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,
}
}
- 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_)
}
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)
}
}
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) => {
--- /dev/null
+#![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]);
+}
--- /dev/null
+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
+
--- /dev/null
+#![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]);
+}
--- /dev/null
+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`.