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:
commit
933c773b61
|
@ -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)]
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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>;
|
||||
}
|
|
@ -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)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
Loading…
Reference in New Issue