diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index adda0cde24fc0..f7301280acd69 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, } -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 { - 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 { - 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 c289176c3038c..7ed6cbf93dab2 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> { - 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> { 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 2c7cbed6a2d36..1df7c64f2c6f0 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> { - 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>, &'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 f99bf2ffdc9d4..1382cf643a173 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 122c71bebc488..e0537ff6faaf8 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 60c4cceac51be..45fede4410630 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 361369e68bc08..f0285730c5a26 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 c47e8689436ee..c81d6dcaf0217 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 58e82facf802e..4a29464aebd2b 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 1cf61ebad4352..5078f03d6017a 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 4b6260b2199e1..3703a59edb836 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 2306fb352738f..f5c8b02ae2722 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 802a2fef6bd40..c2bce305877b4 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 ccc8ac1278c63..cad1cef5155d5 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 9924b0d7f72eb..97933ca122944 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>` - | | - | expected integer, found enum `E` + | - ^ ------- this expression has type `E>` + | | | + | | 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 c329f90596091..8c01e00bae353 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 5094f04b9204f..d5e029d668d47 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` 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` - | | - | expected `usize`, found `isize` + | - ^ ---------------------- this expression has type `std::option::Option` + | | | + | | 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 95cca38f7de14..598b6a3794ef7 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 25d02b8627cbc..45b6fd1b4d445 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 338eb6ff0c83b..24b5cdf98d5e2 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:: => {} | ^^^^^^^^^^^^^ 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 aeeb0c4519161..2de0b6a496958 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 61d1001ce9154..749ed131b204e 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 5c87f7c684f3b..1d3079c90baf6 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 f25fc300d7f3f..27efd450b9471 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 b0d60c7a4c83f..6d18a39606ccf 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 61eabed950423..14f01f0ebdf73 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 abdb754acc5fa..559a2d29551d3 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 846cd2adcd8fe..c2874ae9a14b8 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 `(_, _)`