about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvarkor <github@varkor.com>2019-03-22 01:49:42 +0000
committervarkor <github@varkor.com>2019-03-22 01:49:42 +0000
commitf94f85bebde816d78d8a7e6d8ebb75b2a254593c (patch)
treea0a2d29794a982a992ec0fae9d1ada390c7c0c90
parent7a4df3b53da369110984a2b57419c05a53e33b38 (diff)
downloadrust-f94f85bebde816d78d8a7e6d8ebb75b2a254593c.tar.gz
rust-f94f85bebde816d78d8a7e6d8ebb75b2a254593c.zip
Fix ICE with const generic param in struct
-rw-r--r--src/librustc_resolve/lib.rs44
-rw-r--r--src/test/ui/const-generics/struct-with-invalid-const-param.rs6
-rw-r--r--src/test/ui/const-generics/struct-with-invalid-const-param.stderr15
3 files changed, 48 insertions, 17 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index ac149be4b2a..c9b9898fb41 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -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;
+                        _ => {}
                     }
                 }
             }
diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.rs b/src/test/ui/const-generics/struct-with-invalid-const-param.rs
new file mode 100644
index 00000000000..207b07bf695
--- /dev/null
+++ b/src/test/ui/const-generics/struct-with-invalid-const-param.rs
@@ -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() {}
diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr
new file mode 100644
index 00000000000..561464b21cc
--- /dev/null
+++ b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr
@@ -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`.