Skip to content

Commit 19cefa6

Browse files
committed
Auto merge of #74963 - JohnTitor:ptn-ice, r=petrochenkov
Fix ICEs with `@ ..` binding This reverts #74557 and introduces an alternative fix while ensuring that #74954 is not broken. The diagnostics are verbose though, it fixes three related issues. cc #74954, #74539, and #74702
2 parents a99ae95 + c2afce4 commit 19cefa6

13 files changed

+146
-56
lines changed

src/librustc_ast_lowering/pat.rs

-2
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
112112
// Found a sub-tuple pattern `$binding_mode $ident @ ..`.
113113
// This is not allowed as a sub-tuple pattern
114114
PatKind::Ident(ref _bm, ident, Some(ref sub)) if sub.is_rest() => {
115-
rest = Some((idx, pat.span));
116115
let sp = pat.span;
117116
self.diagnostic()
118117
.struct_span_err(
@@ -128,7 +127,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
128127
Applicability::MaybeIncorrect,
129128
)
130129
.emit();
131-
break;
132130
}
133131
_ => {}
134132
}

src/librustc_resolve/late.rs

+7-19
Original file line numberDiff line numberDiff line change
@@ -1510,30 +1510,18 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
15101510
pat_src: PatternSource,
15111511
bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
15121512
) {
1513-
let is_tuple_struct_pat = matches!(pat.kind, PatKind::TupleStruct(_, _));
1514-
15151513
// Visit all direct subpatterns of this pattern.
15161514
pat.walk(&mut |pat| {
15171515
debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind);
15181516
match pat.kind {
15191517
PatKind::Ident(bmode, ident, ref sub) => {
1520-
if is_tuple_struct_pat && sub.as_ref().filter(|p| p.is_rest()).is_some() {
1521-
// In tuple struct patterns ignore the invalid `ident @ ...`.
1522-
// It will be handled as an error by the AST lowering.
1523-
self.r
1524-
.session
1525-
.delay_span_bug(ident.span, "ident in tuple pattern is invalid");
1526-
} else {
1527-
// First try to resolve the identifier as some existing entity,
1528-
// then fall back to a fresh binding.
1529-
let has_sub = sub.is_some();
1530-
let res = self
1531-
.try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
1532-
.unwrap_or_else(|| {
1533-
self.fresh_binding(ident, pat.id, pat_src, bindings)
1534-
});
1535-
self.r.record_partial_res(pat.id, PartialRes::new(res));
1536-
}
1518+
// First try to resolve the identifier as some existing entity,
1519+
// then fall back to a fresh binding.
1520+
let has_sub = sub.is_some();
1521+
let res = self
1522+
.try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
1523+
.unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
1524+
self.r.record_partial_res(pat.id, PartialRes::new(res));
15371525
}
15381526
PatKind::TupleStruct(ref path, ..) => {
15391527
self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct(pat.span));

src/test/ui/issues/issue-72574-1.rs

+2
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ fn main() {
66
}
77
}
88
//~^^^^ ERROR `_x @` is not allowed in a tuple
9+
//~| ERROR: `..` patterns are not allowed here
10+
//~| ERROR: mismatched types

src/test/ui/issues/issue-72574-1.stderr

+21-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,25 @@ help: if you don't need to use the contents of _x, discard the tuple's remaining
1010
LL | (_a, ..) => {}
1111
| ^^
1212

13-
error: aborting due to previous error
13+
error: `..` patterns are not allowed here
14+
--> $DIR/issue-72574-1.rs:4:19
15+
|
16+
LL | (_a, _x @ ..) => {}
17+
| ^^
18+
|
19+
= note: only allowed in tuple, tuple struct, and slice patterns
20+
21+
error[E0308]: mismatched types
22+
--> $DIR/issue-72574-1.rs:4:9
23+
|
24+
LL | match x {
25+
| - this expression has type `({integer}, {integer}, {integer})`
26+
LL | (_a, _x @ ..) => {}
27+
| ^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 2 elements
28+
|
29+
= note: expected tuple `({integer}, {integer}, {integer})`
30+
found tuple `(_, _)`
31+
32+
error: aborting due to 3 previous errors
1433

34+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/issues/issue-72574-2.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ fn main() {
88
}
99
}
1010
//~^^^^ ERROR `_x @` is not allowed in a tuple struct
11+
//~| ERROR: `..` patterns are not allowed here
12+
//~| ERROR: this pattern has 2 fields, but the corresponding tuple struct has 3 fields

src/test/ui/issues/issue-72574-2.stderr

+19-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,23 @@ help: if you don't need to use the contents of _x, discard the tuple's remaining
1010
LL | Binder(_a, ..) => {}
1111
| ^^
1212

13-
error: aborting due to previous error
13+
error: `..` patterns are not allowed here
14+
--> $DIR/issue-72574-2.rs:6:25
15+
|
16+
LL | Binder(_a, _x @ ..) => {}
17+
| ^^
18+
|
19+
= note: only allowed in tuple, tuple struct, and slice patterns
20+
21+
error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
22+
--> $DIR/issue-72574-2.rs:6:9
23+
|
24+
LL | struct Binder(i32, i32, i32);
25+
| ----------------------------- tuple struct defined here
26+
...
27+
LL | Binder(_a, _x @ ..) => {}
28+
| ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2
29+
30+
error: aborting due to 3 previous errors
1431

32+
For more information about this error, try `rustc --explain E0023`.

src/test/ui/issues/issue-74539.rs

-12
This file was deleted.

src/test/ui/issues/issue-74539.stderr

-21
This file was deleted.

src/test/ui/pattern/issue-74539.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
enum E {
2+
A(u8, u8),
3+
}
4+
5+
fn main() {
6+
let e = E::A(2, 3);
7+
match e {
8+
E::A(x @ ..) => {
9+
//~^ ERROR: `x @` is not allowed in a tuple struct
10+
//~| ERROR: `..` patterns are not allowed here
11+
//~| ERROR: this pattern has 1 field, but the corresponding tuple variant has 2 fields
12+
x
13+
}
14+
};
15+
}
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
error: `x @` is not allowed in a tuple struct
2+
--> $DIR/issue-74539.rs:8:14
3+
|
4+
LL | E::A(x @ ..) => {
5+
| ^^^^^^ this is only allowed in slice patterns
6+
|
7+
= help: remove this and bind each tuple field independently
8+
help: if you don't need to use the contents of x, discard the tuple's remaining fields
9+
|
10+
LL | E::A(..) => {
11+
| ^^
12+
13+
error: `..` patterns are not allowed here
14+
--> $DIR/issue-74539.rs:8:18
15+
|
16+
LL | E::A(x @ ..) => {
17+
| ^^
18+
|
19+
= note: only allowed in tuple, tuple struct, and slice patterns
20+
21+
error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
22+
--> $DIR/issue-74539.rs:8:9
23+
|
24+
LL | A(u8, u8),
25+
| --------- tuple variant defined here
26+
...
27+
LL | E::A(x @ ..) => {
28+
| ^^^^^^^^^^^^ expected 2 fields, found 1
29+
30+
error: aborting due to 3 previous errors
31+
32+
For more information about this error, try `rustc --explain E0023`.

src/test/ui/pattern/issue-74702.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
let (foo @ ..,) = (0, 0);
3+
//~^ ERROR: `foo @` is not allowed in a tuple
4+
//~| ERROR: `..` patterns are not allowed here
5+
//~| ERROR: mismatched types
6+
dbg!(foo);
7+
}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
error: `foo @` is not allowed in a tuple
2+
--> $DIR/issue-74702.rs:2:10
3+
|
4+
LL | let (foo @ ..,) = (0, 0);
5+
| ^^^^^^^^ this is only allowed in slice patterns
6+
|
7+
= help: remove this and bind each tuple field independently
8+
help: if you don't need to use the contents of foo, discard the tuple's remaining fields
9+
|
10+
LL | let (..,) = (0, 0);
11+
| ^^
12+
13+
error: `..` patterns are not allowed here
14+
--> $DIR/issue-74702.rs:2:16
15+
|
16+
LL | let (foo @ ..,) = (0, 0);
17+
| ^^
18+
|
19+
= note: only allowed in tuple, tuple struct, and slice patterns
20+
21+
error[E0308]: mismatched types
22+
--> $DIR/issue-74702.rs:2:9
23+
|
24+
LL | let (foo @ ..,) = (0, 0);
25+
| ^^^^^^^^^^^ ------ this expression has type `({integer}, {integer})`
26+
| |
27+
| expected a tuple with 2 elements, found one with 1 element
28+
|
29+
= note: expected tuple `({integer}, {integer})`
30+
found tuple `(_,)`
31+
32+
error: aborting due to 3 previous errors
33+
34+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/pattern/issue-74954.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// check-pass
2+
3+
fn main() {
4+
if let Some([b'@', filename @ ..]) = Some(b"@abc123") {
5+
println!("filename {:?}", filename);
6+
}
7+
}

0 commit comments

Comments
 (0)