Fix ICE with const generic param in struct

This commit is contained in:
varkor 2019-03-22 01:49:42 +00:00
parent 7a4df3b53d
commit f94f85bebd
3 changed files with 48 additions and 17 deletions

View File

@ -814,7 +814,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
debug!("(resolving function) entering function");
let (rib_kind, asyncness) = match function_kind {
FnKind::ItemFn(_, ref header, ..) =>
(ItemRibKind, header.asyncness.node),
(FnItemRibKind, header.asyncness.node),
FnKind::Method(_, ref sig, _, _) =>
(TraitOrImplItemRibKind, sig.header.asyncness.node),
FnKind::Closure(_) =>
@ -950,6 +950,10 @@ enum RibKind<'a> {
/// upvars).
TraitOrImplItemRibKind,
/// We passed through a function definition. Disallow upvars.
/// Permit only those const parameters specified in the function's generics.
FnItemRibKind,
/// We passed through an item scope. Disallow upvars.
ItemRibKind,
@ -3863,7 +3867,7 @@ impl<'a> Resolver<'a> {
seen.insert(node_id, depth);
}
}
ItemRibKind | TraitOrImplItemRibKind => {
ItemRibKind | FnItemRibKind | TraitOrImplItemRibKind => {
// This was an attempt to access an upvar inside a
// named function item. This is not allowed, so we
// report an error.
@ -3897,7 +3901,7 @@ impl<'a> Resolver<'a> {
ConstantItemRibKind => {
// Nothing to do. Continue.
}
ItemRibKind => {
ItemRibKind | FnItemRibKind => {
// This was an attempt to use a type parameter outside its scope.
if record_used {
resolve_error(
@ -3912,21 +3916,27 @@ impl<'a> Resolver<'a> {
}
}
Def::ConstParam(..) => {
// A const param is always declared in a signature, which is always followed by
// some kind of function rib kind (specifically, ItemRibKind in the case of a
// normal function), so we can skip the first rib as it will be guaranteed to
// (spuriously) conflict with the const param.
for rib in &ribs[1..] {
if let ItemRibKind = rib.kind {
// This was an attempt to use a const parameter outside its scope.
if record_used {
resolve_error(
self,
span,
ResolutionError::GenericParamsFromOuterFunction(def),
);
let mut ribs = ribs.iter().peekable();
if let Some(Rib { kind: FnItemRibKind, .. }) = ribs.peek() {
// When declaring const parameters inside function signatures, the first rib
// is always a `FnItemRibKind`. In this case, we can skip it, to avoid it
// (spuriously) conflicting with the const param.
ribs.next();
}
for rib in ribs {
match rib.kind {
ItemRibKind | FnItemRibKind => {
// This was an attempt to use a const parameter outside its scope.
if record_used {
resolve_error(
self,
span,
ResolutionError::GenericParamsFromOuterFunction(def),
);
}
return Def::Err;
}
return Def::Err;
_ => {}
}
}
}

View File

@ -0,0 +1,6 @@
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
struct S<const C: u8>(C); //~ ERROR expected type, found const parameter
fn main() {}

View File

@ -0,0 +1,15 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/struct-with-invalid-const-param.rs:1:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
error[E0573]: expected type, found const parameter `C`
--> $DIR/struct-with-invalid-const-param.rs:4:23
|
LL | struct S<const C: u8>(C);
| ^ help: a struct with a similar name exists: `S`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0573`.