diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs index 55c1f802663..171856e7e63 100644 --- a/src/librustc_ast_lowering/pat.rs +++ b/src/librustc_ast_lowering/pat.rs @@ -112,7 +112,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Found a sub-tuple pattern `$binding_mode $ident @ ..`. // This is not allowed as a sub-tuple pattern PatKind::Ident(ref _bm, ident, Some(ref sub)) if sub.is_rest() => { - rest = Some((idx, pat.span)); let sp = pat.span; self.diagnostic() .struct_span_err( @@ -128,7 +127,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Applicability::MaybeIncorrect, ) .emit(); - break; } _ => {} } diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 9650c0b2d11..44ff4209095 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1510,30 +1510,18 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { pat_src: PatternSource, bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet); 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) => { - if is_tuple_struct_pat && sub.as_ref().filter(|p| p.is_rest()).is_some() { - // In tuple struct patterns ignore the invalid `ident @ ...`. - // It will be handled as an error by the AST lowering. - self.r - .session - .delay_span_bug(ident.span, "ident in tuple pattern is invalid"); - } else { - // First try to resolve the identifier as some existing entity, - // then fall back to a fresh binding. - let has_sub = sub.is_some(); - let res = self - .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub) - .unwrap_or_else(|| { - self.fresh_binding(ident, pat.id, pat_src, bindings) - }); - self.r.record_partial_res(pat.id, PartialRes::new(res)); - } + // First try to resolve the identifier as some existing entity, + // then fall back to a fresh binding. + let has_sub = sub.is_some(); + let res = self + .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub) + .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings)); + self.r.record_partial_res(pat.id, PartialRes::new(res)); } PatKind::TupleStruct(ref path, ..) => { self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct(pat.span)); diff --git a/src/test/ui/issues/issue-72574-1.rs b/src/test/ui/issues/issue-72574-1.rs index efbb0bfb150..1b80a21793a 100644 --- a/src/test/ui/issues/issue-72574-1.rs +++ b/src/test/ui/issues/issue-72574-1.rs @@ -6,3 +6,5 @@ fn main() { } } //~^^^^ ERROR `_x @` is not allowed in a tuple +//~| ERROR: `..` patterns are not allowed here +//~| ERROR: mismatched types diff --git a/src/test/ui/issues/issue-72574-1.stderr b/src/test/ui/issues/issue-72574-1.stderr index 329f7d008d4..92ebb45e88d 100644 --- a/src/test/ui/issues/issue-72574-1.stderr +++ b/src/test/ui/issues/issue-72574-1.stderr @@ -10,5 +10,25 @@ help: if you don't need to use the contents of _x, discard the tuple's remaining LL | (_a, ..) => {} | ^^ -error: aborting due to previous error +error: `..` patterns are not allowed here + --> $DIR/issue-72574-1.rs:4:19 + | +LL | (_a, _x @ ..) => {} + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns +error[E0308]: mismatched types + --> $DIR/issue-72574-1.rs:4:9 + | +LL | match x { + | - this expression has type `({integer}, {integer}, {integer})` +LL | (_a, _x @ ..) => {} + | ^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 2 elements + | + = note: expected tuple `({integer}, {integer}, {integer})` + found tuple `(_, _)` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-72574-2.rs b/src/test/ui/issues/issue-72574-2.rs index 0c8f6fcc508..0ad2db848b2 100644 --- a/src/test/ui/issues/issue-72574-2.rs +++ b/src/test/ui/issues/issue-72574-2.rs @@ -8,3 +8,5 @@ fn main() { } } //~^^^^ ERROR `_x @` is not allowed in a tuple struct +//~| ERROR: `..` patterns are not allowed here +//~| ERROR: this pattern has 2 fields, but the corresponding tuple struct has 3 fields diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr index 6faa57bcca6..0a9c868af7a 100644 --- a/src/test/ui/issues/issue-72574-2.stderr +++ b/src/test/ui/issues/issue-72574-2.stderr @@ -10,5 +10,23 @@ help: if you don't need to use the contents of _x, discard the tuple's remaining LL | Binder(_a, ..) => {} | ^^ -error: aborting due to previous error +error: `..` patterns are not allowed here + --> $DIR/issue-72574-2.rs:6:25 + | +LL | Binder(_a, _x @ ..) => {} + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns +error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields + --> $DIR/issue-72574-2.rs:6:9 + | +LL | struct Binder(i32, i32, i32); + | ----------------------------- tuple struct defined here +... +LL | Binder(_a, _x @ ..) => {} + | ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2 + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0023`. diff --git a/src/test/ui/issues/issue-74539.rs b/src/test/ui/issues/issue-74539.rs deleted file mode 100644 index 75632d11c1d..00000000000 --- a/src/test/ui/issues/issue-74539.rs +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index 94526dcd7cb..00000000000 --- a/src/test/ui/issues/issue-74539.stderr +++ /dev/null @@ -1,21 +0,0 @@ -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`. diff --git a/src/test/ui/pattern/issue-74539.rs b/src/test/ui/pattern/issue-74539.rs new file mode 100644 index 00000000000..0b25f87ec53 --- /dev/null +++ b/src/test/ui/pattern/issue-74539.rs @@ -0,0 +1,15 @@ +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 struct + //~| ERROR: `..` patterns are not allowed here + //~| ERROR: this pattern has 1 field, but the corresponding tuple variant has 2 fields + x + } + }; +} diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr new file mode 100644 index 00000000000..cbc90b5397d --- /dev/null +++ b/src/test/ui/pattern/issue-74539.stderr @@ -0,0 +1,32 @@ +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: `..` patterns are not allowed here + --> $DIR/issue-74539.rs:8:18 + | +LL | E::A(x @ ..) => { + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields + --> $DIR/issue-74539.rs:8:9 + | +LL | A(u8, u8), + | --------- tuple variant defined here +... +LL | E::A(x @ ..) => { + | ^^^^^^^^^^^^ expected 2 fields, found 1 + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0023`. diff --git a/src/test/ui/pattern/issue-74702.rs b/src/test/ui/pattern/issue-74702.rs new file mode 100644 index 00000000000..0aeb3b217a2 --- /dev/null +++ b/src/test/ui/pattern/issue-74702.rs @@ -0,0 +1,7 @@ +fn main() { + let (foo @ ..,) = (0, 0); + //~^ ERROR: `foo @` is not allowed in a tuple + //~| ERROR: `..` patterns are not allowed here + //~| ERROR: mismatched types + dbg!(foo); +} diff --git a/src/test/ui/pattern/issue-74702.stderr b/src/test/ui/pattern/issue-74702.stderr new file mode 100644 index 00000000000..aca5c9aed96 --- /dev/null +++ b/src/test/ui/pattern/issue-74702.stderr @@ -0,0 +1,34 @@ +error: `foo @` is not allowed in a tuple + --> $DIR/issue-74702.rs:2:10 + | +LL | let (foo @ ..,) = (0, 0); + | ^^^^^^^^ 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 foo, discard the tuple's remaining fields + | +LL | let (..,) = (0, 0); + | ^^ + +error: `..` patterns are not allowed here + --> $DIR/issue-74702.rs:2:16 + | +LL | let (foo @ ..,) = (0, 0); + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error[E0308]: mismatched types + --> $DIR/issue-74702.rs:2:9 + | +LL | let (foo @ ..,) = (0, 0); + | ^^^^^^^^^^^ ------ this expression has type `({integer}, {integer})` + | | + | expected a tuple with 2 elements, found one with 1 element + | + = note: expected tuple `({integer}, {integer})` + found tuple `(_,)` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/pattern/issue-74954.rs b/src/test/ui/pattern/issue-74954.rs new file mode 100644 index 00000000000..269ec3c7abe --- /dev/null +++ b/src/test/ui/pattern/issue-74954.rs @@ -0,0 +1,7 @@ +// check-pass + +fn main() { + if let Some([b'@', filename @ ..]) = Some(b"@abc123") { + println!("filename {:?}", filename); + } +}