about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2020-07-20 12:30:32 -0700
committerGitHub <noreply@github.com>2020-07-20 12:30:32 -0700
commit6bbf82ddd7c09f8332190c7f9a5b53e53a317c21 (patch)
treef1fa35ec33f0996a367957ebf567f26acbb8489e /src
parent963b837a837a4c49086bb2f3b5d2ac0789dcf69c (diff)
parentf5e5eb6f46ef2cf0dd45dba4f975305509334fc6 (diff)
downloadrust-6bbf82ddd7c09f8332190c7f9a5b53e53a317c21.tar.gz
rust-6bbf82ddd7c09f8332190c7f9a5b53e53a317c21.zip
Rollup merge of #74557 - jakubadamw:issue-74539, r=nagisa
Fix an ICE on an invalid `binding @ ...` in a tuple struct pattern

Fixes #74539.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_resolve/late.rs8
-rw-r--r--src/test/ui/issues/issue-74539.rs12
-rw-r--r--src/test/ui/issues/issue-74539.stderr21
3 files changed, 40 insertions, 1 deletions
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index ed88e549692..261c2031364 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -1500,11 +1500,17 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         pat_src: PatternSource,
         bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
     ) {
+        let is_tuple_struct_pat = matches!(pat.kind, PatKind::TupleStruct(_, _));
+
         // Visit all direct subpatterns of this pattern.
         pat.walk(&mut |pat| {
             debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind);
             match pat.kind {
-                PatKind::Ident(bmode, ident, ref sub) => {
+                // In tuple struct patterns ignore the invalid `ident @ ...`.
+                // It will be handled as an error by the AST lowering.
+                PatKind::Ident(bmode, ident, ref sub)
+                    if !(is_tuple_struct_pat && sub.as_ref().filter(|p| p.is_rest()).is_some()) =>
+                {
                     // First try to resolve the identifier as some existing entity,
                     // then fall back to a fresh binding.
                     let has_sub = sub.is_some();
diff --git a/src/test/ui/issues/issue-74539.rs b/src/test/ui/issues/issue-74539.rs
new file mode 100644
index 00000000000..75632d11c1d
--- /dev/null
+++ b/src/test/ui/issues/issue-74539.rs
@@ -0,0 +1,12 @@
+enum E {
+    A(u8, u8),
+}
+
+fn main() {
+    let e = E::A(2, 3);
+    match e {
+        E::A(x @ ..) => {  //~ ERROR `x @` is not allowed in a tuple
+            x //~ ERROR cannot find value `x` in this scope
+        }
+    };
+}
diff --git a/src/test/ui/issues/issue-74539.stderr b/src/test/ui/issues/issue-74539.stderr
new file mode 100644
index 00000000000..94526dcd7cb
--- /dev/null
+++ b/src/test/ui/issues/issue-74539.stderr
@@ -0,0 +1,21 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-74539.rs:9:13
+   |
+LL |             x
+   |             ^ help: a local variable with a similar name exists: `e`
+
+error: `x @` is not allowed in a tuple struct
+  --> $DIR/issue-74539.rs:8:14
+   |
+LL |         E::A(x @ ..) => {
+   |              ^^^^^^ this is only allowed in slice patterns
+   |
+   = help: remove this and bind each tuple field independently
+help: if you don't need to use the contents of x, discard the tuple's remaining fields
+   |
+LL |         E::A(..) => {
+   |              ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.