about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2021-08-26 12:38:06 -0700
committerGitHub <noreply@github.com>2021-08-26 12:38:06 -0700
commit8aa46e51dfc20f6bc01207d67a5f666239ed8e07 (patch)
tree7fadae32b3ab315d7f23f275a749fbe9b9d8b788
parentfb7959774c9a7050c1061bd8d7825d78e1945ea9 (diff)
parent8a6501d28831d864a3af6adf2e0bd83a773062ed (diff)
downloadrust-8aa46e51dfc20f6bc01207d67a5f666239ed8e07.tar.gz
rust-8aa46e51dfc20f6bc01207d67a5f666239ed8e07.zip
Rollup merge of #88123 - camelid:tup-pat-precise-spans, r=estebank
Make spans for tuple patterns in E0023 more precise

As suggested in #86307. Closes #86307.

r? ````@estebank````
-rw-r--r--compiler/rustc_hir/src/hir.rs35
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs13
-rw-r--r--compiler/rustc_typeck/src/check/pat.rs39
-rw-r--r--src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr24
-rw-r--r--src/test/ui/error-codes/E0023.stderr26
-rw-r--r--src/test/ui/issues/issue-72574-2.stderr6
-rw-r--r--src/test/ui/match/match-pattern-field-mismatch.stderr6
-rw-r--r--src/test/ui/pattern/auxiliary/declarations-for-tuple-field-count-errors.rs20
-rw-r--r--src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr2
-rw-r--r--src/test/ui/pattern/issue-74539.stderr6
-rw-r--r--src/test/ui/pattern/pat-tuple-field-count-cross.rs57
-rw-r--r--src/test/ui/pattern/pat-tuple-field-count-cross.stderr536
-rw-r--r--src/test/ui/pattern/pat-tuple-overfield.rs58
-rw-r--r--src/test/ui/pattern/pat-tuple-overfield.stderr284
-rw-r--r--src/test/ui/pattern/pat-tuple-underfield.rs12
-rw-r--r--src/test/ui/pattern/pat-tuple-underfield.stderr76
-rw-r--r--src/test/ui/pattern/pattern-error-continue.stderr6
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr6
-rw-r--r--src/test/ui/typeck/struct-enum-wrong-args.stderr30
19 files changed, 1165 insertions, 77 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 38deb8eaaae..551e6a57b32 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3183,6 +3183,20 @@ pub enum Node<'hir> {
 }
 
 impl<'hir> Node<'hir> {
+    /// Get the identifier of this `Node`, if applicable.
+    ///
+    /// # Edge cases
+    ///
+    /// Calling `.ident()` on a [`Node::Ctor`] will return `None`
+    /// because `Ctor`s do not have identifiers themselves.
+    /// Instead, call `.ident()` on the parent struct/variant, like so:
+    ///
+    /// ```ignore (illustrative)
+    /// ctor
+    ///     .ctor_hir_id()
+    ///     .and_then(|ctor_id| tcx.hir().find(tcx.hir().get_parent_node(ctor_id)))
+    ///     .and_then(|parent| parent.ident())
+    /// ```
     pub fn ident(&self) -> Option<Ident> {
         match self {
             Node::TraitItem(TraitItem { ident, .. })
@@ -3191,8 +3205,25 @@ impl<'hir> Node<'hir> {
             | Node::Field(FieldDef { ident, .. })
             | Node::Variant(Variant { ident, .. })
             | Node::MacroDef(MacroDef { ident, .. })
-            | Node::Item(Item { ident, .. }) => Some(*ident),
-            _ => None,
+            | Node::Item(Item { ident, .. })
+            | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
+            Node::Lifetime(lt) => Some(lt.name.ident()),
+            Node::GenericParam(p) => Some(p.name.ident()),
+            Node::Param(..)
+            | Node::AnonConst(..)
+            | Node::Expr(..)
+            | Node::Stmt(..)
+            | Node::Block(..)
+            | Node::Ctor(..)
+            | Node::Pat(..)
+            | Node::Binding(..)
+            | Node::Arm(..)
+            | Node::Local(..)
+            | Node::Visibility(..)
+            | Node::Crate(..)
+            | Node::Ty(..)
+            | Node::TraitRef(..)
+            | Node::Infer(..) => None,
         }
     }
 
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 8332e738411..c10f6dc3401 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -223,7 +223,18 @@ fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> {
 }
 
 fn def_ident_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
-    tcx.hir().get_if_local(def_id).and_then(|node| node.ident()).map(|ident| ident.span)
+    tcx.hir()
+        .get_if_local(def_id)
+        .and_then(|node| match node {
+            // A `Ctor` doesn't have an identifier itself, but its parent
+            // struct/variant does. Compare with `hir::Map::opt_span`.
+            hir::Node::Ctor(ctor) => ctor
+                .ctor_hir_id()
+                .and_then(|ctor_id| tcx.hir().find(tcx.hir().get_parent_node(ctor_id)))
+                .and_then(|parent| parent.ident()),
+            _ => node.ident(),
+        })
+        .map(|ident| ident.span)
 }
 
 /// If the given `DefId` describes an item belonging to a trait,
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 392262628c0..016b3f7a87c 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -15,7 +15,7 @@ use rustc_span::hygiene::DesugaringKind;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::Ident;
-use rustc_span::{BytePos, DUMMY_SP};
+use rustc_span::{BytePos, MultiSpan, DUMMY_SP};
 use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::traits::{ObligationCause, Pattern};
 use ty::VariantDef;
@@ -990,10 +990,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         let subpats_ending = pluralize!(subpats.len());
         let fields_ending = pluralize!(fields.len());
+
+        let subpat_spans = if subpats.is_empty() {
+            vec![pat_span]
+        } else {
+            subpats.iter().map(|p| p.span).collect()
+        };
+        let last_subpat_span = *subpat_spans.last().unwrap();
         let res_span = self.tcx.def_span(res.def_id());
+        let def_ident_span = self.tcx.def_ident_span(res.def_id()).unwrap_or(res_span);
+        let field_def_spans = if fields.is_empty() {
+            vec![res_span]
+        } else {
+            fields.iter().map(|f| f.ident.span).collect()
+        };
+        let last_field_def_span = *field_def_spans.last().unwrap();
+
         let mut err = struct_span_err!(
             self.tcx.sess,
-            pat_span,
+            MultiSpan::from_spans(subpat_spans.clone()),
             E0023,
             "this pattern has {} field{}, but the corresponding {} has {} field{}",
             subpats.len(),
@@ -1003,10 +1018,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             fields_ending,
         );
         err.span_label(
-            pat_span,
-            format!("expected {} field{}, found {}", fields.len(), fields_ending, subpats.len(),),
-        )
-        .span_label(res_span, format!("{} defined here", res.descr()));
+            last_subpat_span,
+            &format!("expected {} field{}, found {}", fields.len(), fields_ending, subpats.len()),
+        );
+        if self.tcx.sess.source_map().is_multiline(qpath.span().between(last_subpat_span)) {
+            err.span_label(qpath.span(), "");
+        }
+        if self.tcx.sess.source_map().is_multiline(def_ident_span.between(last_field_def_span)) {
+            err.span_label(def_ident_span, format!("{} defined here", res.descr()));
+        }
+        for span in &field_def_spans[..field_def_spans.len() - 1] {
+            err.span_label(*span, "");
+        }
+        err.span_label(
+            last_field_def_span,
+            &format!("{} has {} field{}", res.descr(), fields.len(), fields_ending),
+        );
 
         // Identify the case `Some(x, y)` where the expected type is e.g. `Option<(T, U)>`.
         // More generally, the expected type wants a tuple variant with one field of an
