Skip to content

Commit afa1902

Browse files
authored
Rollup merge of rust-lang#61698 - davidtwco:ice-const-generic-length, r=varkor
typeck: Fix const generic in repeat param ICE. Fixes rust-lang#61336. Turns out this wasn't related to rust-lang#49147 after all. r? @varkor
2 parents 6968754 + 9ed4674 commit afa1902

File tree

6 files changed

+104
-25
lines changed

6 files changed

+104
-25
lines changed

src/librustc_typeck/astconv.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -2155,6 +2155,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
21552155
result_ty
21562156
}
21572157

2158+
/// Returns the `DefId` of the constant parameter that the provided expression is a path to.
2159+
pub fn const_param_def_id(&self, expr: &hir::Expr) -> Option<DefId> {
2160+
match &expr.node {
2161+
ExprKind::Path(hir::QPath::Resolved(_, path)) => match path.res {
2162+
Res::Def(DefKind::ConstParam, did) => Some(did),
2163+
_ => None,
2164+
},
2165+
_ => None,
2166+
}
2167+
}
2168+
21582169
pub fn ast_const_to_const(
21592170
&self,
21602171
ast_const: &hir::AnonConst,
@@ -2185,19 +2196,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
21852196
}
21862197
}
21872198

2188-
if let ExprKind::Path(ref qpath) = expr.node {
2189-
if let hir::QPath::Resolved(_, ref path) = qpath {
2190-
if let Res::Def(DefKind::ConstParam, def_id) = path.res {
2191-
let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
2192-
let item_id = tcx.hir().get_parent_node(node_id);
2193-
let item_def_id = tcx.hir().local_def_id(item_id);
2194-
let generics = tcx.generics_of(item_def_id);
2195-
let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
2196-
let name = tcx.hir().name(node_id).as_interned_str();
2197-
const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
2198-
}
2199-
}
2200-
};
2199+
if let Some(def_id) = self.const_param_def_id(expr) {
2200+
// Find the name and index of the const parameter by indexing the generics of the
2201+
// parent item and construct a `ParamConst`.
2202+
let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
2203+
let item_id = tcx.hir().get_parent_node(node_id);
2204+
let item_def_id = tcx.hir().local_def_id(item_id);
2205+
let generics = tcx.generics_of(item_def_id);
2206+
let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
2207+
let name = tcx.hir().name(node_id).as_interned_str();
2208+
const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
2209+
}
22012210

22022211
tcx.mk_const(const_)
22032212
}

src/librustc_typeck/check/mod.rs

+22-12
Original file line numberDiff line numberDiff line change
@@ -2460,6 +2460,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24602460
ty
24612461
}
24622462

2463+
/// Returns the `DefId` of the constant parameter that the provided expression is a path to.
2464+
pub fn const_param_def_id(&self, hir_c: &hir::AnonConst) -> Option<DefId> {
2465+
AstConv::const_param_def_id(self, &self.tcx.hir().body(hir_c.body).value)
2466+
}
2467+
24632468
pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
24642469
AstConv::ast_const_to_const(self, ast_c, ty)
24652470
}
@@ -4435,19 +4440,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
44354440
}
44364441
ExprKind::Repeat(ref element, ref count) => {
44374442
let count_def_id = tcx.hir().local_def_id_from_hir_id(count.hir_id);
4438-
let param_env = ty::ParamEnv::empty();
4439-
let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), count_def_id);
4440-
let instance = ty::Instance::resolve(
4441-
tcx.global_tcx(),
4442-
param_env,
4443-
count_def_id,
4444-
substs,
4445-
).unwrap();
4446-
let global_id = GlobalId {
4447-
instance,
4448-
promoted: None
4443+
let count = if self.const_param_def_id(count).is_some() {
4444+
Ok(self.to_const(count, self.tcx.type_of(count_def_id)))
4445+
} else {
4446+
let param_env = ty::ParamEnv::empty();
4447+
let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), count_def_id);
4448+
let instance = ty::Instance::resolve(
4449+
tcx.global_tcx(),
4450+
param_env,
4451+
count_def_id,
4452+
substs,
4453+
).unwrap();
4454+
let global_id = GlobalId {
4455+
instance,
4456+
promoted: None
4457+
};
4458+
4459+
tcx.const_eval(param_env.and(global_id))
44494460
};
4450-
let count = tcx.const_eval(param_env.and(global_id));
44514461

44524462
let uty = match expected {
44534463
ExpectHasType(uty) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(const_generics)]
2+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
3+
4+
fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
5+
[x; N]
6+
//~^ ERROR array lengths can't depend on generic parameters
7+
}
8+
9+
fn main() {
10+
let x: [u32; 5] = f::<u32, 5>(3);
11+
assert_eq!(x, [3u32; 5]);
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/issue-61336-1.rs:1:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+
7+
error: array lengths can't depend on generic parameters
8+
--> $DIR/issue-61336-1.rs:5:9
9+
|
10+
LL | [x; N]
11+
| ^
12+
13+
error: aborting due to previous error
14+
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![feature(const_generics)]
2+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
3+
4+
fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
5+
[x; N]
6+
}
7+
8+
fn g<T, const N: usize>(x: T) -> [T; N] {
9+
[x; N]
10+
//~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied [E0277]
11+
}
12+
13+
fn main() {
14+
let x: [u32; 5] = f::<u32, 5>(3);
15+
assert_eq!(x, [3u32; 5]);
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/issue-61336.rs:1:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+
7+
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
8+
--> $DIR/issue-61336.rs:9:5
9+
|
10+
LL | [x; N]
11+
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
12+
|
13+
= help: consider adding a `where T: std::marker::Copy` bound
14+
= note: the `Copy` trait is required because the repeated element will be copied
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)