about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-02-28 17:17:28 +0100
committerGitHub <noreply@github.com>2020-02-28 17:17:28 +0100
commita245221497aa03553b983e2d2bcb1c7ee80bb477 (patch)
tree98d6ce459a4067cc654297d6263946f5d7556062
parent3828fa2852bf5e622267b24c4eda74e4fa6cb5f9 (diff)
parentd234e131b8651ccf4bf8df05c9182e1085fa48fa (diff)
downloadrust-a245221497aa03553b983e2d2bcb1c7ee80bb477.tar.gz
rust-a245221497aa03553b983e2d2bcb1c7ee80bb477.zip
Rollup merge of #69452 - Centril:typeck-pat, r=estebank
typeck: use `Pattern` obligation cause more for better diagnostics

r? @estebank
-rw-r--r--src/librustc/hir/map/mod.rs26
-rw-r--r--src/librustc_typeck/check/demand.rs10
-rw-r--r--src/librustc_typeck/check/pat.rs61
-rw-r--r--src/test/ui/destructure-trait-ref.stderr4
-rw-r--r--src/test/ui/elide-errors-on-mismatched-tuple.stderr4
-rw-r--r--src/test/ui/issues/issue-12552.stderr3
-rw-r--r--src/test/ui/issues/issue-37026.stderr4
-rw-r--r--src/test/ui/issues/issue-5100.stderr8
-rw-r--r--src/test/ui/issues/issue-7867.stderr2
-rw-r--r--src/test/ui/match/match-ill-type2.stderr3
-rw-r--r--src/test/ui/match/match-tag-nullary.stderr4
-rw-r--r--src/test/ui/mismatched_types/E0409.stderr6
-rw-r--r--src/test/ui/mismatched_types/issue-38371.stderr9
-rw-r--r--src/test/ui/mut/mut-pattern-mismatched.stderr6
-rw-r--r--src/test/ui/or-patterns/already-bound-name.stderr8
-rw-r--r--src/test/ui/or-patterns/inconsistent-modes.stderr16
-rw-r--r--src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr158
-rw-r--r--src/test/ui/pattern/pat-tuple-bad-type.stderr2
-rw-r--r--src/test/ui/pattern/pat-tuple-overfield.stderr5
-rw-r--r--src/test/ui/pattern/pattern-ident-path-generics.stderr2
-rw-r--r--src/test/ui/resolve/name-clash-nullary.stderr4
-rw-r--r--src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr17
-rw-r--r--src/test/ui/resolve/resolve-inconsistent-names.stderr6
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/const.stderr2
-rw-r--r--src/test/ui/rfc-2005-default-binding-mode/lit.stderr4
-rw-r--r--src/test/ui/slightly-nice-generic-literal-messages.stderr2
-rw-r--r--src/test/ui/suggestions/match-ergonomics.stderr6
-rw-r--r--src/test/ui/suppressed-error.stderr4
28 files changed, 284 insertions, 102 deletions
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index adda0cde24f..f7301280acd 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -153,17 +153,13 @@ pub struct Map<'hir> {
     hir_to_node_id: FxHashMap<HirId, NodeId>,
 }
 