diff --git a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr
index 0e92cc5c9f2..9aae4b0a3fa 100644
--- a/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr
+++ b/src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr
@@ -15,22 +15,22 @@ LL |     Enum::SingleVariant(a, .., b, ..) = Enum::SingleVariant(0, 1);
    |                            previously used here
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple struct has 2 fields
-  --> $DIR/tuple_struct_destructure_fail.rs:30:5
+  --> $DIR/tuple_struct_destructure_fail.rs:30:17
    |
 LL | struct TupleStruct<S, T>(S, T);
-   | ------------------------------- tuple struct defined here
+   |                          -  - tuple struct has 2 fields
 ...
 LL |     TupleStruct(a, a, b) = TupleStruct(1, 2);
-   |     ^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3
+   |                 ^  ^  ^ expected 2 fields, found 3
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields
-  --> $DIR/tuple_struct_destructure_fail.rs:32:5
+  --> $DIR/tuple_struct_destructure_fail.rs:32:17
    |
 LL | struct TupleStruct<S, T>(S, T);
-   | ------------------------------- tuple struct defined here
+   |                          -  - tuple struct has 2 fields
 ...
 LL |     TupleStruct(_) = TupleStruct(1, 2);
-   |     ^^^^^^^^^^^^^^ expected 2 fields, found 1
+   |                 ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -42,22 +42,22 @@ LL |     TupleStruct(..) = TupleStruct(1, 2);
    |                 ~~
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
-  --> $DIR/tuple_struct_destructure_fail.rs:34:5
+  --> $DIR/tuple_struct_destructure_fail.rs:34:25
    |
 LL |     SingleVariant(S, T)
-   |     ------------------- tuple variant defined here
+   |                   -  - tuple variant has 2 fields
 ...
 LL |     Enum::SingleVariant(a, a, b) = Enum::SingleVariant(1, 2);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3
+   |                         ^  ^  ^ expected 2 fields, found 3
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
-  --> $DIR/tuple_struct_destructure_fail.rs:36:5
+  --> $DIR/tuple_struct_destructure_fail.rs:36:25
    |
 LL |     SingleVariant(S, T)
-   |     ------------------- tuple variant defined here
+   |                   -  - tuple variant has 2 fields
 ...
 LL |     Enum::SingleVariant(_) = Enum::SingleVariant(1, 2);
-   |     ^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 1
+   |                         ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr
index ec3aae29714..3e321b037b2 100644
--- a/src/test/ui/error-codes/E0023.stderr
+++ b/src/test/ui/error-codes/E0023.stderr
@@ -1,11 +1,11 @@
 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
-  --> $DIR/E0023.rs:11:9
+  --> $DIR/E0023.rs:11:22
    |
 LL |     Apple(String, String),
-   |     --------------------- tuple variant defined here
+   |           ------  ------ tuple variant has 2 fields
 ...
 LL |         Fruit::Apple(a) => {},
-   |         ^^^^^^^^^^^^^^^ expected 2 fields, found 1
+   |                      ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -13,31 +13,31 @@ LL |         Fruit::Apple(a, _) => {},
    |                       +++
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
-  --> $DIR/E0023.rs:12:9
+  --> $DIR/E0023.rs:12:22
    |
 LL |     Apple(String, String),
-   |     --------------------- tuple variant defined here
+   |           ------  ------ tuple variant has 2 fields
 ...
 LL |         Fruit::Apple(a, b, c) => {},
-   |         ^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3
+   |                      ^  ^  ^ expected 2 fields, found 3
 
 error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field
-  --> $DIR/E0023.rs:13:9
+  --> $DIR/E0023.rs:13:21
    |
 LL |     Pear(u32),
-   |     --------- tuple variant defined here
+   |          --- tuple variant has 1 field
 ...
 LL |         Fruit::Pear(1, 2) => {},
-   |         ^^^^^^^^^^^^^^^^^ expected 1 field, found 2
+   |                     ^  ^ expected 1 field, found 2
 
 error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field
-  --> $DIR/E0023.rs:14:9
+  --> $DIR/E0023.rs:14:23
    |
 LL |     Orange((String, String)),
-   |     ------------------------ tuple variant defined here
+   |            ---------------- tuple variant has 1 field
 ...
 LL |         Fruit::Orange(a, b) => {},
-   |         ^^^^^^^^^^^^^^^^^^^ expected 1 field, found 2
+   |                       ^  ^ expected 1 field, found 2
    |
 help: missing parentheses
    |
@@ -48,7 +48,7 @@ error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has
   --> $DIR/E0023.rs:15:9
    |
 LL |     Banana(()),
-   |     ---------- tuple variant defined here
+   |            -- tuple variant has 1 field
 ...
 LL |         Fruit::Banana() => {},
    |         ^^^^^^^^^^^^^^^ expected 1 field, found 0
diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr
index 928fa58b175..05650f05cbf 100644
--- a/src/test/ui/issues/issue-72574-2.stderr
+++ b/src/test/ui/issues/issue-72574-2.stderr
@@ -19,13 +19,13 @@ LL |         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
-  --> $DIR/issue-72574-2.rs:6:9
+  --> $DIR/issue-72574-2.rs:6:16
    |
 LL | struct Binder(i32, i32, i32);
-   | ----------------------------- tuple struct defined here
+   |               ---  ---  --- tuple struct has 3 fields
 ...
 LL |         Binder(_a, _x @ ..) => {}
-   |         ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2
+   |                ^^  ^^^^^^^ expected 3 fields, found 2
    |
 help: use `_` to explicitly ignore each field
    |
diff --git a/src/test/ui/match/match-pattern-field-mismatch.stderr b/src/test/ui/match/match-pattern-field-mismatch.stderr
index e34164ec0db..c994ee4f6d4 100644
--- a/src/test/ui/match/match-pattern-field-mismatch.stderr
+++ b/src/test/ui/match/match-pattern-field-mismatch.stderr
@@ -1,11 +1,11 @@
 error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
-  --> $DIR/match-pattern-field-mismatch.rs:10:11
+  --> $DIR/match-pattern-field-mismatch.rs:10:22
    |
 LL |         Rgb(usize, usize, usize),
-   |         ------------------------ tuple variant defined here
+   |             -----  -----  ----- tuple variant has 3 fields
 ...
 LL |           Color::Rgb(_, _) => { }
-   |           ^^^^^^^^^^^^^^^^ expected 3 fields, found 2
+   |                      ^  ^ expected 3 fields, found 2
    |
 help: use `_` to explicitly ignore each field
    |
diff --git a/src/test/ui/pattern/auxiliary/declarations-for-tuple-field-count-errors.rs b/src/test/ui/pattern/auxiliary/declarations-for-tuple-field-count-errors.rs
new file mode 100644
index 00000000000..f7373c45396
--- /dev/null
+++ b/src/test/ui/pattern/auxiliary/declarations-for-tuple-field-count-errors.rs
@@ -0,0 +1,20 @@
+pub struct Z0;
+pub struct Z1();
+
+pub struct S(pub u8, pub u8, pub u8);
+pub struct M(
+    pub u8,
+    pub u8,
+    pub u8,
+);
+
+pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+
+pub enum E2 {
+    S(u8, u8, u8),
+    M(
+        u8,
+        u8,
+        u8,
+    ),
+}
diff --git a/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr b/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
index 7f5da8f3c2d..75a231f6b4b 100644
--- a/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
+++ b/src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
@@ -13,7 +13,7 @@ error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has
   --> $DIR/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs:19:9
    |
 LL | struct P<T>(T); // 1 type parameter wanted
-   | --------------- tuple struct defined here
+   |             - tuple struct has 1 field
 ...
 LL |     let P() = U {};
    |         ^^^ expected 1 field, found 0
