Skip to content

Commit 933c773

Browse files
authored
Rollup merge of rust-lang#60839 - davidtwco:const-generics-struct-ctor, r=varkor
Fix ICE with struct ctors and const generics. Fixes rust-lang#60818. r? @varkor
2 parents 040af62 + 41aaf7b commit 933c773

6 files changed

+74
-73
lines changed

src/librustc/hir/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,13 @@ impl GenericArg {
425425
GenericArg::Const(c) => c.value.hir_id,
426426
}
427427
}
428+
429+
pub fn is_const(&self) -> bool {
430+
match self {
431+
GenericArg::Const(_) => true,
432+
_ => false,
433+
}
434+
}
428435
}
429436

430437
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]

src/librustc_typeck/collect.rs

+47-51
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rustc::ty::subst::{Subst, InternalSubsts};
2727
use rustc::ty::util::Discr;
2828
use rustc::ty::util::IntTypeExt;
2929
use rustc::ty::subst::UnpackedKind;
30-
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
30+
use rustc::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
3131
use rustc::ty::{ReprOptions, ToPredicate};
3232
use rustc::util::captures::Captures;
3333
use rustc::util::nodemap::FxHashMap;
@@ -1349,65 +1349,61 @@ pub fn checked_type_of<'a, 'tcx>(
13491349

13501350
match path {
13511351
QPath::Resolved(_, ref path) => {
1352-
let mut arg_index = 0;
1353-
let mut found_const = false;
1354-
for seg in &path.segments {
1355-
if let Some(generic_args) = &seg.args {
1356-
let args = &generic_args.args;
1357-
for arg in args {
1358-
if let GenericArg::Const(ct) = arg {
1359-
if ct.value.hir_id == hir_id {
1360-
found_const = true;
1361-
break;
1362-
}
1363-
arg_index += 1;
1364-
}
1365-
}
1366-
}
1367-
}
1368-
// Sanity check to make sure everything is as expected.
1369-
if !found_const {
1370-
if !fail {
1371-
return None;
1372-
}
1373-
bug!("no arg matching AnonConst in path")
1374-
}
1375-
match path.res {
1376-
// We've encountered an `AnonConst` in some path, so we need to
1377-
// figure out which generic parameter it corresponds to and return
1378-
// the relevant type.
1379-
Res::Def(DefKind::Struct, def_id)
1380-
| Res::Def(DefKind::Union, def_id)
1381-
| Res::Def(DefKind::Enum, def_id)
1382-
| Res::Def(DefKind::Fn, def_id) => {
1383-
let generics = tcx.generics_of(def_id);
1384-
let mut param_index = 0;
1385-
for param in &generics.params {
1386-
if let ty::GenericParamDefKind::Const = param.kind {
1387-
if param_index == arg_index {
1388-
return Some(tcx.type_of(param.def_id));
1389-
}
1390-
param_index += 1;
1391-
}
1392-
}
1393-
// This is no generic parameter associated with the arg. This is
1394-
// probably from an extra arg where one is not needed.
1395-
return Some(tcx.types.err);
1396-
}
1397-
Res::Err => tcx.types.err,
1398-
x => {
1352+
let arg_index = path.segments.iter()
1353+
.filter_map(|seg| seg.args.as_ref())
1354+
.map(|generic_args| generic_args.args.as_ref())
1355+
.find_map(|args| {
1356+
args.iter()
1357+
.filter(|arg| arg.is_const())
1358+
.enumerate()
1359+
.filter(|(_, arg)| arg.id() == hir_id)
1360+
.map(|(index, _)| index)
1361+
.next()
1362+
})
1363+
.or_else(|| {
13991364
if !fail {
1400-
return None;
1365+
None
1366+
} else {
1367+
bug!("no arg matching AnonConst in path")
14011368
}
1369+
})?;
1370+
1371+
// We've encountered an `AnonConst` in some path, so we need to
1372+
// figure out which generic parameter it corresponds to and return
1373+
// the relevant type.
1374+
let generics = match path.res {
1375+
Res::Def(DefKind::Ctor(..), def_id) =>
1376+
tcx.generics_of(tcx.parent(def_id).unwrap()),
1377+
Res::Def(_, def_id) =>
1378+
tcx.generics_of(def_id),
1379+
Res::Err =>
1380+
return Some(tcx.types.err),
1381+
_ if !fail =>
1382+
return None,
1383+
x => {
14021384
tcx.sess.delay_span_bug(
14031385
DUMMY_SP,
14041386
&format!(
14051387
"unexpected const parent path def {:?}", x
14061388
),
14071389
);
1408-
tcx.types.err
1390+
return Some(tcx.types.err);
14091391
}
1410-
}
1392+
};
1393+
1394+
generics.params.iter()
1395+
.filter(|param| {
1396+
if let ty::GenericParamDefKind::Const = param.kind {
1397+
true
1398+
} else {
1399+
false
1400+
}
1401+
})
1402+
.nth(arg_index)
1403+
.map(|param| tcx.type_of(param.def_id))
1404+
// This is no generic parameter associated with the arg. This is
1405+
// probably from an extra arg where one is not needed.
1406+
.unwrap_or(tcx.types.err)
14111407
}
14121408
x => {
14131409
if !fail {

src/test/ui/const-generics/cannot-infer-type-for-const-param.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
// compile-pass
12
#![feature(const_generics)]
23
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
34

4-
// We should probably be able to infer the types here. However, this test is checking that we don't
5-
// get an ICE in this case. It may be modified later to not be an error.
5+
// This test confirms that the types can be inferred correctly for this example with const
6+
// generics. Previously this would ICE, and more recently error.
67

78
struct Foo<const NUM_BYTES: usize>(pub [u8; NUM_BYTES]);
89

Original file line numberDiff line numberDiff line change
@@ -1,25 +1,6 @@
11
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2-
--> $DIR/cannot-infer-type-for-const-param.rs:1:12
2+
--> $DIR/cannot-infer-type-for-const-param.rs:2:12
33
|
44
LL | #![feature(const_generics)]
55
| ^^^^^^^^^^^^^^
66

7-
error[E0282]: type annotations needed
8-
--> $DIR/cannot-infer-type-for-const-param.rs:10:19
9-
|
10-
LL | let _ = Foo::<3>([1, 2, 3]);
11-
| ^ cannot infer type for `{integer}`
12-
13-
error[E0308]: mismatched types
14-
--> $DIR/cannot-infer-type-for-const-param.rs:10:22
15-
|
16-
LL | let _ = Foo::<3>([1, 2, 3]);
17-
| ^^^^^^^^^ expected `3`, found `3usize`
18-
|
19-
= note: expected type `[u8; _]`
20-
found type `[u8; 3]`
21-
22-
error: aborting due to 2 previous errors
23-
24-
Some errors have detailed explanations: E0282, E0308.
25-
For more information about an error, try `rustc --explain E0282`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// compile-pass
2+
3+
#![feature(const_generics)]
4+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
5+
6+
struct Generic<const V: usize>;
7+
8+
fn main() {
9+
let _ = Generic::<0>;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/issue-60818-struct-constructors.rs:3:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+

0 commit comments

Comments
 (0)