-struct ParentHirIterator<'map, 'hir> {
+/// An iterator that walks up the ancestor tree of a given `HirId`.
+/// Constructed using `tcx.hir().parent_iter(hir_id)`.
+pub struct ParentHirIterator<'map, 'hir> {
     current_id: HirId,
     map: &'map Map<'hir>,
 }
 
-impl<'map, 'hir> ParentHirIterator<'map, 'hir> {
-    fn new(current_id: HirId, map: &'map Map<'hir>) -> Self {
-        Self { current_id, map }
-    }
-}
-
 impl<'hir> Iterator for ParentHirIterator<'_, 'hir> {
     type Item = (HirId, Node<'hir>);
 
@@ -618,6 +614,12 @@ impl<'hir> Map<'hir> {
         self.find_entry(hir_id).and_then(|x| x.parent_node()).unwrap_or(hir_id)
     }
 
+    /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
+    /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+    pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> {
+        ParentHirIterator { current_id, map: self }
+    }
+
     /// Checks if the node is an argument. An argument is a local variable whose
     /// immediate parent is an item or a closure.
     pub fn is_argument(&self, id: HirId) -> bool {
@@ -684,7 +686,7 @@ impl<'hir> Map<'hir> {
     /// }
     /// ```
     pub fn get_return_block(&self, id: HirId) -> Option<HirId> {
-        let mut iter = ParentHirIterator::new(id, &self).peekable();
+        let mut iter = self.parent_iter(id).peekable();
         let mut ignore_tail = false;
         if let Some(entry) = self.find_entry(id) {
             if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = entry.node {
@@ -731,7 +733,7 @@ impl<'hir> Map<'hir> {
     /// in the HIR which is recorded by the map and is an item, either an item
     /// in a module, trait, or impl.
     pub fn get_parent_item(&self, hir_id: HirId) -> HirId {
-        for (hir_id, node) in ParentHirIterator::new(hir_id, &self) {
+        for (hir_id, node) in self.parent_iter(hir_id) {
             match node {
                 Node::Crate
                 | Node::Item(_)
@@ -753,7 +755,7 @@ impl<'hir> Map<'hir> {
     /// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
     /// module parent is in this map.
     pub fn get_module_parent_node(&self, hir_id: HirId) -> HirId {
-        for (hir_id, node) in ParentHirIterator::new(hir_id, &self) {
+        for (hir_id, node) in self.parent_iter(hir_id) {
             if let Node::Item(&Item { kind: ItemKind::Mod(_), .. }) = node {
                 return hir_id;
             }
@@ -767,7 +769,7 @@ impl<'hir> Map<'hir> {
     /// Used by error reporting when there's a type error in a match arm caused by the `match`
     /// expression needing to be unit.
     pub fn get_match_if_cause(&self, hir_id: HirId) -> Option<&'hir Expr<'hir>> {
-        for (_, node) in ParentHirIterator::new(hir_id, &self) {
+        for (_, node) in self.parent_iter(hir_id) {
             match node {
                 Node::Item(_) | Node::ForeignItem(_) | Node::TraitItem(_) | Node::ImplItem(_) => {
                     break;
@@ -788,7 +790,7 @@ impl<'hir> Map<'hir> {
 
     /// Returns the nearest enclosing scope. A scope is roughly an item or block.
     pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option<HirId> {
-        for (hir_id, node) in ParentHirIterator::new(hir_id, &self) {
+        for (hir_id, node) in self.parent_iter(hir_id) {
             if match node {
                 Node::Item(i) => match i.kind {
                     ItemKind::Fn(..)
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index c289176c303..7ed6cbf93da 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -43,7 +43,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         actual: Ty<'tcx>,
     ) -> Option<DiagnosticBuilder<'tcx>> {
-        let cause = &self.misc(sp);
+        self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
+    }
+
+    pub fn demand_suptype_with_origin(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        expected: Ty<'tcx>,
+        actual: Ty<'tcx>,
+    ) -> Option<DiagnosticBuilder<'tcx>> {
         match self.at(cause, self.param_env).sup(expected, actual) {
             Ok(InferOk { obligations, value: () }) => {
                 self.register_predicates(obligations);
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 2c7cbed6a2d..1df7c64f2c6 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -9,9 +9,9 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::{HirId, Pat, PatKind};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::traits::Pattern;
+use rustc_infer::traits::{ObligationCause, Pattern};
 use rustc_span::hygiene::DesugaringKind;
-use rustc_span::Span;
+use rustc_span::source_map::{Span, Spanned};
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
 
@@ -66,6 +66,11 @@ struct TopInfo<'tcx> {
 }
 
 impl<'tcx> FnCtxt<'_, 'tcx> {
+    fn pattern_cause(&self, ti: TopInfo<'tcx>, cause_span: Span) -> ObligationCause<'tcx> {
+        let code = Pattern { span: ti.span, root_ty: ti.expected, origin_expr: ti.origin_expr };
+        self.cause(cause_span, code)
+    }
+
     fn demand_eqtype_pat_diag(
         &self,
         cause_span: Span,
@@ -73,9 +78,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         actual: Ty<'tcx>,
         ti: TopInfo<'tcx>,
     ) -> Option<DiagnosticBuilder<'tcx>> {
-        let code = Pattern { span: ti.span, root_ty: ti.expected, origin_expr: ti.origin_expr };
-        let cause = self.cause(cause_span, code);
-        self.demand_eqtype_with_origin(&cause, expected, actual)
+        self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
     }
 
     fn demand_eqtype_pat(
@@ -152,7 +155,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, def_bm, ti)
             }
             PatKind::Path(ref qpath) => {
-                self.check_pat_path(pat, path_res.unwrap(), qpath, expected)
+                self.check_pat_path(pat, path_res.unwrap(), qpath, expected, ti)
             }
             PatKind::Struct(ref qpath, fields, etc) => {
                 self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, ti)
@@ -361,16 +364,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Byte string patterns behave the same way as array patterns
         // They can denote both statically and dynamically-sized byte arrays.
         let mut pat_ty = ty;
-        if let hir::ExprKind::Lit(ref lt) = lt.kind {
-            if let ast::LitKind::ByteStr(_) = lt.node {
-                let expected_ty = self.structurally_resolved_type(span, expected);
-                if let ty::Ref(_, r_ty, _) = expected_ty.kind {
-                    if let ty::Slice(_) = r_ty.kind {
-                        let tcx = self.tcx;
-                        pat_ty =
-                            tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_slice(tcx.types.u8));
-                    }
-                }
+        if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(_), .. }) = lt.kind {
+            let expected = self.structurally_resolved_type(span, expected);
+            if let ty::Ref(_, ty::TyS { kind: ty::Slice(_), .. }, _) = expected.kind {
+                let tcx = self.tcx;
+                pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_slice(tcx.types.u8));
             }
         }
 
@@ -384,7 +382,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         //     &'static str <: expected
         //
         // then that's equivalent to there existing a LUB.
-        if let Some(mut err) = self.demand_suptype_diag(span, expected, pat_ty) {
+        let cause = self.pattern_cause(ti, span);
+        if let Some(mut err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
             err.emit_unless(
                 ti.span
                     .filter(|&s| {
@@ -543,8 +542,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // If there are multiple arms, make sure they all agree on
         // what the type of the binding `x` ought to be.
         if var_id != pat.hir_id {
-            let vt = self.local_ty(pat.span, var_id).decl_ty;
-            self.demand_eqtype_pat(pat.span, vt, local_ty, ti);
+            self.check_binding_alt_eq_ty(pat.span, var_id, local_ty, ti);
         }
 
         if let Some(p) = sub {
@@ -554,6 +552,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         local_ty
     }
 
+    fn check_binding_alt_eq_ty(&self, span: Span, var_id: HirId, ty: Ty<'tcx>, ti: TopInfo<'tcx>) {
+        let var_ty = self.local_ty(span, var_id).decl_ty;
+        if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
+            let hir = self.tcx.hir();
+            let var_ty = self.resolve_vars_with_obligations(var_ty);
+            let msg = format!("first introduced with type `{}` here", var_ty);
+            err.span_label(hir.span(var_id), msg);
+            let in_arm = hir.parent_iter(var_id).any(|(_, n)| matches!(n, hir::Node::Arm(..)));
+            let pre = if in_arm { "in the same arm, " } else { "" };
+            err.note(&format!("{}a binding must have the same type in all alternatives", pre));
+            err.emit();
+        }
+    }
+
     fn borrow_pat_suggestion(
         &self,
         err: &mut DiagnosticBuilder<'_>,
@@ -659,6 +671,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         path_resolution: (Res, Option<Ty<'tcx>>, &'b [hir::PathSegment<'b>]),
         qpath: &hir::QPath<'_>,
         expected: Ty<'tcx>,
+        ti: TopInfo<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
 
@@ -684,7 +697,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Type-check the path.
         let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0;
-        self.demand_suptype(pat.span, expected, pat_ty);
+        if let Some(mut err) =
+            self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
+        {
+            err.emit();
+        }
         pat_ty
     }
 
@@ -901,7 +918,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         });
         let element_tys = tcx.mk_substs(element_tys_iter);
         let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
-        if let Some(mut err) = self.demand_eqtype_diag(span, expected, pat_ty) {
+        if let Some(mut err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, ti) {
             err.emit();
             // Walk subpatterns with an expected type of `err` in this case to silence
             // further errors being emitted when using the bindings. #50333
@@ -1205,7 +1222,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     });
                     let rptr_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
                     debug!("check_pat_ref: demanding {:?} = {:?}", expected, rptr_ty);
-                    let err = self.demand_eqtype_diag(pat.span, expected, rptr_ty);
+                    let err = self.demand_eqtype_pat_diag(pat.span, expected, rptr_ty, ti);
 
                     // Look for a case like `fn foo(&foo: u32)` and suggest
                     // `fn foo(foo: &u32)`
diff --git a/src/test/ui/destructure-trait-ref.stderr b/src/test/ui/destructure-trait-ref.stderr
index f99bf2ffdc9..1382cf643a1 100644
--- a/src/test/ui/destructure-trait-ref.stderr
+++ b/src/test/ui/destructure-trait-ref.stderr
@@ -20,7 +20,7 @@ error[E0308]: mismatched types
   --> $DIR/destructure-trait-ref.rs:32:10
    |
 LL |     let &&x = &1isize as &dyn T;
-   |          ^^
+   |          ^^   ----------------- this expression has type `&dyn T`
    |          |
    |          expected trait object `dyn T`, found reference
    |          help: you can probably remove the explicit borrow: `x`
@@ -32,7 +32,7 @@ error[E0308]: mismatched types
   --> $DIR/destructure-trait-ref.rs:36:11
    |
 LL |     let &&&x = &(&1isize as &dyn T);
-   |           ^^
+   |           ^^   -------------------- this expression has type `&&dyn T`
    |           |
    |           expected trait object `dyn T`, found reference
    |           help: you can probably remove the explicit borrow: `x`
diff --git a/src/test/ui/elide-errors-on-mismatched-tuple.stderr b/src/test/ui/elide-errors-on-mismatched-tuple.stderr
index 122c71bebc4..e0537ff6faa 100644
--- a/src/test/ui/elide-errors-on-mismatched-tuple.stderr
+++ b/src/test/ui/elide-errors-on-mismatched-tuple.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/elide-errors-on-mismatched-tuple.rs:14:9
    |
 LL |     let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three
-   |         ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+   |         ^^^^^^^^^   -------------------- this expression has type `(A, A)`
+   |         |
+   |         expected a tuple with 2 elements, found one with 3 elements
    |
    = note: expected tuple `(A, A)`
               found tuple `(_, _, _)`
diff --git a/src/test/ui/issues/issue-12552.stderr b/src/test/ui/issues/issue-12552.stderr
index 60c4cceac51..45fede44106 100644
--- a/src/test/ui/issues/issue-12552.stderr
+++ b/src/test/ui/issues/issue-12552.stderr
@@ -12,6 +12,9 @@ LL |     Some(k) => match k {
 error[E0308]: mismatched types
   --> $DIR/issue-12552.rs:9:5
    |
+LL |   match t {
+   |         - this expression has type `std::result::Result<_, {integer}>`
+...
 LL |     None => ()
    |     ^^^^ expected enum `std::result::Result`, found enum `std::option::Option`
    |
diff --git a/src/test/ui/issues/issue-37026.stderr b/src/test/ui/issues/issue-37026.stderr
index 361369e68bc..f0285730c5a 100644
--- a/src/test/ui/issues/issue-37026.stderr
+++ b/src/test/ui/issues/issue-37026.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-37026.rs:6:9
    |
 LL |     let empty_struct::XEmpty2 = ();
-   |         ^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `empty_struct::XEmpty2`
+   |         ^^^^^^^^^^^^^^^^^^^^^   -- this expression has type `()`
+   |         |
+   |         expected `()`, found struct `empty_struct::XEmpty2`
 
 error[E0308]: mismatched types
   --> $DIR/issue-37026.rs:7:9
diff --git a/src/test/ui/issues/issue-5100.stderr b/src/test/ui/issues/issue-5100.stderr
index c47e8689436..c81d6dcaf02 100644
--- a/src/test/ui/issues/issue-5100.stderr
+++ b/src/test/ui/issues/issue-5100.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-5100.rs:8:9
    |
+LL |     match (true, false) {
+   |           ------------- this expression has type `(bool, bool)`
 LL |         A::B => (),
    |         ^^^^ expected tuple, found enum `A`
    |
@@ -10,6 +12,8 @@ LL |         A::B => (),
 error[E0308]: mismatched types
   --> $DIR/issue-5100.rs:17:9
    |
+LL |     match (true, false) {
+   |           ------------- this expression has type `(bool, bool)`
 LL |         (true, false, false) => ()
    |         ^^^^^^^^^^^^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
    |
@@ -19,6 +23,8 @@ LL |         (true, false, false) => ()
 error[E0308]: mismatched types
   --> $DIR/issue-5100.rs:25:9
    |
+LL |     match (true, false) {
+   |           ------------- this expression has type `(bool, bool)`
 LL |         (true, false, false) => ()
    |         ^^^^^^^^^^^^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
    |
@@ -39,6 +45,8 @@ LL |         box (true, false) => ()
 error[E0308]: mismatched types
   --> $DIR/issue-5100.rs:40:9
    |
+LL |     match (true, false) {
+   |           ------------- this expression has type `(bool, bool)`
 LL |         &(true, false) => ()
    |         ^^^^^^^^^^^^^^ expected tuple, found reference
    |
diff --git a/src/test/ui/issues/issue-7867.stderr b/src/test/ui/issues/issue-7867.stderr
index 58e82facf80..4a29464aebd 100644
--- a/src/test/ui/issues/issue-7867.stderr
+++ b/src/test/ui/issues/issue-7867.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-7867.rs:7:9
    |
+LL |     match (true, false) {
+   |           ------------- this expression has type `(bool, bool)`
 LL |         A::B => (),
    |         ^^^^ expected tuple, found enum `A`
    |
diff --git a/src/test/ui/match/match-ill-type2.stderr b/src/test/ui/match/match-ill-type2.stderr
index 1cf61ebad43..5078f03d601 100644
--- a/src/test/ui/match/match-ill-type2.stderr
+++ b/src/test/ui/match/match-ill-type2.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/match-ill-type2.rs:4:9
    |
+LL |     match 1i32 {
+   |           ---- this expression has type `i32`
+LL |         1i32 => 1,
 LL |         2u32 => 1,
    |         ^^^^ expected `i32`, found `u32`
 
diff --git a/src/test/ui/match/match-tag-nullary.stderr b/src/test/ui/match/match-tag-nullary.stderr
index 4b6260b2199..3703a59edb8 100644
--- a/src/test/ui/match/match-tag-nullary.stderr
+++ b/src/test/ui/match/match-tag-nullary.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/match-tag-nullary.rs:4:40
    |
 LL | fn main() { let x: A = A::A; match x { B::B => { } } }
-   |                                        ^^^^ expected enum `A`, found enum `B`
+   |                                    -   ^^^^ expected enum `A`, found enum `B`
+   |                                    |
+   |                                    this expression has type `A`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr
index 2306fb35273..f5c8b02ae27 100644
--- a/src/test/ui/mismatched_types/E0409.stderr
+++ b/src/test/ui/mismatched_types/E0409.stderr
@@ -12,7 +12,11 @@ error[E0308]: mismatched types
 LL |     match x {
    |           - this expression has type `({integer}, {integer})`
 LL |         (0, ref y) | (y, 0) => {}
-   |                       ^ expected `&{integer}`, found integer
+   |             -----     ^ expected `&{integer}`, found integer
+   |             |
+   |             first introduced with type `&{integer}` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr
index 802a2fef6bd..c2bce305877 100644
--- a/src/test/ui/mismatched_types/issue-38371.stderr
+++ b/src/test/ui/mismatched_types/issue-38371.stderr
@@ -3,7 +3,8 @@ error[E0308]: mismatched types
    |
 LL | fn foo(&foo: Foo) {
    |        ^^^^------
-   |        |
+   |        |     |
+   |        |     expected due to this
    |        expected struct `Foo`, found reference
    |        help: did you mean `foo`: `&Foo`
    |
@@ -14,7 +15,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-38371.rs:18:9
    |
 LL | fn agh(&&bar: &u32) {
-   |         ^^^^
+   |         ^^^^  ---- expected due to this
    |         |
    |         expected `u32`, found reference
    |         help: you can probably remove the explicit borrow: `bar`
@@ -26,7 +27,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-38371.rs:21:8
    |
 LL | fn bgh(&&bar: u32) {
-   |        ^^^^^ expected `u32`, found reference
+   |        ^^^^^  --- expected due to this
+   |        |
+   |        expected `u32`, found reference
    |
    = note:   expected type `u32`
            found reference `&_`
diff --git a/src/test/ui/mut/mut-pattern-mismatched.stderr b/src/test/ui/mut/mut-pattern-mismatched.stderr
index ccc8ac1278c..cad1cef5155 100644
--- a/src/test/ui/mut/mut-pattern-mismatched.stderr
+++ b/src/test/ui/mut/mut-pattern-mismatched.stderr
@@ -3,6 +3,9 @@ error[E0308]: mismatched types
    |
 LL |      let &_
    |          ^^ types differ in mutability
+...
+LL |         = foo;
+   |           --- this expression has type `&mut {integer}`
    |
    = note: expected mutable reference `&mut {integer}`
                       found reference `&_`
@@ -12,6 +15,9 @@ error[E0308]: mismatched types
    |
 LL |     let &mut _
    |         ^^^^^^ types differ in mutability
+...
+LL |          = bar;
+   |            --- this expression has type `&{integer}`
    |
    = note:      expected reference `&{integer}`
            found mutable reference `&mut _`
diff --git a/src/test/ui/or-patterns/already-bound-name.stderr b/src/test/ui/or-patterns/already-bound-name.stderr
index 9924b0d7f72..97933ca1229 100644
--- a/src/test/ui/or-patterns/already-bound-name.stderr
+++ b/src/test/ui/or-patterns/already-bound-name.stderr
@@ -86,12 +86,14 @@ error[E0308]: mismatched types
   --> $DIR/already-bound-name.rs:32:31
    |
 LL |     let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1));
-   |                               ^                    ------- this expression has type `E<E<{integer}>>`
-   |                               |
-   |                               expected integer, found enum `E`
+   |             -                 ^                    ------- this expression has type `E<E<{integer}>>`
+   |             |                 |
+   |             |                 expected integer, found enum `E`
+   |             first introduced with type `{integer}` here
    |
    = note: expected type `{integer}`
               found type `E<{integer}>`
+   = note: a binding must have the same type in all alternatives
 
 error: aborting due to 15 previous errors
 
diff --git a/src/test/ui/or-patterns/inconsistent-modes.stderr b/src/test/ui/or-patterns/inconsistent-modes.stderr
index c329f905960..8c01e00bae3 100644
--- a/src/test/ui/or-patterns/inconsistent-modes.stderr
+++ b/src/test/ui/or-patterns/inconsistent-modes.stderr
@@ -52,23 +52,27 @@ error[E0308]: mismatched types
   --> $DIR/inconsistent-modes.rs:11:25
    |
 LL |     let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0);
-   |                         ^^^^^^^^^   -------------------- expected due to this
-   |                         |
-   |                         types differ in mutability
+   |            -----        ^^^^^^^^^   -------------------- expected due to this
+   |            |            |
+   |            |            types differ in mutability
+   |            first introduced with type `&&u8` here
    |
    = note: expected type `&&u8`
               found type `&mut &mut u8`
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/inconsistent-modes.rs:14:31
    |
 LL |     let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
-   |                               ^^^^^^^^^            ----------- this expression has type `std::result::Result<({integer}, &{integer}), (_, _)>`
-   |                               |
-   |                               types differ in mutability
+   |             -----             ^^^^^^^^^            ----------- this expression has type `std::result::Result<({integer}, &{integer}), (_, _)>`
+   |             |                 |
+   |             |                 types differ in mutability
+   |             first introduced with type `&{integer}` here
    |
    = note: expected type `&{integer}`
               found type `&mut _`
+   = note: a binding must have the same type in all alternatives
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr
index 5094f04b920..d5e029d668d 100644
--- a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr
+++ b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr
@@ -4,7 +4,11 @@ error[E0308]: mismatched types
 LL |     match Blah::A(1, 1, 2) {
    |           ---------------- this expression has type `main::Blah`
 LL |         Blah::A(_, x, y) | Blah::B(x, y) => {}
-   |                                       ^ expected `usize`, found `isize`
+   |                       -               ^ expected `usize`, found `isize`
+   |                       |
+   |                       first introduced with type `usize` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:17:44
@@ -12,7 +16,11 @@ error[E0308]: mismatched types
 LL |     match Some(Blah::A(1, 1, 2)) {
    |           ---------------------- this expression has type `std::option::Option<main::Blah>`
 LL |         Some(Blah::A(_, x, y) | Blah::B(x, y)) => {}
-   |                                            ^ expected `usize`, found `isize`
+   |                            -               ^ expected `usize`, found `isize`
+   |                            |
+   |                            first introduced with type `usize` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:21:19
@@ -20,7 +28,11 @@ error[E0308]: mismatched types
 LL |     match (0u8, 1u16) {
    |           ----------- this expression has type `(u8, u16)`
 LL |         (x, y) | (y, x) => {}
-   |                   ^ expected `u16`, found `u8`
+   |             -     ^ expected `u16`, found `u8`
+   |             |
+   |             first introduced with type `u16` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:21:22
@@ -28,7 +40,11 @@ error[E0308]: mismatched types
 LL |     match (0u8, 1u16) {
    |           ----------- this expression has type `(u8, u16)`
 LL |         (x, y) | (y, x) => {}
-   |                      ^ expected `u8`, found `u16`
+   |          -           ^ expected `u8`, found `u16`
+   |          |
+   |          first introduced with type `u8` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:26:41
@@ -36,7 +52,11 @@ error[E0308]: mismatched types
 LL |     match Some((0u8, Some((1u16, 2u32)))) {
    |           ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
 LL |         Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {}
-   |                                         ^ expected `u16`, found `u8`
+   |                        -                ^ expected `u16`, found `u8`
+   |                        |
+   |                        first introduced with type `u16` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:26:50
@@ -44,7 +64,11 @@ error[E0308]: mismatched types
 LL |     match Some((0u8, Some((1u16, 2u32)))) {
    |           ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
 LL |         Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {}
-   |                                                  ^ expected `u8`, found `u16`
+   |               -                                  ^ expected `u8`, found `u16`
+   |               |
+   |               first introduced with type `u8` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:26:59
@@ -52,7 +76,11 @@ error[E0308]: mismatched types
 LL |     match Some((0u8, Some((1u16, 2u32)))) {
    |           ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
 LL |         Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {}
-   |                                                           ^ expected `u32`, found `u16`
+   |                           -                               ^ expected `u32`, found `u16`
+   |                           |
+   |                           first introduced with type `u32` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:26:62
@@ -60,123 +88,169 @@ error[E0308]: mismatched types
 LL |     match Some((0u8, Some((1u16, 2u32)))) {
    |           ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
 LL |         Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {}
-   |                                                              ^ expected `u8`, found `u32`
+   |               - first introduced with type `u8` here         ^ expected `u8`, found `u32`
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:34:42
    |
 LL |     if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) {
-   |                                          ^    ---------------- this expression has type `main::Blah`
-   |                                          |
-   |                                          expected `usize`, found `isize`
+   |                          -               ^    ---------------- this expression has type `main::Blah`
+   |                          |               |
+   |                          |               expected `usize`, found `isize`
+   |                          first introduced with type `usize` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:38:47
    |
 LL |     if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2)) {
-   |                                               ^     ---------------------- this expression has type `std::option::Option<main::Blah>`
-   |                                               |
-   |                                               expected `usize`, found `isize`
+   |                               -               ^     ---------------------- this expression has type `std::option::Option<main::Blah>`
+   |                               |               |
+   |                               |               expected `usize`, found `isize`
+   |                               first introduced with type `usize` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:42:22
    |
 LL |     if let (x, y) | (y, x) = (0u8, 1u16) {
-   |                      ^       ----------- this expression has type `(u8, u16)`
-   |                      |
-   |                      expected `u16`, found `u8`
+   |                -     ^       ----------- this expression has type `(u8, u16)`
+   |                |     |
+   |                |     expected `u16`, found `u8`
+   |                first introduced with type `u16` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:42:25
    |
 LL |     if let (x, y) | (y, x) = (0u8, 1u16) {
-   |                         ^    ----------- this expression has type `(u8, u16)`
-   |                         |
-   |                         expected `u8`, found `u16`
+   |             -           ^    ----------- this expression has type `(u8, u16)`
+   |             |           |
+   |             |           expected `u8`, found `u16`
+   |             first introduced with type `u8` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:47:44
    |
 LL |     if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x))))
-   |                                            ^ expected `u16`, found `u8`
+   |                           -                ^ expected `u16`, found `u8`
+   |                           |
+   |                           first introduced with type `u16` here
 ...
 LL |     = Some((0u8, Some((1u16, 2u32))))
    |       ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:47:53
    |
 LL |     if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x))))
-   |                                                     ^ expected `u8`, found `u16`
+   |                  -                                  ^ expected `u8`, found `u16`
+   |                  |
+   |                  first introduced with type `u8` here
 ...
 LL |     = Some((0u8, Some((1u16, 2u32))))
    |       ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:47:62
    |
 LL |     if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x))))
-   |                                                              ^ expected `u32`, found `u16`
+   |                              -                               ^ expected `u32`, found `u16`
+   |                              |
+   |                              first introduced with type `u32` here
 ...
 LL |     = Some((0u8, Some((1u16, 2u32))))
    |       ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:47:65
    |
 LL |     if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x))))
-   |                                                                 ^ expected `u8`, found `u32`
+   |                  - first introduced with type `u8` here         ^ expected `u8`, found `u32`
 ...
 LL |     = Some((0u8, Some((1u16, 2u32))))
    |       ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>`
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:55:39
    |
 LL |     let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2);
-   |                                       ^    ---------------- this expression has type `main::Blah`
-   |                                       |
-   |                                       expected `usize`, found `isize`
+   |                       -               ^    ---------------- this expression has type `main::Blah`
+   |                       |               |
+   |                       |               expected `usize`, found `isize`
+   |                       first introduced with type `usize` here
+   |
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:58:19
    |
 LL |     let (x, y) | (y, x) = (0u8, 1u16);
-   |                   ^       ----------- this expression has type `(u8, u16)`
-   |                   |
-   |                   expected `u16`, found `u8`
+   |             -     ^       ----------- this expression has type `(u8, u16)`
+   |             |     |
+   |             |     expected `u16`, found `u8`
+   |             first introduced with type `u16` here
+   |
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:58:22
    |
 LL |     let (x, y) | (y, x) = (0u8, 1u16);
-   |                      ^    ----------- this expression has type `(u8, u16)`
-   |                      |
-   |                      expected `u8`, found `u16`
+   |          -           ^    ----------- this expression has type `(u8, u16)`
+   |          |           |
+   |          |           expected `u8`, found `u16`
+   |          first introduced with type `u8` here
+   |
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:62:42
    |
 LL |     fn f1((Blah::A(_, x, y) | Blah::B(x, y)): Blah) {}
-   |                                          ^    ---- expected due to this
-   |                                          |
-   |                                          expected `usize`, found `isize`
+   |                          -               ^    ---- expected due to this
+   |                          |               |
+   |                          |               expected `usize`, found `isize`
+   |                          first introduced with type `usize` here
+   |
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:65:22
    |
 LL |     fn f2(((x, y) | (y, x)): (u8, u16)) {}
-   |                      ^       --------- expected due to this
-   |                      |
-   |                      expected `u16`, found `u8`
+   |                -     ^       --------- expected due to this
+   |                |     |
+   |                |     expected `u16`, found `u8`
+   |                first introduced with type `u16` here
+   |
+   = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/or-patterns-binding-type-mismatch.rs:65:25
    |
 LL |     fn f2(((x, y) | (y, x)): (u8, u16)) {}
-   |                         ^    --------- expected due to this
-   |                         |
-   |                         expected `u8`, found `u16`
+   |             -           ^    --------- expected due to this
+   |             |           |
+   |             |           expected `u8`, found `u16`
+   |             first introduced with type `u8` here
+   |
+   = note: a binding must have the same type in all alternatives
 
 error: aborting due to 22 previous errors
 
diff --git a/src/test/ui/pattern/pat-tuple-bad-type.stderr b/src/test/ui/pattern/pat-tuple-bad-type.stderr
index 95cca38f7de..598b6a3794e 100644
--- a/src/test/ui/pattern/pat-tuple-bad-type.stderr
+++ b/src/test/ui/pattern/pat-tuple-bad-type.stderr
@@ -12,6 +12,8 @@ LL |         (..) => {}
 error[E0308]: mismatched types
   --> $DIR/pat-tuple-bad-type.rs:10:9
    |
+LL |     match 0u8 {
+   |           --- this expression has type `u8`
 LL |         (..) => {}
    |         ^^^^ expected `u8`, found `()`
 
diff --git a/src/test/ui/pattern/pat-tuple-overfield.stderr b/src/test/ui/pattern/pat-tuple-overfield.stderr
index 25d02b8627c..45b6fd1b4d4 100644
--- a/src/test/ui/pattern/pat-tuple-overfield.stderr
+++ b/src/test/ui/pattern/pat-tuple-overfield.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/pat-tuple-overfield.rs:5:9
    |
+LL |     match (1, 2, 3) {
+   |           --------- this expression has type `({integer}, {integer}, {integer})`
 LL |         (1, 2, 3, 4) => {}
    |         ^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 4 elements
    |
@@ -10,6 +12,9 @@ LL |         (1, 2, 3, 4) => {}
 error[E0308]: mismatched types
   --> $DIR/pat-tuple-overfield.rs:6:9
    |
+LL |     match (1, 2, 3) {
+   |           --------- this expression has type `({integer}, {integer}, {integer})`
+LL |         (1, 2, 3, 4) => {}
 LL |         (1, 2, .., 3, 4) => {}
    |         ^^^^^^^^^^^^^^^^ expected a tuple with 3 elements, found one with 4 elements
    |
diff --git a/src/test/ui/pattern/pattern-ident-path-generics.stderr b/src/test/ui/pattern/pattern-ident-path-generics.stderr
index 338eb6ff0c8..24b5cdf98d5 100644
--- a/src/test/ui/pattern/pattern-ident-path-generics.stderr
+++ b/src/test/ui/pattern/pattern-ident-path-generics.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/pattern-ident-path-generics.rs:3:9
    |
+LL |     match Some("foo") {
+   |           ----------- this expression has type `std::option::Option<&str>`
 LL |         None::<isize> => {}
    |         ^^^^^^^^^^^^^ expected `&str`, found `isize`
    |
diff --git a/src/test/ui/resolve/name-clash-nullary.stderr b/src/test/ui/resolve/name-clash-nullary.stderr
index aeeb0c45191..2de0b6a4969 100644
--- a/src/test/ui/resolve/name-clash-nullary.stderr
+++ b/src/test/ui/resolve/name-clash-nullary.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/name-clash-nullary.rs:2:7
    |
 LL |   let None: isize = 42;
-   |       ^^^^ expected `isize`, found enum `std::option::Option`
+   |       ^^^^  ----- expected due to this
+   |       |
+   |       expected `isize`, found enum `std::option::Option`
    |
    = note: expected type `isize`
               found enum `std::option::Option<_>`
diff --git a/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr b/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr
index 61d1001ce91..749ed131b20 100644
--- a/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr
+++ b/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr
@@ -26,7 +26,11 @@ error[E0308]: mismatched types
 LL |     match x {
    |           - this expression has type `Opts`
 LL |       Opts::A(ref i) | Opts::B(i) => {}
-   |                                ^ expected `&isize`, found `isize`
+   |               -----            ^ expected `&isize`, found `isize`
+   |               |
+   |               first introduced with type `&isize` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/resolve-inconsistent-binding-mode.rs:16:32
@@ -34,7 +38,11 @@ error[E0308]: mismatched types
 LL |     match x {
    |           - this expression has type `Opts`
 LL |       Opts::A(ref i) | Opts::B(i) => {}
-   |                                ^ expected `&isize`, found `isize`
+   |               -----            ^ expected `&isize`, found `isize`
+   |               |
+   |               first introduced with type `&isize` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
   --> $DIR/resolve-inconsistent-binding-mode.rs:25:36
@@ -42,10 +50,13 @@ error[E0308]: mismatched types
 LL |     match x {
    |           - this expression has type `Opts`
 LL |       Opts::A(ref mut i) | Opts::B(ref i) => {}
-   |                                    ^^^^^ types differ in mutability
+   |               ---------            ^^^^^ types differ in mutability
+   |               |
+   |               first introduced with type `&mut isize` here
    |
    = note: expected type `&mut isize`
               found type `&isize`
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/resolve/resolve-inconsistent-names.stderr b/src/test/ui/resolve/resolve-inconsistent-names.stderr
index 5c87f7c684f..1d3079c90ba 100644
--- a/src/test/ui/resolve/resolve-inconsistent-names.stderr
+++ b/src/test/ui/resolve/resolve-inconsistent-names.stderr
@@ -89,7 +89,11 @@ error[E0308]: mismatched types
 LL |     match x {
    |           - this expression has type `(E, E)`
 LL |         (A, B) | (ref B, c) | (c, A) => ()
-   |                   ^^^^^ expected enum `E`, found `&E`
+   |             -     ^^^^^ expected enum `E`, found `&E`
+   |             |
+   |             first introduced with type `E` here
+   |
+   = note: in the same arm, a binding must have the same type in all alternatives
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/rfc-2005-default-binding-mode/const.stderr b/src/test/ui/rfc-2005-default-binding-mode/const.stderr
index f25fc300d7f..27efd450b94 100644
--- a/src/test/ui/rfc-2005-default-binding-mode/const.stderr
+++ b/src/test/ui/rfc-2005-default-binding-mode/const.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/const.rs:14:9
    |
+LL |     match &f {
+   |           -- this expression has type `&Foo`
 LL |         FOO => {},
    |         ^^^ expected `&Foo`, found struct `Foo`
 
diff --git a/src/test/ui/rfc-2005-default-binding-mode/lit.stderr b/src/test/ui/rfc-2005-default-binding-mode/lit.stderr
index b0d60c7a4c8..6d18a39606c 100644
--- a/src/test/ui/rfc-2005-default-binding-mode/lit.stderr
+++ b/src/test/ui/rfc-2005-default-binding-mode/lit.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/lit.rs:7:13
    |
+LL |     match &s {
+   |           -- this expression has type `&&str`
 LL |             "abc" => true,
    |             ^^^^^ expected `&str`, found `str`
    |
@@ -10,6 +12,8 @@ LL |             "abc" => true,
 error[E0308]: mismatched types
   --> $DIR/lit.rs:16:9
    |
+LL |     match &s {
+   |           -- this expression has type `&&[u8]`
 LL |         b"abc" => true,
    |         ^^^^^^ expected `&[u8]`, found array `[u8; 3]`
    |
diff --git a/src/test/ui/slightly-nice-generic-literal-messages.stderr b/src/test/ui/slightly-nice-generic-literal-messages.stderr
index 61eabed9504..14f01f0ebdf 100644
--- a/src/test/ui/slightly-nice-generic-literal-messages.stderr
+++ b/src/test/ui/slightly-nice-generic-literal-messages.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/slightly-nice-generic-literal-messages.rs:7:9
    |
+LL |     match Foo(1.1, marker::PhantomData) {
+   |           ----------------------------- this expression has type `Foo<{float}, _>`
 LL |         1 => {}
    |         ^ expected struct `Foo`, found integer
    |
diff --git a/src/test/ui/suggestions/match-ergonomics.stderr b/src/test/ui/suggestions/match-ergonomics.stderr
index abdb754acc5..559a2d29551 100644
--- a/src/test/ui/suggestions/match-ergonomics.stderr
+++ b/src/test/ui/suggestions/match-ergonomics.stderr
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/match-ergonomics.rs:4:10
    |
+LL |     match &x[..] {
+   |           ------ this expression has type `&[i32]`
 LL |         [&v] => {},
    |          ^^
    |          |
@@ -25,6 +27,8 @@ LL |         [v] => {},
 error[E0308]: mismatched types
   --> $DIR/match-ergonomics.rs:29:9
    |
+LL |     match y {
+   |           - this expression has type `i32`
 LL |         &v => {},
    |         ^^
    |         |
@@ -38,7 +42,7 @@ error[E0308]: mismatched types
   --> $DIR/match-ergonomics.rs:40:13
    |
 LL |     if let [&v] = &x[..] {}
-   |             ^^
+   |             ^^    ------ this expression has type `&[i32]`
    |             |
    |             expected `i32`, found reference
    |             help: you can probably remove the explicit borrow: `v`
diff --git a/src/test/ui/suppressed-error.stderr b/src/test/ui/suppressed-error.stderr
index 846cd2adcd8..c2874ae9a14 100644
--- a/src/test/ui/suppressed-error.stderr
+++ b/src/test/ui/suppressed-error.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/suppressed-error.rs:2:9
    |
 LL |     let (x, y) = ();
-   |         ^^^^^^ expected `()`, found tuple
+   |         ^^^^^^   -- this expression has type `()`
+   |         |
+   |         expected `()`, found tuple
    |
    = note: expected unit type `()`
                   found tuple `(_, _)`