Change:
and I are working on diagnostics for the rest idiom in slice patterns () and came across this issue when an attempt is made to use it in tuples and tuple structs. IIUC, this is allowed: and this is not allowed (note the addition of ): The error messages for the tuple and tuple struct cases include the following incorrect information: This should state that the id binding to rest is not allowed. patterns are allowed. is only allowed in slice patterns, not in tuple or tuple struct patterns. This should state that the idiom is only allowed in slice patterns. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
appears to be the site of the check: This method is called:
Perhaps it's worth supporting "tuple slicing" pattern too in Rust:
that would implicitly create a tuple for (or a slice?). I don't think it'd be a good addition. We already support , which is much more useful in my eyes.
That syntax is meant to produce a shorter tuple xs with the omission of the first item of the tuple. lf you think it's an useless idea then let's ignore it :)
claim

Discussion:
use rustc_ast::ast::*; use rustc_ast::ptr::P; use rustc_data_structures::stack::ensure_sufficient_stack; <ins> use rustc_errors::Applicability; </ins> use rustc_hir as hir; use rustc_hir::def::Res; use rustc_span::symbol::Ident;

// Note that unlike for slice patterns, // where `xs @ ..` is a legal sub-slice pattern, // it is not a legal sub-tuple pattern. <del> if pat.is_rest() { rest = Some((idx, pat.span)); break; </del> <ins> 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; } _ => {} </ins> } // It was not a sub-tuple pattern so lower it normally. elems.push(self.lower_pat(pat)); }

<ins> fn main() { let x = (1, 2, 3); match x { (_a, _x @ ..) => {} _ => {} } } //~^^^^ ERROR `_x @` is not allowed in a tuple </ins>

<ins> 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 </ins>

<ins> 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 </ins>

<ins> 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 </ins>