Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ICEs with @ .. binding #74963

Merged
merged 2 commits into from
Aug 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/librustc_ast_lowering/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -128,7 +127,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
Applicability::MaybeIncorrect,
)
.emit();
break;
}
_ => {}
}
Expand Down
26 changes: 7 additions & 19 deletions src/librustc_resolve/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1510,30 +1510,18 @@ 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) => {
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));
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/issues/issue-72574-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ fn main() {
}
}
//~^^^^ ERROR `_x @` is not allowed in a tuple
//~| ERROR: `..` patterns are not allowed here
//~| ERROR: mismatched types
22 changes: 21 additions & 1 deletion src/test/ui/issues/issue-72574-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
2 changes: 2 additions & 0 deletions src/test/ui/issues/issue-72574-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 19 additions & 1 deletion src/test/ui/issues/issue-72574-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
12 changes: 0 additions & 12 deletions src/test/ui/issues/issue-74539.rs

This file was deleted.

21 changes: 0 additions & 21 deletions src/test/ui/issues/issue-74539.stderr

This file was deleted.

15 changes: 15 additions & 0 deletions src/test/ui/pattern/issue-74539.rs
Original file line number Diff line number Diff line change
@@ -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
}
};
}
32 changes: 32 additions & 0 deletions src/test/ui/pattern/issue-74539.stderr
Original file line number Diff line number Diff line change
@@ -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`.
7 changes: 7 additions & 0 deletions src/test/ui/pattern/issue-74702.rs
Original file line number Diff line number Diff line change
@@ -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);
}
34 changes: 34 additions & 0 deletions src/test/ui/pattern/issue-74702.stderr
Original file line number Diff line number Diff line change
@@ -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`.
7 changes: 7 additions & 0 deletions src/test/ui/pattern/issue-74954.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// check-pass

fn main() {
if let Some([b'@', filename @ ..]) = Some(b"@abc123") {
println!("filename {:?}", filename);
}
}