From a873337f2100ffa341f1a03e316ded6bfa2e95f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 5 Jan 2019 17:08:15 -0800 Subject: [PATCH] Point at the match discriminant when arm pattern has a type mismatch --- src/librustc/infer/error_reporting/mod.rs | 3 + src/librustc/traits/error_reporting.rs | 4 +- src/librustc/traits/mod.rs | 9 +- src/librustc/traits/structural_impls.rs | 3 + src/librustc_typeck/check/_match.rs | 147 ++++++++++-------- src/librustc_typeck/check/demand.rs | 21 ++- src/librustc_typeck/check/mod.rs | 17 +- src/test/ui/block-result/issue-13624.stderr | 2 + src/test/ui/error-codes/E0308-4.stderr | 2 + src/test/ui/issues/issue-11844.stderr | 2 + src/test/ui/issues/issue-12552.stderr | 2 + src/test/ui/issues/issue-13466.stderr | 5 + src/test/ui/issues/issue-15896.stderr | 3 + src/test/ui/issues/issue-16401.stderr | 2 + src/test/ui/issues/issue-3680.stderr | 2 + src/test/ui/issues/issue-5100.stderr | 2 + src/test/ui/issues/issue-5358-1.stderr | 2 + src/test/ui/issues/issue-7092.stderr | 2 + src/test/ui/match/match-range-fail.stderr | 2 + src/test/ui/match/match-struct.stderr | 2 + src/test/ui/match/match-tag-unary.stderr | 4 +- src/test/ui/mismatched_types/E0409.stderr | 2 + src/test/ui/or-pattern-mismatch.stderr | 4 +- .../ui/pattern/pattern-error-continue.stderr | 2 + src/test/ui/pattern/pattern-tyvar.stderr | 2 + .../resolve-inconsistent-binding-mode.stderr | 6 + ...structure-constructor-type-mismatch.stderr | 6 + 27 files changed, 183 insertions(+), 77 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 4cce8343c02..0063e488b0d 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -487,6 +487,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) { match cause.code { + ObligationCauseCode::MatchExpressionArmPattern { span, ty } => { + err.span_label(span, format!("this match expression evaluates to `{}`", ty)); + } ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source { hir::MatchSource::IfLetDesugar { .. } => { let msg = "`if let` arm with an incompatible type"; diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 7ce5960b9b3..7d9e80fd60f 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1444,6 +1444,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match *cause_code { ObligationCauseCode::ExprAssignable | ObligationCauseCode::MatchExpressionArm { .. } | + ObligationCauseCode::MatchExpressionArmPattern { .. } | ObligationCauseCode::IfExpression | ObligationCauseCode::IfExpressionWithNoElse | ObligationCauseCode::MainFunctionType | @@ -1451,8 +1452,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::IntrinsicType | ObligationCauseCode::MethodReceiver | ObligationCauseCode::ReturnNoExpression | - ObligationCauseCode::MiscObligation => { - } + ObligationCauseCode::MiscObligation => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index b42d742b7f8..14c25b77a1b 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -220,8 +220,13 @@ pub enum ObligationCauseCode<'tcx> { ExprAssignable, /// Computing common supertype in the arms of a match expression - MatchExpressionArm { arm_span: Span, - source: hir::MatchSource }, + MatchExpressionArm { + arm_span: Span, + source: hir::MatchSource, + }, + + /// Computing common supertype in the pattern guard for the arms of a match expression + MatchExpressionArmPattern { span: Span, ty: Ty<'tcx> }, /// Computing common supertype in an if expression IfExpression, diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index ae2b83e1057..277e2ed0e87 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -517,6 +517,9 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { arm_span, source: source, }), + super::MatchExpressionArmPattern { span, ty } => { + tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty }) + } super::IfExpression => Some(super::IfExpression), super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse), super::MainFunctionType => Some(super::MainFunctionType), diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index b66c383edb5..48bd882da22 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -29,12 +29,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pat: &'gcx hir::Pat, mut expected: Ty<'tcx>, mut def_bm: ty::BindingMode, - is_arg: bool) - { + match_discrim_span: Option, + ) { let tcx = self.tcx; - debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?},is_arg={})", - pat, expected, def_bm, is_arg); + debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm); let is_non_ref_pat = match pat.node { PatKind::Struct(..) | @@ -210,8 +209,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let common_type = self.resolve_type_vars_if_possible(&lhs_ty); // subtyping doesn't matter here, as the value is some kind of scalar - self.demand_eqtype(pat.span, expected, lhs_ty); - self.demand_eqtype(pat.span, expected, rhs_ty); + self.demand_eqtype_pat(pat.span, expected, lhs_ty, match_discrim_span); + self.demand_eqtype_pat(pat.span, expected, rhs_ty, match_discrim_span); common_type } PatKind::Binding(ba, var_id, _, ref sub) => { @@ -240,13 +239,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is // required. However, we use equality, which is stronger. See (*) for // an explanation. - self.demand_eqtype(pat.span, region_ty, local_ty); + self.demand_eqtype_pat(pat.span, region_ty, local_ty, match_discrim_span); } // otherwise the type of x is the expected type T ty::BindByValue(_) => { // As above, `T <: typeof(x)` is required but we // use equality, see (*) below. - self.demand_eqtype(pat.span, expected, local_ty); + self.demand_eqtype_pat(pat.span, expected, local_ty, match_discrim_span); } } @@ -254,23 +253,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // what the type of the binding `x` ought to be if var_id != pat.id { let vt = self.local_ty(pat.span, var_id).decl_ty; - self.demand_eqtype(pat.span, vt, local_ty); + self.demand_eqtype_pat(pat.span, vt, local_ty, match_discrim_span); } if let Some(ref p) = *sub { - self.check_pat_walk(&p, expected, def_bm, true); + self.check_pat_walk(&p, expected, def_bm, match_discrim_span); } local_ty } PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { - self.check_pat_tuple_struct(pat, qpath, &subpats, ddpos, expected, def_bm) + self.check_pat_tuple_struct( + pat, + qpath, + &subpats, + ddpos, + expected, + def_bm, + match_discrim_span, + ) } PatKind::Path(ref qpath) => { self.check_pat_path(pat, qpath, expected) } PatKind::Struct(ref qpath, ref fields, etc) => { - self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm) + self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, match_discrim_span) } PatKind::Tuple(ref elements, ddpos) => { let mut expected_len = elements.len(); @@ -295,12 +302,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // further errors being emitted when using the bindings. #50333 let element_tys_iter = (0..max_len).map(|_| tcx.types.err); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk(elem, &tcx.types.err, def_bm, true); + self.check_pat_walk(elem, &tcx.types.err, def_bm, match_discrim_span); } tcx.mk_tup(element_tys_iter) } else { for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk(elem, &element_tys[i], def_bm, true); + self.check_pat_walk(elem, &element_tys[i], def_bm, match_discrim_span); } pat_ty } @@ -313,11 +320,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Here, `demand::subtype` is good enough, but I don't // think any errors can be introduced by using // `demand::eqtype`. - self.demand_eqtype(pat.span, expected, uniq_ty); - self.check_pat_walk(&inner, inner_ty, def_bm, true); + self.demand_eqtype_pat(pat.span, expected, uniq_ty, match_discrim_span); + self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span); uniq_ty } else { - self.check_pat_walk(&inner, tcx.types.err, def_bm, true); + self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span); tcx.types.err } } @@ -349,15 +356,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Look for a case like `fn foo(&foo: u32)` and suggest // `fn foo(foo: &u32)` if let Some(mut err) = err { - if is_arg { - if let PatKind::Binding(..) = inner.node { - if let Ok(snippet) = tcx.sess.source_map() - .span_to_snippet(pat.span) - { - err.help(&format!("did you mean `{}: &{}`?", - &snippet[1..], - expected)); - } + if let PatKind::Binding(..) = inner.node { + if let Ok(snippet) = tcx.sess.source_map() + .span_to_snippet(pat.span) + { + err.help(&format!("did you mean `{}: &{}`?", + &snippet[1..], + expected)); } } err.emit(); @@ -366,10 +371,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; - self.check_pat_walk(&inner, inner_ty, def_bm, true); + self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span); rptr_ty } else { - self.check_pat_walk(&inner, tcx.types.err, def_bm, true); + self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span); tcx.types.err } } @@ -427,13 +432,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; for elt in before { - self.check_pat_walk(&elt, inner_ty, def_bm, true); + self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span); } if let Some(ref slice) = *slice { - self.check_pat_walk(&slice, slice_ty, def_bm, true); + self.check_pat_walk(&slice, slice_ty, def_bm, match_discrim_span); } for elt in after { - self.check_pat_walk(&elt, inner_ty, def_bm, true); + self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span); } expected_ty } @@ -524,12 +529,14 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); true } - pub fn check_match(&self, - expr: &'gcx hir::Expr, - discrim: &'gcx hir::Expr, - arms: &'gcx [hir::Arm], - expected: Expectation<'tcx>, - match_src: hir::MatchSource) -> Ty<'tcx> { + pub fn check_match( + &self, + expr: &'gcx hir::Expr, + discrim: &'gcx hir::Expr, + arms: &'gcx [hir::Arm], + expected: Expectation<'tcx>, + match_src: hir::MatchSource, + ) -> Ty<'tcx> { let tcx = self.tcx; // Not entirely obvious: if matches may create ref bindings, we want to @@ -624,8 +631,12 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let mut all_pats_diverge = Diverges::WarnedAlways; for p in &arm.pats { self.diverges.set(Diverges::Maybe); - self.check_pat_walk(&p, discrim_ty, - ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true); + self.check_pat_walk( + &p, + discrim_ty, + ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), + Some(discrim.span), + ); all_pats_diverge &= self.diverges.get(); } @@ -703,26 +714,29 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); coercion.complete(self) } - fn check_pat_struct(&self, - pat: &'gcx hir::Pat, - qpath: &hir::QPath, - fields: &'gcx [Spanned], - etc: bool, - expected: Ty<'tcx>, - def_bm: ty::BindingMode) -> Ty<'tcx> + fn check_pat_struct( + &self, + pat: &'gcx hir::Pat, + qpath: &hir::QPath, + fields: &'gcx [Spanned], + etc: bool, + expected: Ty<'tcx>, + def_bm: ty::BindingMode, + match_discrim_span: Option, + ) -> Ty<'tcx> { // Resolve the path and check the definition for errors. let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) { variant_ty } else { for field in fields { - self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, true); + self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, match_discrim_span); } return self.tcx.types.err; }; // Type-check the path. - self.demand_eqtype(pat.span, expected, pat_ty); + self.demand_eqtype_pat(pat.span, expected, pat_ty, match_discrim_span); // Type-check subpatterns. if self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc, def_bm) { @@ -732,11 +746,12 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); } } - fn check_pat_path(&self, - pat: &hir::Pat, - qpath: &hir::QPath, - expected: Ty<'tcx>) -> Ty<'tcx> - { + fn check_pat_path( + &self, + pat: &hir::Pat, + qpath: &hir::QPath, + expected: Ty<'tcx>, + ) -> Ty<'tcx> { let tcx = self.tcx; // Resolve the path and check the definition for errors. @@ -767,18 +782,20 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); pat_ty } - fn check_pat_tuple_struct(&self, - pat: &hir::Pat, - qpath: &hir::QPath, - subpats: &'gcx [P], - ddpos: Option, - expected: Ty<'tcx>, - def_bm: ty::BindingMode) -> Ty<'tcx> - { + fn check_pat_tuple_struct( + &self, + pat: &hir::Pat, + qpath: &hir::QPath, + subpats: &'gcx [P], + ddpos: Option, + expected: Ty<'tcx>, + def_bm: ty::BindingMode, + match_arm_pat_span: Option, + ) -> Ty<'tcx> { let tcx = self.tcx; let on_error = || { for pat in subpats { - self.check_pat_walk(&pat, tcx.types.err, def_bm, true); + self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span); } }; let report_unexpected_def = |def: Def| { @@ -826,7 +843,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let pat_ty = pat_ty.fn_sig(tcx).output(); let pat_ty = pat_ty.no_bound_vars().expect("expected fn type"); - self.demand_eqtype(pat.span, expected, pat_ty); + self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span); // Type-check subpatterns. if subpats.len() == variant.fields.len() || @@ -837,7 +854,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); }; for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs); - self.check_pat_walk(&subpat, field_ty, def_bm, true); + self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span); self.tcx.check_stability(variant.fields[i].did, Some(pat.id), subpat.span); } @@ -917,7 +934,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); } }; - self.check_pat_walk(&field.pat, field_ty, def_bm, true); + self.check_pat_walk(&field.pat, field_ty, def_bm, None); } let mut unmentioned_fields = variant.fields .iter() diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 41f2b0ec7d2..c0cedd77440 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -1,6 +1,6 @@ use check::FnCtxt; use rustc::infer::InferOk; -use rustc::traits::ObligationCause; +use rustc::traits::{ObligationCause, ObligationCauseCode}; use syntax::ast; use syntax::util::parser::PREC_POSTFIX; @@ -66,6 +66,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } + pub fn demand_eqtype_pat( + &self, + cause_span: Span, + expected: Ty<'tcx>, + actual: Ty<'tcx>, + match_expr_span: Option, + ) { + let cause = if let Some(span) = match_expr_span { + self.cause( + cause_span, + ObligationCauseCode::MatchExpressionArmPattern { span, ty: expected }, + ) + } else { + self.misc(cause_span) + }; + self.demand_eqtype_with_origin(&cause, expected, actual).map(|mut err| err.emit()); + } + + pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1a5d164873d..438deecbe77 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1084,8 +1084,12 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // Add formal parameters. for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) { // Check the pattern. - fcx.check_pat_walk(&arg.pat, arg_ty, - ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true); + fcx.check_pat_walk( + &arg.pat, + arg_ty, + ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), + None, + ); // Check that argument is Sized. // The check for a non-trivial pattern is a hack to avoid duplicate warnings @@ -4723,9 +4727,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - self.check_pat_walk(&local.pat, t, - ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), - true); + self.check_pat_walk( + &local.pat, + t, + ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), + None, + ); let pat_ty = self.node_ty(local.pat.hir_id); if pat_ty.references_error() { self.write_ty(local.hir_id, pat_ty); diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr index b38633b0ffe..545d4916cf7 100644 --- a/src/test/ui/block-result/issue-13624.stderr +++ b/src/test/ui/block-result/issue-13624.stderr @@ -12,6 +12,8 @@ LL | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } error[E0308]: mismatched types --> $DIR/issue-13624.rs:22:9 | +LL | match enum_struct_variant { + | ------------------- this match expression evaluates to `()` LL | a::Enum::EnumStructVariant { x, y, z } => { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` | diff --git a/src/test/ui/error-codes/E0308-4.stderr b/src/test/ui/error-codes/E0308-4.stderr index 8117bc754b6..7971f1d9eda 100644 --- a/src/test/ui/error-codes/E0308-4.stderr +++ b/src/test/ui/error-codes/E0308-4.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/E0308-4.rs:4:9 | +LL | match x { + | - this match expression evaluates to `u8` LL | 0u8..=3i8 => (), //~ ERROR E0308 | ^^^^^^^^^ expected u8, found i8 diff --git a/src/test/ui/issues/issue-11844.stderr b/src/test/ui/issues/issue-11844.stderr index 05d2685958e..4459b64aa8f 100644 --- a/src/test/ui/issues/issue-11844.stderr +++ b/src/test/ui/issues/issue-11844.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-11844.rs:6:9 | +LL | match a { + | - this match expression evaluates to `std::option::Option>` LL | Ok(a) => //~ ERROR: mismatched types | ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result` | diff --git a/src/test/ui/issues/issue-12552.stderr b/src/test/ui/issues/issue-12552.stderr index ca5efcdc472..b299b3fb3e8 100644 --- a/src/test/ui/issues/issue-12552.stderr +++ b/src/test/ui/issues/issue-12552.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-12552.rs:6:5 | +LL | match t { + | - this match expression evaluates to `std::result::Result<_, {integer}>` LL | Some(k) => match k { //~ ERROR mismatched types | ^^^^^^^ expected enum `std::result::Result`, found enum `std::option::Option` | diff --git a/src/test/ui/issues/issue-13466.stderr b/src/test/ui/issues/issue-13466.stderr index 2f60070337b..8ba5114d143 100644 --- a/src/test/ui/issues/issue-13466.stderr +++ b/src/test/ui/issues/issue-13466.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-13466.rs:8:9 | +LL | let _x: usize = match Some(1) { + | ------- this match expression evaluates to `std::option::Option<{integer}>` LL | Ok(u) => u, | ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result` | @@ -10,6 +12,9 @@ LL | Ok(u) => u, error[E0308]: mismatched types --> $DIR/issue-13466.rs:14:9 | +LL | let _x: usize = match Some(1) { + | ------- this match expression evaluates to `std::option::Option<{integer}>` +... LL | Err(e) => panic!(e) | ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result` | diff --git a/src/test/ui/issues/issue-15896.stderr b/src/test/ui/issues/issue-15896.stderr index cd629841fee..b88bfea7e85 100644 --- a/src/test/ui/issues/issue-15896.stderr +++ b/src/test/ui/issues/issue-15896.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/issue-15896.rs:11:11 | +LL | let u = match e { + | - this match expression evaluates to `main::R` +LL | E::B( LL | Tau{t: x}, | ^^^^^^^^^ expected enum `main::R`, found struct `main::Tau` | diff --git a/src/test/ui/issues/issue-16401.stderr b/src/test/ui/issues/issue-16401.stderr index a1cf6c98705..ea5f89d18dd 100644 --- a/src/test/ui/issues/issue-16401.stderr +++ b/src/test/ui/issues/issue-16401.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-16401.rs:8:9 | +LL | match () { + | -- this match expression evaluates to `()` LL | Slice { data: data, len: len } => (), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `Slice` | diff --git a/src/test/ui/issues/issue-3680.stderr b/src/test/ui/issues/issue-3680.stderr index 78c3f92fb53..82b6462d3b4 100644 --- a/src/test/ui/issues/issue-3680.stderr +++ b/src/test/ui/issues/issue-3680.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-3680.rs:3:9 | +LL | match None { + | ---- this match expression evaluates to `std::option::Option<_>` LL | Err(_) => () | ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result` | diff --git a/src/test/ui/issues/issue-5100.stderr b/src/test/ui/issues/issue-5100.stderr index a6f6229fe78..d3072143c15 100644 --- a/src/test/ui/issues/issue-5100.stderr +++ b/src/test/ui/issues/issue-5100.stderr @@ -28,6 +28,8 @@ LL | (true, false, false) => () error[E0308]: mismatched types --> $DIR/issue-5100.rs:33:9 | +LL | match (true, false) { + | ------------- this match expression evaluates to `(bool, bool)` LL | box (true, false) => () | ^^^^^^^^^^^^^^^^^ expected tuple, found struct `std::boxed::Box` | diff --git a/src/test/ui/issues/issue-5358-1.stderr b/src/test/ui/issues/issue-5358-1.stderr index dbbafb38e65..bdd70ebac94 100644 --- a/src/test/ui/issues/issue-5358-1.stderr +++ b/src/test/ui/issues/issue-5358-1.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-5358-1.rs:6:9 | +LL | match S(Either::Left(5)) { + | ------------------ this match expression evaluates to `S` LL | Either::Right(_) => {} | ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either` | diff --git a/src/test/ui/issues/issue-7092.stderr b/src/test/ui/issues/issue-7092.stderr index aa24182e3a3..61564f9004e 100644 --- a/src/test/ui/issues/issue-7092.stderr +++ b/src/test/ui/issues/issue-7092.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-7092.rs:6:9 | +LL | match x { + | - this match expression evaluates to `Whatever` LL | Some(field) => | ^^^^^^^^^^^ expected enum `Whatever`, found enum `std::option::Option` | diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr index 54969927433..db7afc36bd7 100644 --- a/src/test/ui/match/match-range-fail.stderr +++ b/src/test/ui/match/match-range-fail.stderr @@ -19,6 +19,8 @@ LL | 10 ..= "what" => () error[E0308]: mismatched types --> $DIR/match-range-fail.rs:17:9 | +LL | match 5 { + | - this match expression evaluates to `{integer}` LL | 'c' ..= 100 => { } | ^^^^^^^^^^^ expected integer, found char | diff --git a/src/test/ui/match/match-struct.stderr b/src/test/ui/match/match-struct.stderr index bad41485a53..8e9d09288b1 100644 --- a/src/test/ui/match/match-struct.stderr +++ b/src/test/ui/match/match-struct.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/match-struct.rs:6:9 | +LL | match (S { a: 1 }) { + | ------------ this match expression evaluates to `S` LL | E::C(_) => (), | ^^^^^^^ expected struct `S`, found enum `E` | diff --git a/src/test/ui/match/match-tag-unary.stderr b/src/test/ui/match/match-tag-unary.stderr index c90029b2fa1..f5e7051a9e8 100644 --- a/src/test/ui/match/match-tag-unary.stderr +++ b/src/test/ui/match/match-tag-unary.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/match-tag-unary.rs:4:43 | LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } //~ ERROR mismatched types - | ^^^^^^^ expected enum `A`, found enum `B` + | - ^^^^^^^ expected enum `A`, found enum `B` + | | + | this match expression evaluates to `A` | = note: expected type `A` found type `B` diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr index 08f132efd05..4df2984a6dc 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -9,6 +9,8 @@ LL | (0, ref y) | (y, 0) => {} //~ ERROR E0409 error[E0308]: mismatched types --> $DIR/E0409.rs:5:23 | +LL | match x { + | - this match expression evaluates to `_` LL | (0, ref y) | (y, 0) => {} //~ ERROR E0409 | ^ expected &{integer}, found integer | diff --git a/src/test/ui/or-pattern-mismatch.stderr b/src/test/ui/or-pattern-mismatch.stderr index 731b2090a7b..49f68c7f068 100644 --- a/src/test/ui/or-pattern-mismatch.stderr +++ b/src/test/ui/or-pattern-mismatch.stderr @@ -2,7 +2,9 @@ error[E0308]: mismatched types --> $DIR/or-pattern-mismatch.rs:3:68 | LL | fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, y) => { } } } - | ^ expected usize, found isize + | ---------------- ^ expected usize, found isize + | | + | this match expression evaluates to `_` | = note: expected type `usize` found type `isize` diff --git a/src/test/ui/pattern/pattern-error-continue.stderr b/src/test/ui/pattern/pattern-error-continue.stderr index c17d4b70f0b..318067cbb50 100644 --- a/src/test/ui/pattern/pattern-error-continue.stderr +++ b/src/test/ui/pattern/pattern-error-continue.stderr @@ -21,6 +21,8 @@ LL | A::B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but error[E0308]: mismatched types --> $DIR/pattern-error-continue.rs:22:9 | +LL | match 'c' { + | --- this match expression evaluates to `char` LL | S { .. } => (), | ^^^^^^^^ expected char, found struct `S` | diff --git a/src/test/ui/pattern/pattern-tyvar.stderr b/src/test/ui/pattern/pattern-tyvar.stderr index dae17fa5166..cb9058a30da 100644 --- a/src/test/ui/pattern/pattern-tyvar.stderr +++ b/src/test/ui/pattern/pattern-tyvar.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/pattern-tyvar.rs:5:18 | +LL | match t { + | - this match expression evaluates to `std::option::Option>` LL | Bar::T1(_, Some::(x)) => { //~ ERROR mismatched types | ^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found isize | diff --git a/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr b/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr index a14d3d67b10..69b151c733b 100644 --- a/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr +++ b/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr @@ -23,6 +23,8 @@ LL | Opts::A(ref mut i) | Opts::B(ref i) => {} error[E0308]: mismatched types --> $DIR/resolve-inconsistent-binding-mode.rs:7:32 | +LL | match x { + | - this match expression evaluates to `_` LL | Opts::A(ref i) | Opts::B(i) => {} | ^ expected &isize, found isize | @@ -32,6 +34,8 @@ LL | Opts::A(ref i) | Opts::B(i) => {} error[E0308]: mismatched types --> $DIR/resolve-inconsistent-binding-mode.rs:16:32 | +LL | match x { + | - this match expression evaluates to `_` LL | Opts::A(ref i) | Opts::B(i) => {} | ^ expected &isize, found isize | @@ -41,6 +45,8 @@ LL | Opts::A(ref i) | Opts::B(i) => {} error[E0308]: mismatched types --> $DIR/resolve-inconsistent-binding-mode.rs:25:36 | +LL | match x { + | - this match expression evaluates to `_` LL | Opts::A(ref mut i) | Opts::B(ref i) => {} | ^^^^^ types differ in mutability | diff --git a/src/test/ui/structs/structure-constructor-type-mismatch.stderr b/src/test/ui/structs/structure-constructor-type-mismatch.stderr index 3c1ed8e69a6..564e3551065 100644 --- a/src/test/ui/structs/structure-constructor-type-mismatch.stderr +++ b/src/test/ui/structs/structure-constructor-type-mismatch.stderr @@ -109,6 +109,8 @@ LL | PointF:: { .. } => {} //~ ERROR wrong number of type arguments error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:54:9 | +LL | match (Point { x: 1, y: 2 }) { + | ---------------------- this match expression evaluates to `Point<{integer}>` LL | PointF:: { .. } => {} //~ ERROR wrong number of type arguments | ^^^^^^^^^^^^^^^^^^^^ expected integer, found f32 | @@ -118,6 +120,8 @@ LL | PointF:: { .. } => {} //~ ERROR wrong number of type arguments error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:59:9 | +LL | match (Point { x: 1, y: 2 }) { + | ---------------------- this match expression evaluates to `Point<{integer}>` LL | PointF { .. } => {} //~ ERROR mismatched types | ^^^^^^^^^^^^^ expected integer, found f32 | @@ -127,6 +131,8 @@ LL | PointF { .. } => {} //~ ERROR mismatched types error[E0308]: mismatched types --> $DIR/structure-constructor-type-mismatch.rs:67:9 | +LL | match (Pair { x: 1, y: 2 }) { + | --------------------- this match expression evaluates to `Pair<{integer}, {integer}>` LL | PairF:: { .. } => {} //~ ERROR mismatched types | ^^^^^^^^^^^^^^^^^^^ expected integer, found f32 |