Skip to content

Commit

Permalink
Rollup merge of rust-lang#72677 - chrissimpkins:fix-72574, r=estebank
Browse files Browse the repository at this point in the history
Fix diagnostics for `@ ..` binding pattern in tuples and tuple structs

Fixes rust-lang#72574
Associated rust-lang#72534 rust-lang#72373

Includes a new suggestion with `Applicability::MaybeIncorrect` confidence level.

### Before

#### tuple

```
error: `..` patterns are not allowed here
 --> src/main.rs:4:19
  |
4 |         (_a, _x @ ..) => {}
  |                   ^^
  |
  = note: only allowed in tuple, tuple struct, and slice patterns

error[E0308]: mismatched types
 --> src/main.rs:4:9
  |
3 |     match x {
  |           - this expression has type `({integer}, {integer}, {integer})`
4 |         (_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 2 previous errors
```

#### tuple struct

```
error: `..` patterns are not allowed here
 --> src/main.rs:6:25
  |
6 |         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
 --> src/main.rs:6:9
  |
1 | struct Binder(i32, i32, i32);
  | ----------------------------- tuple struct defined here
...
6 |         Binder(_a, _x @ ..) => {}
  |         ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2

error: aborting due to 2 previous errors
```

### After

*Note: final output edited during source review discussion, see thread for details*

#### tuple

```
error: `_x @` is not allowed in a tuple
 --> src/main.rs:4:14
  |
4 |         (_a, _x @ ..) => {}
  |              ^^^^^^^ is only allowed in a slice
  |
help: replace with `..` or use a different valid pattern
  |
4 |         (_a, ..) => {}
  |              ^^

error[E0308]: mismatched types
 --> src/main.rs:4:9
  |
3 |     match x {
  |           - this expression has type `({integer}, {integer}, {integer})`
4 |         (_a, _x @ ..) => {}
  |         ^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 1 element
  |
  = note: expected tuple `({integer}, {integer}, {integer})`
             found tuple `(_,)`

error: aborting due to 2 previous errors
```

#### tuple struct

```
error: `_x @` is not allowed in a tuple struct
 --> src/main.rs:6:20
  |
6 |         Binder(_a, _x @ ..) => {}
  |                    ^^^^^^^ is only allowed in a slice
  |
help: replace with `..` or use a different valid pattern
  |
6 |         Binder(_a, ..) => {}
  |                    ^^

error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 3 fields
 --> src/main.rs:6:9
  |
1 | struct Binder(i32, i32, i32);
  | ----------------------------- tuple struct defined here
...
6 |         Binder(_a, _x @ ..) => {}
  |         ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 1

error: aborting due to 2 previous errors
```

r? @estebank
  • Loading branch information
JohnTitor committed May 30, 2020
2 parents 7624ac7 + 27ed143 commit ca8640e
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 3 deletions.
33 changes: 30 additions & 3 deletions src/librustc_ast_lowering/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::{ImplTraitContext, LoweringContext, ParamMode};
use rustc_ast::ast::*;
use rustc_ast::ptr::P;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_span::symbol::Ident;
Expand Down Expand Up @@ -102,10 +103,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Note that unlike for slice patterns,
// where `xs @ ..` is a legal sub-slice pattern,
// it is not a legal sub-tuple pattern.
if pat.is_rest() {
rest = Some((idx, pat.span));
break;
match pat.kind {
// Found a sub-tuple rest pattern
PatKind::Rest => {
rest = Some((idx, pat.span));
break;
}
// 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(
sp,
&format!("`{} @` is not allowed in a {}", ident.name, ctx),
)
.span_label(sp, "this is only allowed in slice patterns")
.help("remove this and bind each tuple field independently")
.span_suggestion_verbose(
sp,
&format!("if you don't need to use the contents of {}, discard the tuple's remaining fields", ident),
"..".to_string(),
Applicability::MaybeIncorrect,
)
.emit();
break;
}
_ => {}
}

// It was not a sub-tuple pattern so lower it normally.
elems.push(self.lower_pat(pat));
}
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/issues/issue-72574-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn main() {
let x = (1, 2, 3);
match x {
(_a, _x @ ..) => {}
_ => {}
}
}
//~^^^^ ERROR `_x @` is not allowed in a tuple
14 changes: 14 additions & 0 deletions src/test/ui/issues/issue-72574-1.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: `_x @` is not allowed in a tuple
--> $DIR/issue-72574-1.rs:4:14
|
LL | (_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 | (_a, ..) => {}
| ^^

error: aborting due to previous error

10 changes: 10 additions & 0 deletions src/test/ui/issues/issue-72574-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
struct Binder(i32, i32, i32);

fn main() {
let x = Binder(1, 2, 3);
match x {
Binder(_a, _x @ ..) => {}
_ => {}
}
}
//~^^^^ ERROR `_x @` is not allowed in a tuple struct
14 changes: 14 additions & 0 deletions src/test/ui/issues/issue-72574-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: `_x @` is not allowed in a tuple struct
--> $DIR/issue-72574-2.rs:6:20
|
LL | Binder(_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 | Binder(_a, ..) => {}
| ^^

error: aborting due to previous error

0 comments on commit ca8640e

Please sign in to comment.