diff --git a/src/test/ui/pattern/issue-74539.stderr b/src/test/ui/pattern/issue-74539.stderr
index 7d998af7fb3..7443946c013 100644
--- a/src/test/ui/pattern/issue-74539.stderr
+++ b/src/test/ui/pattern/issue-74539.stderr
@@ -19,13 +19,13 @@ LL |         E::A(x @ ..) => {
    = note: only allowed in tuple, tuple struct, and slice patterns
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
-  --> $DIR/issue-74539.rs:8:9
+  --> $DIR/issue-74539.rs:8:14
    |
 LL |     A(u8, u8),
-   |     --------- tuple variant defined here
+   |       --  -- tuple variant has 2 fields
 ...
 LL |         E::A(x @ ..) => {
-   |         ^^^^^^^^^^^^ expected 2 fields, found 1
+   |              ^^^^^^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
diff --git a/src/test/ui/pattern/pat-tuple-field-count-cross.rs b/src/test/ui/pattern/pat-tuple-field-count-cross.rs
new file mode 100644
index 00000000000..b63da4e154f
--- /dev/null
+++ b/src/test/ui/pattern/pat-tuple-field-count-cross.rs
@@ -0,0 +1,57 @@
+// aux-build:declarations-for-tuple-field-count-errors.rs
+
+extern crate declarations_for_tuple_field_count_errors;
+
+use declarations_for_tuple_field_count_errors::*;
+
+fn main() {
+    match Z0 {
+        Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0`
+        Z0(x) => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0`
+    }
+    match Z1() {
+        Z1 => {} //~ ERROR match bindings cannot shadow tuple structs
+        Z1(x) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 0 fields
+    }
+
+    match S(1, 2, 3) {
+        S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple struct has 3 fields
+        S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields
+        S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+        S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+    }
+    match M(1, 2, 3) {
+        M() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple struct has 3 fields
+        M(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields
+        M(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+        M(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+    }
+
+    match E1::Z0 {
+        E1::Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0`
+        E1::Z0(x) => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0`
+    }
+    match E1::Z1() {
+        E1::Z1 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1`
+        E1::Z1(x) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 0 fields
+    }
+    match E1::S(1, 2, 3) {
+        E1::S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+        E1::S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields
+        E1::S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+        E1::S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+    }
+
+    match E2::S(1, 2, 3) {
+        E2::S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+        E2::S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields
+        E2::S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+        E2::S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+    }
+    match E2::M(1, 2, 3) {
+        E2::M() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+        E2::M(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields
+        E2::M(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+        E2::M(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+    }
+}
diff --git a/src/test/ui/pattern/pat-tuple-field-count-cross.stderr b/src/test/ui/pattern/pat-tuple-field-count-cross.stderr
new file mode 100644
index 00000000000..cab8d4759df
--- /dev/null
+++ b/src/test/ui/pattern/pat-tuple-field-count-cross.stderr
@@ -0,0 +1,536 @@
+error[E0530]: match bindings cannot shadow tuple structs
+  --> $DIR/pat-tuple-field-count-cross.rs:13:9
+   |
+LL | use declarations_for_tuple_field_count_errors::*;
+   |     -------------------------------------------- the tuple struct `Z1` is imported here
+...
+LL |         Z1 => {}
+   |         ^^ cannot be named the same as a tuple struct
+
+error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0`
+  --> $DIR/pat-tuple-field-count-cross.rs:9:9
+   |
+LL |         Z0() => {}
+   |         ^^^^
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:1:1
+   |
+LL | pub struct Z0;
+   | -------------- `Z0` defined here
+LL | pub struct Z1();
+   | ---------------- similarly named tuple struct `Z1` defined here
+   |
+help: use this syntax instead
+   |
+LL |         Z0 => {}
+   |         ~~
+help: a tuple struct with a similar name exists
+   |
+LL |         Z1() => {}
+   |         ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0`
+  --> $DIR/pat-tuple-field-count-cross.rs:10:9
+   |
+LL |         Z0(x) => {}
+   |         ^^^^^
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:1:1
+   |
+LL | pub struct Z0;
+   | -------------- `Z0` defined here
+LL | pub struct Z1();
+   | ---------------- similarly named tuple struct `Z1` defined here
+   |
+help: use this syntax instead
+   |
+LL |         Z0 => {}
+   |         ~~
+help: a tuple struct with a similar name exists
+   |
+LL |         Z1(x) => {}
+   |         ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0`
+  --> $DIR/pat-tuple-field-count-cross.rs:31:9
+   |
+LL |         E1::Z0() => {}
+   |         ^^^^^^^^
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:15
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |               --  ---- similarly named tuple variant `Z1` defined here
+   |               |
+   |               `E1::Z0` defined here
+   |
+help: use this syntax instead
+   |
+LL |         E1::Z0 => {}
+   |         ~~~~~~
+help: a tuple variant with a similar name exists
+   |
+LL |         E1::Z1() => {}
+   |             ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0`
+  --> $DIR/pat-tuple-field-count-cross.rs:32:9
+   |
+LL |         E1::Z0(x) => {}
+   |         ^^^^^^^^^
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:15
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |               --  ---- similarly named tuple variant `Z1` defined here
+   |               |
+   |               `E1::Z0` defined here
+   |
+help: use this syntax instead
+   |
+LL |         E1::Z0 => {}
+   |         ~~~~~~
+help: a tuple variant with a similar name exists
+   |
+LL |         E1::Z1(x) => {}
+   |             ~~
+
+error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E1::Z1`
+  --> $DIR/pat-tuple-field-count-cross.rs:35:9
+   |
+LL |         E1::Z1 => {}
+   |         ^^^^^^
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:19
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |               --  ---- `E1::Z1` defined here
+   |               |
+   |               similarly named unit variant `Z0` defined here
+   |
+help: use the tuple variant pattern syntax instead
+   |
+LL |         E1::Z1(/* fields */) => {}
+   |         ~~~~~~~~~~~~~~~~~~~~
+help: a unit variant with a similar name exists
+   |
+LL |         E1::Z0 => {}
+   |             ~~
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 0 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:14:12
+   |
+LL |         Z1(x) => {}
+   |            ^ expected 0 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:2:1
+   |
+LL | pub struct Z1();
+   | ---------------- tuple struct has 0 fields
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:18:9
+   |
+LL |         S() => {}
+   |         ^^^ expected 3 fields, found 0
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14
+   |
+LL | pub struct S(pub u8, pub u8, pub u8);
+   |              ------  ------  ------ tuple struct has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         S(_, _, _) => {}
+   |           +++++++
+help: use `..` to ignore all fields
+   |
+LL |         S(..) => {}
+   |           ++
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:19:11
+   |
+LL |         S(1) => {}
+   |           ^ expected 3 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14
+   |
+LL | pub struct S(pub u8, pub u8, pub u8);
+   |              ------  ------  ------ tuple struct has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         S(1, _, _) => {}
+   |            ++++++
+help: use `..` to ignore the rest of the fields
+   |
+LL |         S(1, ..) => {}
+   |            ++++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:20:11
+   |
+LL |         S(xyz, abc) => {}
+   |           ^^^  ^^^ expected 3 fields, found 2
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14
+   |
+LL | pub struct S(pub u8, pub u8, pub u8);
+   |              ------  ------  ------ tuple struct has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         S(xyz, abc, _) => {}
+   |                   +++
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:21:11
+   |
+LL |         S(1, 2, 3, 4) => {}
+   |           ^  ^  ^  ^ expected 3 fields, found 4
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14
+   |
+LL | pub struct S(pub u8, pub u8, pub u8);
+   |              ------  ------  ------ tuple struct has 3 fields
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:24:9
+   |
+LL |           M() => {}
+   |           ^^^ expected 3 fields, found 0
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:1
+   |
+LL | / pub struct M(
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------ tuple struct has 3 fields
+LL | | );
+   | |__- tuple struct defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         M(_, _, _) => {}
+   |           +++++++
+help: use `..` to ignore all fields
+   |
+LL |         M(..) => {}
+   |           ++
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:25:11
+   |
+LL |           M(1) => {}
+   |             ^ expected 3 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:1
+   |
+LL | / pub struct M(
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------ tuple struct has 3 fields
+LL | | );
+   | |__- tuple struct defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         M(1, _, _) => {}
+   |            ++++++
+help: use `..` to ignore the rest of the fields
+   |
+LL |         M(1, ..) => {}
+   |            ++++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:26:11
+   |
+LL |           M(xyz, abc) => {}
+   |             ^^^  ^^^ expected 3 fields, found 2
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:1
+   |
+LL | / pub struct M(
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------ tuple struct has 3 fields
+LL | | );
+   | |__- tuple struct defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         M(xyz, abc, _) => {}
+   |                   +++
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:27:11
+   |
+LL |           M(1, 2, 3, 4) => {}
+   |             ^  ^  ^  ^ expected 3 fields, found 4
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:1
+   |
+LL | / pub struct M(
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------ tuple struct has 3 fields
+LL | | );
+   | |__- tuple struct defined here
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 0 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:36:16
+   |
+LL |         E1::Z1(x) => {}
+   |                ^ expected 0 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:19
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |                   ---- tuple variant has 0 fields
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:39:9
+   |
+LL |         E1::S() => {}
+   |         ^^^^^^^ expected 3 fields, found 0
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |                           --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E1::S(_, _, _) => {}
+   |               +++++++
+help: use `..` to ignore all fields
+   |
+LL |         E1::S(..) => {}
+   |               ++
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:40:15
+   |
+LL |         E1::S(1) => {}
+   |               ^ expected 3 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |                           --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E1::S(1, _, _) => {}
+   |                ++++++
+help: use `..` to ignore the rest of the fields
+   |
+LL |         E1::S(1, ..) => {}
+   |                ++++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:41:15
+   |
+LL |         E1::S(xyz, abc) => {}
+   |               ^^^  ^^^ expected 3 fields, found 2
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |                           --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E1::S(xyz, abc, _) => {}
+   |                       +++
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:42:15
+   |
+LL |         E1::S(1, 2, 3, 4) => {}
+   |               ^  ^  ^  ^ expected 3 fields, found 4
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |                           --  --  -- tuple variant has 3 fields
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:46:9
+   |
+LL |         E2::S() => {}
+   |         ^^^^^^^ expected 3 fields, found 0
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7
+   |
+LL |     S(u8, u8, u8),
+   |       --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::S(_, _, _) => {}
+   |               +++++++
+help: use `..` to ignore all fields
+   |
+LL |         E2::S(..) => {}
+   |               ++
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:47:15
+   |
+LL |         E2::S(1) => {}
+   |               ^ expected 3 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7
+   |
+LL |     S(u8, u8, u8),
+   |       --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::S(1, _, _) => {}
+   |                ++++++
+help: use `..` to ignore the rest of the fields
+   |
+LL |         E2::S(1, ..) => {}
+   |                ++++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:48:15
+   |
+LL |         E2::S(xyz, abc) => {}
+   |               ^^^  ^^^ expected 3 fields, found 2
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7
+   |
+LL |     S(u8, u8, u8),
+   |       --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::S(xyz, abc, _) => {}
+   |                       +++
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:49:15
+   |
+LL |         E2::S(1, 2, 3, 4) => {}
+   |               ^  ^  ^  ^ expected 3 fields, found 4
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7
+   |
+LL |     S(u8, u8, u8),
+   |       --  --  -- tuple variant has 3 fields
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:52:9
+   |
+LL |           E2::M() => {}
+   |           ^^^^^^^ expected 3 fields, found 0
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5
+   |
+LL | /     M(
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         -- tuple variant has 3 fields
+LL | |     ),
+   | |_____- tuple variant defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::M(_, _, _) => {}
+   |               +++++++
+help: use `..` to ignore all fields
+   |
+LL |         E2::M(..) => {}
+   |               ++
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:53:15
+   |
+LL |           E2::M(1) => {}
+   |                 ^ expected 3 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5
+   |
+LL | /     M(
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         -- tuple variant has 3 fields
+LL | |     ),
+   | |_____- tuple variant defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::M(1, _, _) => {}
+   |                ++++++
+help: use `..` to ignore the rest of the fields
+   |
+LL |         E2::M(1, ..) => {}
+   |                ++++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:54:15
+   |
+LL |           E2::M(xyz, abc) => {}
+   |                 ^^^  ^^^ expected 3 fields, found 2
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5
+   |
+LL | /     M(
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         -- tuple variant has 3 fields
+LL | |     ),
+   | |_____- tuple variant defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::M(xyz, abc, _) => {}
+   |                       +++
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:55:15
+   |
+LL |           E2::M(1, 2, 3, 4) => {}
+   |                 ^  ^  ^  ^ expected 3 fields, found 4
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5
+   |
+LL | /     M(
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         -- tuple variant has 3 fields
+LL | |     ),
+   | |_____- tuple variant defined here
+
+error: aborting due to 28 previous errors
+
+Some errors have detailed explanations: E0023, E0530, E0532.
+For more information about an error, try `rustc --explain E0023`.
diff --git a/src/test/ui/pattern/pat-tuple-overfield.rs b/src/test/ui/pattern/pat-tuple-overfield.rs
index 46a5e15ffa5..c863c657514 100644
--- a/src/test/ui/pattern/pat-tuple-overfield.rs
+++ b/src/test/ui/pattern/pat-tuple-overfield.rs
@@ -1,4 +1,18 @@
 struct S(u8, u8, u8);
+struct M(
+    u8,
+    u8,
+    u8,
+    u8,
+    u8,
+);
+
+struct Z0;
+struct Z1();
+enum E1 {
+    Z0,
+    Z1(),
+}
 
 fn main() {
     match (1, 2, 3) {
@@ -13,4 +27,48 @@ fn main() {
         //~^ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields
         _ => {}
     }
+    match M(1, 2, 3, 4, 5) {
+        M(1, 2, 3, 4, 5, 6) => {}
+        //~^ ERROR this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+        M(1,
+          2,
+          3,
+          4,
+          5,
+          6) => {}
+        //~^ ERROR this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+        M(
+            1,
+            2,
+            3,
+            4,
+            5,
+            6,
+        ) => {}
+        //~^^ ERROR this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+    }
+    match Z0 {
+        Z0 => {}
+        Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0`
+        Z0(_) => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0`
+        Z0(_, _) => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0`
+    }
+    match Z1() {
+        Z1 => {} //~ ERROR match bindings cannot shadow tuple structs
+        Z1() => {}
+        Z1(_) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 0 fields
+        Z1(_, _) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple struct has 0 fields
+    }
+    match E1::Z0 {
+        E1::Z0 => {}
+        E1::Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0`
+        E1::Z0(_) => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0`
+        E1::Z0(_, _) => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0`
+    }
+    match E1::Z1() {
+        E1::Z1 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1`
+        E1::Z1() => {}
+        E1::Z1(_) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 0 fields
+        E1::Z1(_, _) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 0 fields
+    }
 }
diff --git a/src/test/ui/pattern/pat-tuple-overfield.stderr b/src/test/ui/pattern/pat-tuple-overfield.stderr
index 45b6fd1b4d4..1c44f7e5f6f 100644
--- a/src/test/ui/pattern/pat-tuple-overfield.stderr
+++ b/src/test/ui/pattern/pat-tuple-overfield.stderr
@@ -1,5 +1,154 @@
+error[E0530]: match bindings cannot shadow tuple structs
+  --> $DIR/pat-tuple-overfield.rs:57:9
+   |
+LL | struct Z1();
+   | ------------ the tuple struct `Z1` is defined here
+...
+LL |         Z1 => {}
+   |         ^^ cannot be named the same as a tuple struct
+
+error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0`
+  --> $DIR/pat-tuple-overfield.rs:52:9
+   |
+LL | struct Z0;
+   | ---------- `Z0` defined here
+LL | struct Z1();
+   | ------------ similarly named tuple struct `Z1` defined here
+...
+LL |         Z0() => {}
+   |         ^^^^
+   |
+help: use this syntax instead
+   |
+LL |         Z0 => {}
+   |         ~~
+help: a tuple struct with a similar name exists
+   |
+LL |         Z1() => {}
+   |         ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0`
+  --> $DIR/pat-tuple-overfield.rs:53:9
+   |
+LL | struct Z0;
+   | ---------- `Z0` defined here
+LL | struct Z1();
+   | ------------ similarly named tuple struct `Z1` defined here
+...
+LL |         Z0(_) => {}
+   |         ^^^^^
+   |
+help: use this syntax instead
+   |
+LL |         Z0 => {}
+   |         ~~
+help: a tuple struct with a similar name exists
+   |
+LL |         Z1(_) => {}
+   |         ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0`
+  --> $DIR/pat-tuple-overfield.rs:54:9
+   |
+LL | struct Z0;
+   | ---------- `Z0` defined here
+LL | struct Z1();
+   | ------------ similarly named tuple struct `Z1` defined here
+...
+LL |         Z0(_, _) => {}
+   |         ^^^^^^^^
+   |
+help: use this syntax instead
+   |
+LL |         Z0 => {}
+   |         ~~
+help: a tuple struct with a similar name exists
+   |
+LL |         Z1(_, _) => {}
+   |         ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0`
+  --> $DIR/pat-tuple-overfield.rs:64:9
+   |
+LL |     Z0,
+   |     -- `E1::Z0` defined here
+LL |     Z1(),
+   |     ---- similarly named tuple variant `Z1` defined here
+...
+LL |         E1::Z0() => {}
+   |         ^^^^^^^^
+   |
+help: use this syntax instead
+   |
+LL |         E1::Z0 => {}
+   |         ~~~~~~
+help: a tuple variant with a similar name exists
+   |
+LL |         E1::Z1() => {}
+   |             ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0`
+  --> $DIR/pat-tuple-overfield.rs:65:9
+   |
+LL |     Z0,
+   |     -- `E1::Z0` defined here
+LL |     Z1(),
+   |     ---- similarly named tuple variant `Z1` defined here
+...
+LL |         E1::Z0(_) => {}
+   |         ^^^^^^^^^
+   |
+help: use this syntax instead
+   |
+LL |         E1::Z0 => {}
+   |         ~~~~~~
+help: a tuple variant with a similar name exists
+   |
+LL |         E1::Z1(_) => {}
+   |             ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0`
+  --> $DIR/pat-tuple-overfield.rs:66:9
+   |
+LL |     Z0,
+   |     -- `E1::Z0` defined here
+LL |     Z1(),
+   |     ---- similarly named tuple variant `Z1` defined here
+...
+LL |         E1::Z0(_, _) => {}
+   |         ^^^^^^^^^^^^
+   |
+help: use this syntax instead
+   |
+LL |         E1::Z0 => {}
+   |         ~~~~~~
+help: a tuple variant with a similar name exists
+   |
+LL |         E1::Z1(_, _) => {}
+   |             ~~
+
+error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E1::Z1`
+  --> $DIR/pat-tuple-overfield.rs:69:9
+   |
+LL |     Z0,
+   |     -- similarly named unit variant `Z0` defined here
+LL |     Z1(),
+   |     ---- `E1::Z1` defined here
+...
+LL |         E1::Z1 => {}
+   |         ^^^^^^
+   |
+help: use the tuple variant pattern syntax instead
+   |
+LL |         E1::Z1() => {}
+   |         ~~~~~~~~
+help: a unit variant with a similar name exists
+   |
+LL |         E1::Z0 => {}
+   |             ~~
+
 error[E0308]: mismatched types
-  --> $DIR/pat-tuple-overfield.rs:5:9
+  --> $DIR/pat-tuple-overfield.rs:19:9
    |
 LL |     match (1, 2, 3) {
    |           --------- this expression has type `({integer}, {integer}, {integer})`
@@ -10,7 +159,7 @@ LL |         (1, 2, 3, 4) => {}
               found tuple `(_, _, _, _)`
 
 error[E0308]: mismatched types
-  --> $DIR/pat-tuple-overfield.rs:6:9
+  --> $DIR/pat-tuple-overfield.rs:20:9
    |
 LL |     match (1, 2, 3) {
    |           --------- this expression has type `({integer}, {integer}, {integer})`
@@ -22,24 +171,139 @@ LL |         (1, 2, .., 3, 4) => {}
               found tuple `(_, _, _, _)`
 
 error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
-  --> $DIR/pat-tuple-overfield.rs:10:9
+  --> $DIR/pat-tuple-overfield.rs:24:11
    |
 LL | struct S(u8, u8, u8);
-   | --------------------- tuple struct defined here
+   |          --  --  -- tuple struct has 3 fields
 ...
 LL |         S(1, 2, 3, 4) => {}
-   |         ^^^^^^^^^^^^^ expected 3 fields, found 4
+   |           ^  ^  ^  ^ expected 3 fields, found 4
 
 error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
-  --> $DIR/pat-tuple-overfield.rs:12:9
+  --> $DIR/pat-tuple-overfield.rs:26:11
    |
 LL | struct S(u8, u8, u8);
-   | --------------------- tuple struct defined here
+   |          --  --  -- tuple struct has 3 fields
 ...
 LL |         S(1, 2, .., 3, 4) => {}
-   |         ^^^^^^^^^^^^^^^^^ expected 3 fields, found 4
+   |           ^  ^      ^  ^ expected 3 fields, found 4
+
+error[E0023]: this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+  --> $DIR/pat-tuple-overfield.rs:31:11
+   |
+LL | struct M(
+   |        - tuple struct defined here
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     -- tuple struct has 5 fields
+...
+LL |         M(1, 2, 3, 4, 5, 6) => {}
+   |           ^  ^  ^  ^  ^  ^ expected 5 fields, found 6
+
+error[E0023]: this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+  --> $DIR/pat-tuple-overfield.rs:33:11
+   |
+LL | struct M(
+   |        - tuple struct defined here
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     -- tuple struct has 5 fields
+...
+LL |         M(1,
+   |         - ^
+LL |           2,
+   |           ^
+LL |           3,
+   |           ^
+LL |           4,
+   |           ^
+LL |           5,
+   |           ^
+LL |           6) => {}
+   |           ^ expected 5 fields, found 6
+
+error[E0023]: this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+  --> $DIR/pat-tuple-overfield.rs:41:13
+   |
+LL | struct M(
+   |        - tuple struct defined here
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     -- tuple struct has 5 fields
+...
+LL |         M(
+   |         -
+LL |             1,
+   |             ^
+LL |             2,
+   |             ^
+LL |             3,
+   |             ^
+LL |             4,
+   |             ^
+LL |             5,
+   |             ^
+LL |             6,
+   |             ^ expected 5 fields, found 6
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 0 fields
+  --> $DIR/pat-tuple-overfield.rs:59:12
+   |
+LL | struct Z1();
+   | ------------ tuple struct has 0 fields
+...
+LL |         Z1(_) => {}
+   |            ^ expected 0 fields, found 1
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 0 fields
+  --> $DIR/pat-tuple-overfield.rs:60:12
+   |
+LL | struct Z1();
+   | ------------ tuple struct has 0 fields
+...
+LL |         Z1(_, _) => {}
+   |            ^  ^ expected 0 fields, found 2
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 0 fields
+  --> $DIR/pat-tuple-overfield.rs:71:16
+   |
+LL |     Z1(),
+   |     ---- tuple variant has 0 fields
+...
+LL |         E1::Z1(_) => {}
+   |                ^ expected 0 fields, found 1
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 0 fields
+  --> $DIR/pat-tuple-overfield.rs:72:16
+   |
+LL |     Z1(),
+   |     ---- tuple variant has 0 fields
+...
+LL |         E1::Z1(_, _) => {}
+   |                ^  ^ expected 0 fields, found 2
 
-error: aborting due to 4 previous errors
+error: aborting due to 19 previous errors
 
-Some errors have detailed explanations: E0023, E0308.
+Some errors have detailed explanations: E0023, E0308, E0530, E0532.
 For more information about an error, try `rustc --explain E0023`.
diff --git a/src/test/ui/pattern/pat-tuple-underfield.rs b/src/test/ui/pattern/pat-tuple-underfield.rs
index ed852a47bb4..dac60e3fab2 100644
--- a/src/test/ui/pattern/pat-tuple-underfield.rs
+++ b/src/test/ui/pattern/pat-tuple-underfield.rs
@@ -21,6 +21,12 @@ fn main() {
         //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 2 fields
         //~| HELP use `_` to explicitly ignore each field
         //~| HELP use `..` to ignore all fields
+
+        // Test non-standard formatting
+        S () => {}
+        //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 2 fields
+        //~| HELP use `_` to explicitly ignore each field
+        //~| HELP use `..` to ignore all fields
     }
 
     match E::S(0, 1.0) {
@@ -39,6 +45,12 @@ fn main() {
         //~^ ERROR this pattern has 0 fields, but the corresponding tuple variant has 2 fields
         //~| HELP use `_` to explicitly ignore each field
         //~| HELP use `..` to ignore all fields
+
+        // Test non-standard formatting
+        E::S () => {}
+        //~^ ERROR this pattern has 0 fields, but the corresponding tuple variant has 2 fields
+        //~| HELP use `_` to explicitly ignore each field
+        //~| HELP use `..` to ignore all fields
     }
     match E::S(0, 1.0) {
         E::S => {}
diff --git a/src/test/ui/pattern/pat-tuple-underfield.stderr b/src/test/ui/pattern/pat-tuple-underfield.stderr
index 2fbcb6d67ba..e75f9b38da5 100644
--- a/src/test/ui/pattern/pat-tuple-underfield.stderr
+++ b/src/test/ui/pattern/pat-tuple-underfield.stderr
@@ -1,5 +1,5 @@
 error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S`
-  --> $DIR/pat-tuple-underfield.rs:44:9
+  --> $DIR/pat-tuple-underfield.rs:56:9
    |
 LL |     S(i32, f32),
    |     ----------- `E::S` defined here
@@ -8,13 +8,13 @@ LL |         E::S => {}
    |         ^^^^ help: use the tuple variant pattern syntax instead: `E::S(_, _)`
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields
-  --> $DIR/pat-tuple-underfield.rs:9:9
+  --> $DIR/pat-tuple-underfield.rs:9:11
    |
 LL | struct S(i32, f32);
-   | ------------------- tuple struct defined here
+   |          ---  --- tuple struct has 2 fields
 ...
 LL |         S(x) => {}
-   |         ^^^^ expected 2 fields, found 1
+   |           ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -22,13 +22,13 @@ LL |         S(x, _) => {}
    |            +++
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields
-  --> $DIR/pat-tuple-underfield.rs:14:9
+  --> $DIR/pat-tuple-underfield.rs:14:11
    |
 LL | struct S(i32, f32);
-   | ------------------- tuple struct defined here
+   |          ---  --- tuple struct has 2 fields
 ...
 LL |         S(_) => {}
-   |         ^^^^ expected 2 fields, found 1
+   |           ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -43,7 +43,7 @@ error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has
   --> $DIR/pat-tuple-underfield.rs:20:9
    |
 LL | struct S(i32, f32);
-   | ------------------- tuple struct defined here
+   |          ---  --- tuple struct has 2 fields
 ...
 LL |         S() => {}
    |         ^^^ expected 2 fields, found 0
@@ -57,14 +57,32 @@ help: use `..` to ignore all fields
 LL |         S(..) => {}
    |           ++
 
+error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields
+  --> $DIR/pat-tuple-underfield.rs:26:9
+   |
+LL | struct S(i32, f32);
+   |          ---  --- tuple struct has 2 fields
+...
+LL |         S () => {}
+   |         ^^^^ expected 2 fields, found 0
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         S (_, _) => {}
+   |            ++++
+help: use `..` to ignore all fields
+   |
+LL |         S (..) => {}
+   |            ++
+
 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
-  --> $DIR/pat-tuple-underfield.rs:27:9
+  --> $DIR/pat-tuple-underfield.rs:33:14
    |
 LL |     S(i32, f32),
-   |     ----------- tuple variant defined here
+   |       ---  --- tuple variant has 2 fields
 ...
 LL |         E::S(x) => {}
-   |         ^^^^^^^ expected 2 fields, found 1
+   |              ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -72,13 +90,13 @@ LL |         E::S(x, _) => {}
    |               +++
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
-  --> $DIR/pat-tuple-underfield.rs:32:9
+  --> $DIR/pat-tuple-underfield.rs:38:14
    |
 LL |     S(i32, f32),
-   |     ----------- tuple variant defined here
+   |       ---  --- tuple variant has 2 fields
 ...
 LL |         E::S(_) => {}
-   |         ^^^^^^^ expected 2 fields, found 1
+   |              ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -90,10 +108,10 @@ LL |         E::S(..) => {}
    |              ~~
 
 error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields
-  --> $DIR/pat-tuple-underfield.rs:38:9
+  --> $DIR/pat-tuple-underfield.rs:44:9
    |
 LL |     S(i32, f32),
-   |     ----------- tuple variant defined here
+   |       ---  --- tuple variant has 2 fields
 ...
 LL |         E::S() => {}
    |         ^^^^^^ expected 2 fields, found 0
@@ -107,14 +125,32 @@ help: use `..` to ignore all fields
 LL |         E::S(..) => {}
    |              ++
 
-error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 4 fields
+error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields
   --> $DIR/pat-tuple-underfield.rs:50:9
    |
+LL |     S(i32, f32),
+   |       ---  --- tuple variant has 2 fields
+...
+LL |         E::S () => {}
+   |         ^^^^^^^ expected 2 fields, found 0
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E::S (_, _) => {}
+   |               ++++
+help: use `..` to ignore all fields
+   |
+LL |         E::S (..) => {}
+   |               ++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 4 fields
+  --> $DIR/pat-tuple-underfield.rs:62:19
+   |
 LL | struct Point4(i32, i32, i32, i32);
-   | ---------------------------------- tuple struct defined here
+   |               ---  ---  ---  --- tuple struct has 4 fields
 ...
 LL |         Point4(   a   ,     _    ) => {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 4 fields, found 2
+   |                   ^         ^ expected 4 fields, found 2
    |
 help: use `_` to explicitly ignore each field
    |
@@ -125,7 +161,7 @@ help: use `..` to ignore the rest of the fields
 LL |         Point4(   a, ..) => {}
    |                    ~~~~
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0023, E0532.
 For more information about an error, try `rustc --explain E0023`.
diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr
index 3f28ffed291..c800afdae2a 100644
--- a/src/test/ui/pattern/pattern-error-continue.stderr
+++ b/src/test/ui/pattern/pattern-error-continue.stderr
@@ -26,13 +26,13 @@ LL |         A::B(_) => (),
    |            ~
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
-  --> $DIR/pattern-error-continue.rs:17:9
+  --> $DIR/pattern-error-continue.rs:17:14
    |
 LL |     B(isize, isize),
-   |     --------------- tuple variant defined here
+   |       -----  ----- tuple variant has 2 fields
 ...
 LL |         A::B(_, _, _) => (),
-   |         ^^^^^^^^^^^^^ expected 2 fields, found 3
+   |              ^  ^  ^ expected 2 fields, found 3
 
 error[E0308]: mismatched types
   --> $DIR/pattern-error-continue.rs:22:9
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
index 1d520613a28..37543c137f6 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
@@ -5,6 +5,12 @@ LL |     <E>::V();
    |     ^^^^^^-- supplied 0 arguments
    |     |
    |     expected 1 argument
+   |
+note: tuple variant defined here
+  --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:5:5
+   |
+LL |     V(u8)
+   |     ^
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
diff --git a/src/test/ui/typeck/struct-enum-wrong-args.stderr b/src/test/ui/typeck/struct-enum-wrong-args.stderr
index d77ef73028b..6e99feed33f 100644
--- a/src/test/ui/typeck/struct-enum-wrong-args.stderr
+++ b/src/test/ui/typeck/struct-enum-wrong-args.stderr
@@ -29,6 +29,12 @@ LL |     let _ = Wrapper();
    |             ^^^^^^^-- supplied 0 arguments
    |             |
    |             expected 1 argument
+   |
+note: tuple struct defined here
+  --> $DIR/struct-enum-wrong-args.rs:2:8
+   |
+LL | struct Wrapper(i32);
+   |        ^^^^^^^
 
 error[E0061]: this struct takes 1 argument but 2 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:10:13
@@ -37,6 +43,12 @@ LL |     let _ = Wrapper(5, 2);
    |             ^^^^^^^ -  - supplied 2 arguments
    |             |
    |             expected 1 argument
+   |
+note: tuple struct defined here
+  --> $DIR/struct-enum-wrong-args.rs:2:8
+   |
+LL | struct Wrapper(i32);
+   |        ^^^^^^^
 
 error[E0061]: this struct takes 2 arguments but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:11:13
@@ -45,6 +57,12 @@ LL |     let _ = DoubleWrapper();
    |             ^^^^^^^^^^^^^-- supplied 0 arguments
    |             |
    |             expected 2 arguments
+   |
+note: tuple struct defined here
+  --> $DIR/struct-enum-wrong-args.rs:3:8
+   |
+LL | struct DoubleWrapper(i32, i32);
+   |        ^^^^^^^^^^^^^
 
 error[E0061]: this struct takes 2 arguments but 1 argument was supplied
   --> $DIR/struct-enum-wrong-args.rs:12:13
@@ -53,6 +71,12 @@ LL |     let _ = DoubleWrapper(5);
    |             ^^^^^^^^^^^^^ - supplied 1 argument
    |             |
    |             expected 2 arguments
+   |
+note: tuple struct defined here
+  --> $DIR/struct-enum-wrong-args.rs:3:8
+   |
+LL | struct DoubleWrapper(i32, i32);
+   |        ^^^^^^^^^^^^^
 
 error[E0061]: this struct takes 2 arguments but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:13:13
@@ -61,6 +85,12 @@ LL |     let _ = DoubleWrapper(5, 2, 7);
    |             ^^^^^^^^^^^^^ -  -  - supplied 3 arguments
    |             |
    |             expected 2 arguments
+   |
+note: tuple struct defined here
+  --> $DIR/struct-enum-wrong-args.rs:3:8
+   |
+LL | struct DoubleWrapper(i32, i32);
+   |        ^^^^^^^^^^^^^
 
 error: aborting due to 8 previous errors