Rollup merge of #72677 - chrissimpkins:fix-72574, r=estebank
Fix diagnostics for `@ ..` binding pattern in tuples and tuple structs Fixes #72574 Associated https://github.com/rust-lang/rust/pull/72534 https://github.com/rust-lang/rust/issues/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
This commit is contained in:
commit
ca8640e128
5 changed files with 76 additions and 3 deletions
|
|
@ -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;
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
8
src/test/ui/issues/issue-72574-1.rs
Normal file
8
src/test/ui/issues/issue-72574-1.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
fn main() {
|
||||
let x = (1, 2, 3);
|
||||
match x {
|
||||
(_a, _x @ ..) => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
//~^^^^ ERROR `_x @` is not allowed in a tuple
|
||||
14
src/test/ui/issues/issue-72574-1.stderr
Normal file
14
src/test/ui/issues/issue-72574-1.stderr
Normal file
|
|
@ -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
src/test/ui/issues/issue-72574-2.rs
Normal file
10
src/test/ui/issues/issue-72574-2.rs
Normal file
|
|
@ -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
src/test/ui/issues/issue-72574-2.stderr
Normal file
14
src/test/ui/issues/issue-72574-2.stderr
Normal file
|
|
@ -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
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue