From 27ed143ba9bb96e907f56c9f294c904a2cb26123 Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Fri, 29 May 2020 16:03:46 -0400 Subject: [PATCH] fix diagnostics for `@ ..` binding pattern in tuples and tuple structs fix comment add newline for tidy fmt error... edit suggestion message change the suggestion message to better handle cases with binding modes Apply suggestions from estebank code review Co-authored-by: Esteban Kuber edits to address source review Apply suggestions from estebank code review #2 Co-authored-by: Esteban Kuber update test files --- src/librustc_ast_lowering/pat.rs | 33 ++++++++++++++++++++++--- src/test/ui/issues/issue-72574-1.rs | 8 ++++++ src/test/ui/issues/issue-72574-1.stderr | 14 +++++++++++ src/test/ui/issues/issue-72574-2.rs | 10 ++++++++ src/test/ui/issues/issue-72574-2.stderr | 14 +++++++++++ 5 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/issues/issue-72574-1.rs create mode 100644 src/test/ui/issues/issue-72574-1.stderr create mode 100644 src/test/ui/issues/issue-72574-2.rs create mode 100644 src/test/ui/issues/issue-72574-2.stderr diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs index 496e401d06124..55c1f80266337 100644 --- a/src/librustc_ast_lowering/pat.rs +++ b/src/librustc_ast_lowering/pat.rs @@ -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)); } diff --git a/src/test/ui/issues/issue-72574-1.rs b/src/test/ui/issues/issue-72574-1.rs new file mode 100644 index 0000000000000..efbb0bfb1508f --- /dev/null +++ b/src/test/ui/issues/issue-72574-1.rs @@ -0,0 +1,8 @@ +fn main() { + let x = (1, 2, 3); + match x { + (_a, _x @ ..) => {} + _ => {} + } +} +//~^^^^ ERROR `_x @` is not allowed in a tuple diff --git a/src/test/ui/issues/issue-72574-1.stderr b/src/test/ui/issues/issue-72574-1.stderr new file mode 100644 index 0000000000000..329f7d008d498 --- /dev/null +++ b/src/test/ui/issues/issue-72574-1.stderr @@ -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 + diff --git a/src/test/ui/issues/issue-72574-2.rs b/src/test/ui/issues/issue-72574-2.rs new file mode 100644 index 0000000000000..0c8f6fcc50889 --- /dev/null +++ b/src/test/ui/issues/issue-72574-2.rs @@ -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 diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr new file mode 100644 index 0000000000000..6faa57bcca6b1 --- /dev/null +++ b/src/test/ui/issues/issue-72574-2.stderr @@ -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 +