Rollup merge of #60839 - davidtwco:const-generics-struct-ctor, r=varkor

Fix ICE with struct ctors and const generics.

Fixes #60818.

r? @varkor
This commit is contained in:
Mazdak Farrokhzad 2019-05-30 10:52:49 +02:00 committed by GitHub
commit 933c773b61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 73 deletions

View File

@ -425,6 +425,13 @@ impl GenericArg {
GenericArg::Const(c) => c.value.hir_id,
}
}
pub fn is_const(&self) -> bool {
match self {
GenericArg::Const(_) => true,
_ => false,
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]

View File

@ -27,7 +27,7 @@ use rustc::ty::subst::{Subst, InternalSubsts};
use rustc::ty::util::Discr;
use rustc::ty::util::IntTypeExt;
use rustc::ty::subst::UnpackedKind;
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
use rustc::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
use rustc::ty::{ReprOptions, ToPredicate};
use rustc::util::captures::Captures;
use rustc::util::nodemap::FxHashMap;
@ -1349,65 +1349,61 @@ pub fn checked_type_of<'a, 'tcx>(
match path {
QPath::Resolved(_, ref path) => {
let mut arg_index = 0;
let mut found_const = false;
for seg in &path.segments {
if let Some(generic_args) = &seg.args {
let args = &generic_args.args;
for arg in args {
if let GenericArg::Const(ct) = arg {
if ct.value.hir_id == hir_id {
found_const = true;
break;
}
arg_index += 1;
}
}
}
}
// Sanity check to make sure everything is as expected.
if !found_const {
if !fail {
return None;
}
bug!("no arg matching AnonConst in path")
}
match path.res {
// We've encountered an `AnonConst` in some path, so we need to
// figure out which generic parameter it corresponds to and return
// the relevant type.
Res::Def(DefKind::Struct, def_id)
| Res::Def(DefKind::Union, def_id)
| Res::Def(DefKind::Enum, def_id)
| Res::Def(DefKind::Fn, def_id) => {
let generics = tcx.generics_of(def_id);
let mut param_index = 0;
for param in &generics.params {
if let ty::GenericParamDefKind::Const = param.kind {
if param_index == arg_index {
return Some(tcx.type_of(param.def_id));
}
param_index += 1;
}
}
// This is no generic parameter associated with the arg. This is
// probably from an extra arg where one is not needed.
return Some(tcx.types.err);
}
Res::Err => tcx.types.err,
x => {
let arg_index = path.segments.iter()
.filter_map(|seg| seg.args.as_ref())
.map(|generic_args| generic_args.args.as_ref())
.find_map(|args| {
args.iter()
.filter(|arg| arg.is_const())
.enumerate()
.filter(|(_, arg)| arg.id() == hir_id)
.map(|(index, _)| index)
.next()
})
.or_else(|| {
if !fail {
return None;
None
} else {
bug!("no arg matching AnonConst in path")
}
})?;
// We've encountered an `AnonConst` in some path, so we need to
// figure out which generic parameter it corresponds to and return
// the relevant type.
let generics = match path.res {
Res::Def(DefKind::Ctor(..), def_id) =>
tcx.generics_of(tcx.parent(def_id).unwrap()),
Res::Def(_, def_id) =>
tcx.generics_of(def_id),
Res::Err =>
return Some(tcx.types.err),
_ if !fail =>
return None,
x => {
tcx.sess.delay_span_bug(
DUMMY_SP,
&format!(
"unexpected const parent path def {:?}", x
),
);
tcx.types.err
return Some(tcx.types.err);
}
}
};
generics.params.iter()
.filter(|param| {
if let ty::GenericParamDefKind::Const = param.kind {
true
} else {
false
}
})
.nth(arg_index)
.map(|param| tcx.type_of(param.def_id))
// This is no generic parameter associated with the arg. This is
// probably from an extra arg where one is not needed.
.unwrap_or(tcx.types.err)
}
x => {
if !fail {

View File

@ -1,8 +1,9 @@
// compile-pass
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
// We should probably be able to infer the types here. However, this test is checking that we don't
// get an ICE in this case. It may be modified later to not be an error.
// This test confirms that the types can be inferred correctly for this example with const
// generics. Previously this would ICE, and more recently error.
struct Foo<const NUM_BYTES: usize>(pub [u8; NUM_BYTES]);

View File

@ -1,25 +1,6 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/cannot-infer-type-for-const-param.rs:1:12
--> $DIR/cannot-infer-type-for-const-param.rs:2:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
error[E0282]: type annotations needed
--> $DIR/cannot-infer-type-for-const-param.rs:10:19
|
LL | let _ = Foo::<3>([1, 2, 3]);
| ^ cannot infer type for `{integer}`
error[E0308]: mismatched types
--> $DIR/cannot-infer-type-for-const-param.rs:10:22
|
LL | let _ = Foo::<3>([1, 2, 3]);
| ^^^^^^^^^ expected `3`, found `3usize`
|
= note: expected type `[u8; _]`
found type `[u8; 3]`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0282, E0308.
For more information about an error, try `rustc --explain E0282`.

View File

@ -0,0 +1,10 @@
// compile-pass
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
struct Generic<const V: usize>;
fn main() {
let _ = Generic::<0>;
}

View File

@ -0,0 +1,6 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/issue-60818-struct-constructors.rs:3:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^