Skip to content

Commit ca8640e

Browse files
authored
Rollup merge of #72677 - chrissimpkins:fix-72574, r=estebank
Fix diagnostics for `@ ..` binding pattern in tuples and tuple structs Fixes #72574 Associated #72534 #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
2 parents 7624ac7 + 27ed143 commit ca8640e

File tree

5 files changed

+76
-3
lines changed

5 files changed

+76
-3
lines changed

src/librustc_ast_lowering/pat.rs

+30-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use super::{ImplTraitContext, LoweringContext, ParamMode};
33
use rustc_ast::ast::*;
44
use rustc_ast::ptr::P;
55
use rustc_data_structures::stack::ensure_sufficient_stack;
6+
use rustc_errors::Applicability;
67
use rustc_hir as hir;
78
use rustc_hir::def::Res;
89
use rustc_span::symbol::Ident;
@@ -102,10 +103,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
102103
// Note that unlike for slice patterns,
103104
// where `xs @ ..` is a legal sub-slice pattern,
104105
// it is not a legal sub-tuple pattern.
105-
if pat.is_rest() {
106-
rest = Some((idx, pat.span));
107-
break;
106+
match pat.kind {
107+
// Found a sub-tuple rest pattern
108+
PatKind::Rest => {
109+
rest = Some((idx, pat.span));
110+
break;
111+
}
112+
// Found a sub-tuple pattern `$binding_mode $ident @ ..`.
113+
// This is not allowed as a sub-tuple pattern
114+
PatKind::Ident(ref _bm, ident, Some(ref sub)) if sub.is_rest() => {
115+
rest = Some((idx, pat.span));
116+
let sp = pat.span;
117+
self.diagnostic()
118+
.struct_span_err(
119+
sp,
120+
&format!("`{} @` is not allowed in a {}", ident.name, ctx),
121+
)
122+
.span_label(sp, "this is only allowed in slice patterns")
123+
.help("remove this and bind each tuple field independently")
124+
.span_suggestion_verbose(
125+
sp,
126+
&format!("if you don't need to use the contents of {}, discard the tuple's remaining fields", ident),
127+
"..".to_string(),
128+
Applicability::MaybeIncorrect,
129+
)
130+
.emit();
131+
break;
132+
}
133+
_ => {}
108134
}
135+
109136
// It was not a sub-tuple pattern so lower it normally.
110137
elems.push(self.lower_pat(pat));
111138
}

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

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn main() {
2+
let x = (1, 2, 3);
3+
match x {
4+
(_a, _x @ ..) => {}
5+
_ => {}
6+
}
7+
}
8+
//~^^^^ ERROR `_x @` is not allowed in a tuple
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: `_x @` is not allowed in a tuple
2+
--> $DIR/issue-72574-1.rs:4:14
3+
|
4+
LL | (_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 | (_a, ..) => {}
11+
| ^^
12+
13+
error: aborting due to previous error
14+

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

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
struct Binder(i32, i32, i32);
2+
3+
fn main() {
4+
let x = Binder(1, 2, 3);
5+
match x {
6+
Binder(_a, _x @ ..) => {}
7+
_ => {}
8+
}
9+
}
10+
//~^^^^ ERROR `_x @` is not allowed in a tuple struct
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: `_x @` is not allowed in a tuple struct
2+
--> $DIR/issue-72574-2.rs:6:20
3+
|
4+
LL | Binder(_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 | Binder(_a, ..) => {}
11+
| ^^
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)