Skip to content

Commit

Permalink
Rollup merge of rust-lang#61698 - davidtwco:ice-const-generic-length,…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
Centril authored Jun 11, 2019
2 parents 2c642de + 9ed4674 commit 4f6aa0d
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 25 deletions.
35 changes: 22 additions & 13 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2155,6 +2155,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
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,
Expand Down Expand Up @@ -2185,19 +2196,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
}
}

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_)
}
Expand Down
34 changes: 22 additions & 12 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2460,6 +2460,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, '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)
}
Expand Down Expand Up @@ -4435,19 +4440,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
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) => {
Expand Down
12 changes: 12 additions & 0 deletions src/test/ui/const-generics/issue-61336-1.rs
Original file line number Diff line number Diff line change
@@ -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]);
}
14 changes: 14 additions & 0 deletions src/test/ui/const-generics/issue-61336-1.stderr
Original file line number Diff line number Diff line change
@@ -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

16 changes: 16 additions & 0 deletions src/test/ui/const-generics/issue-61336.rs
Original file line number Diff line number Diff line change
@@ -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]);
}
18 changes: 18 additions & 0 deletions src/test/ui/const-generics/issue-61336.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 4f6aa0d

Please sign in to comment.