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 1/5] 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 4cce8343c02c8..0063e488b0da1 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 7ce5960b9b3d6..7d9e80fd60f5c 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 b42d742b7f841..14c25b77a1b82 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 ae2b83e105773..277e2ed0e87d2 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 b66c383edb51e..48bd882da22b3 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 41f2b0ec7d24e..c0cedd77440d9 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 1a5d164873d32..438deecbe77d3 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 b38633b0ffeea..545d4916cf7a5 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 8117bc754b6b9..7971f1d9eda44 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 05d2685958eb8..4459b64aa8f06 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 ca5efcdc4726a..b299b3fb3e832 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 2f60070337b77..8ba5114d143b0 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 cd629841fee83..b88bfea7e85b5 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 a1cf6c98705aa..ea5f89d18ddb2 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 78c3f92fb53b5..82b6462d3b4b0 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 a6f6229fe78d2..d3072143c1555 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 dbbafb38e6580..bdd70ebac94b8 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 aa24182e3a39d..61564f9004eb5 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 54969927433a4..db7afc36bd7b0 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 bad41485a53b1..8e9d09288b1db 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 c90029b2fa12e..f5e7051a9e820 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 08f132efd0526..4df2984a6dcc6 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 731b2090a7ba0..49f68c7f0682a 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 c17d4b70f0b00..318067cbb50bf 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 dae17fa516610..cb9058a30da43 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 a14d3d67b10a3..69b151c733bf3 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 3c1ed8e69a6bd..564e3551065df 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 | From f9e10f1aee72445c0e3c1e25915fbf5f2070256a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 6 Jan 2019 14:08:08 -0800 Subject: [PATCH 2/5] tidy fix --- src/librustc_typeck/check/_match.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 48bd882da22b3..85292dc1f13c3 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -730,7 +730,12 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); variant_ty } else { for field in fields { - self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, match_discrim_span); + self.check_pat_walk( + &field.node.pat, + self.tcx.types.err, + def_bm, + match_discrim_span, + ); } return self.tcx.types.err; }; From 72d965f7b7c2dcf0f6d076982c254093cdf96fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 6 Jan 2019 14:23:57 -0800 Subject: [PATCH 3/5] Reword label as per review comment --- src/librustc/infer/error_reporting/mod.rs | 2 +- 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 | 4 ++-- src/test/ui/issues/issue-15896.stderr | 2 +- 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 | 2 +- src/test/ui/mismatched_types/E0409.stderr | 2 +- src/test/ui/or-pattern-mismatch.stderr | 2 +- src/test/ui/pattern/pattern-error-continue.stderr | 2 +- src/test/ui/pattern/pattern-tyvar.stderr | 2 +- .../ui/resolve/resolve-inconsistent-binding-mode.stderr | 6 +++--- .../ui/structs/structure-constructor-type-mismatch.stderr | 6 +++--- 21 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 0063e488b0da1..eec92675af681 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -488,7 +488,7 @@ 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)); + err.span_label(span, format!("this match expression has type `{}`", ty)); } ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source { hir::MatchSource::IfLetDesugar { .. } => { diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr index 545d4916cf7a5..417667a5354fd 100644 --- a/src/test/ui/block-result/issue-13624.stderr +++ b/src/test/ui/block-result/issue-13624.stderr @@ -13,7 +13,7 @@ error[E0308]: mismatched types --> $DIR/issue-13624.rs:22:9 | LL | match enum_struct_variant { - | ------------------- this match expression evaluates to `()` + | ------------------- this match expression has type `()` 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 7971f1d9eda44..f69a389336590 100644 --- a/src/test/ui/error-codes/E0308-4.stderr +++ b/src/test/ui/error-codes/E0308-4.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/E0308-4.rs:4:9 | LL | match x { - | - this match expression evaluates to `u8` + | - this match expression has type `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 4459b64aa8f06..683ad48ff52c0 100644 --- a/src/test/ui/issues/issue-11844.stderr +++ b/src/test/ui/issues/issue-11844.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-11844.rs:6:9 | LL | match a { - | - this match expression evaluates to `std::option::Option>` + | - this match expression has type `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 b299b3fb3e832..768d11bf899a1 100644 --- a/src/test/ui/issues/issue-12552.stderr +++ b/src/test/ui/issues/issue-12552.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-12552.rs:6:5 | LL | match t { - | - this match expression evaluates to `std::result::Result<_, {integer}>` + | - this match expression has type `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 8ba5114d143b0..66255891f469a 100644 --- a/src/test/ui/issues/issue-13466.stderr +++ b/src/test/ui/issues/issue-13466.stderr @@ -2,7 +2,7 @@ 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}>` + | ------- this match expression has type `std::option::Option<{integer}>` LL | Ok(u) => u, | ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result` | @@ -13,7 +13,7 @@ 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}>` + | ------- this match expression has type `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 b88bfea7e85b5..de9757d5d32ed 100644 --- a/src/test/ui/issues/issue-15896.stderr +++ b/src/test/ui/issues/issue-15896.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-15896.rs:11:11 | LL | let u = match e { - | - this match expression evaluates to `main::R` + | - this match expression has type `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 ea5f89d18ddb2..1779d0befd871 100644 --- a/src/test/ui/issues/issue-16401.stderr +++ b/src/test/ui/issues/issue-16401.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-16401.rs:8:9 | LL | match () { - | -- this match expression evaluates to `()` + | -- this match expression has type `()` 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 82b6462d3b4b0..51903cfadab15 100644 --- a/src/test/ui/issues/issue-3680.stderr +++ b/src/test/ui/issues/issue-3680.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-3680.rs:3:9 | LL | match None { - | ---- this match expression evaluates to `std::option::Option<_>` + | ---- this match expression has type `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 d3072143c1555..0a918a789703e 100644 --- a/src/test/ui/issues/issue-5100.stderr +++ b/src/test/ui/issues/issue-5100.stderr @@ -29,7 +29,7 @@ error[E0308]: mismatched types --> $DIR/issue-5100.rs:33:9 | LL | match (true, false) { - | ------------- this match expression evaluates to `(bool, bool)` + | ------------- this match expression has type `(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 bdd70ebac94b8..649a0c1581a68 100644 --- a/src/test/ui/issues/issue-5358-1.stderr +++ b/src/test/ui/issues/issue-5358-1.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-5358-1.rs:6:9 | LL | match S(Either::Left(5)) { - | ------------------ this match expression evaluates to `S` + | ------------------ this match expression has type `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 61564f9004eb5..7bb6820287487 100644 --- a/src/test/ui/issues/issue-7092.stderr +++ b/src/test/ui/issues/issue-7092.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-7092.rs:6:9 | LL | match x { - | - this match expression evaluates to `Whatever` + | - this match expression has type `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 db7afc36bd7b0..532f5e23ff5e9 100644 --- a/src/test/ui/match/match-range-fail.stderr +++ b/src/test/ui/match/match-range-fail.stderr @@ -20,7 +20,7 @@ error[E0308]: mismatched types --> $DIR/match-range-fail.rs:17:9 | LL | match 5 { - | - this match expression evaluates to `{integer}` + | - this match expression has type `{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 8e9d09288b1db..2a24a293e9836 100644 --- a/src/test/ui/match/match-struct.stderr +++ b/src/test/ui/match/match-struct.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/match-struct.rs:6:9 | LL | match (S { a: 1 }) { - | ------------ this match expression evaluates to `S` + | ------------ this match expression has type `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 f5e7051a9e820..53b6635136966 100644 --- a/src/test/ui/match/match-tag-unary.stderr +++ b/src/test/ui/match/match-tag-unary.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } //~ ERROR mismatched types | - ^^^^^^^ expected enum `A`, found enum `B` | | - | this match expression evaluates to `A` + | this match expression has type `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 4df2984a6dcc6..a73f9ab4dfdda 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -10,7 +10,7 @@ error[E0308]: mismatched types --> $DIR/E0409.rs:5:23 | LL | match x { - | - this match expression evaluates to `_` + | - this match expression has type `_` 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 49f68c7f0682a..c3a203cf3ab6e 100644 --- a/src/test/ui/or-pattern-mismatch.stderr +++ b/src/test/ui/or-pattern-mismatch.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, y) => { } } } | ---------------- ^ expected usize, found isize | | - | this match expression evaluates to `_` + | this match expression has type `_` | = 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 318067cbb50bf..c2810d764c2ce 100644 --- a/src/test/ui/pattern/pattern-error-continue.stderr +++ b/src/test/ui/pattern/pattern-error-continue.stderr @@ -22,7 +22,7 @@ error[E0308]: mismatched types --> $DIR/pattern-error-continue.rs:22:9 | LL | match 'c' { - | --- this match expression evaluates to `char` + | --- this match expression has type `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 cb9058a30da43..69cd552aabd1b 100644 --- a/src/test/ui/pattern/pattern-tyvar.stderr +++ b/src/test/ui/pattern/pattern-tyvar.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/pattern-tyvar.rs:5:18 | LL | match t { - | - this match expression evaluates to `std::option::Option>` + | - this match expression has type `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 69b151c733bf3..148f084e401ac 100644 --- a/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr +++ b/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr @@ -24,7 +24,7 @@ error[E0308]: mismatched types --> $DIR/resolve-inconsistent-binding-mode.rs:7:32 | LL | match x { - | - this match expression evaluates to `_` + | - this match expression has type `_` LL | Opts::A(ref i) | Opts::B(i) => {} | ^ expected &isize, found isize | @@ -35,7 +35,7 @@ error[E0308]: mismatched types --> $DIR/resolve-inconsistent-binding-mode.rs:16:32 | LL | match x { - | - this match expression evaluates to `_` + | - this match expression has type `_` LL | Opts::A(ref i) | Opts::B(i) => {} | ^ expected &isize, found isize | @@ -46,7 +46,7 @@ error[E0308]: mismatched types --> $DIR/resolve-inconsistent-binding-mode.rs:25:36 | LL | match x { - | - this match expression evaluates to `_` + | - this match expression has type `_` 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 564e3551065df..cc62316bec185 100644 --- a/src/test/ui/structs/structure-constructor-type-mismatch.stderr +++ b/src/test/ui/structs/structure-constructor-type-mismatch.stderr @@ -110,7 +110,7 @@ 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}>` + | ---------------------- this match expression has type `Point<{integer}>` LL | PointF:: { .. } => {} //~ ERROR wrong number of type arguments | ^^^^^^^^^^^^^^^^^^^^ expected integer, found f32 | @@ -121,7 +121,7 @@ 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}>` + | ---------------------- this match expression has type `Point<{integer}>` LL | PointF { .. } => {} //~ ERROR mismatched types | ^^^^^^^^^^^^^ expected integer, found f32 | @@ -132,7 +132,7 @@ 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}>` + | --------------------- this match expression has type `Pair<{integer}, {integer}>` LL | PairF:: { .. } => {} //~ ERROR mismatched types | ^^^^^^^^^^^^^^^^^^^ expected integer, found f32 | From 486ecc5e27992175c194b5bb12a374d15293c9c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 6 Jan 2019 14:31:39 -0800 Subject: [PATCH 4/5] Don't add label to the match expr when the type is not fully realized --- src/librustc/infer/error_reporting/mod.rs | 4 +++- src/test/ui/match/match-range-fail.stderr | 2 -- src/test/ui/mismatched_types/E0409.stderr | 2 -- src/test/ui/or-pattern-mismatch.stderr | 4 +--- .../ui/resolve/resolve-inconsistent-binding-mode.stderr | 6 ------ 5 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index eec92675af681..f71cce8273c46 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -488,7 +488,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 has type `{}`", ty)); + if ty.is_suggestable() { // don't show type `_` + err.span_label(span, format!("this match expression has type `{}`", ty)); + } } ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source { hir::MatchSource::IfLetDesugar { .. } => { diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr index 532f5e23ff5e9..54969927433a4 100644 --- a/src/test/ui/match/match-range-fail.stderr +++ b/src/test/ui/match/match-range-fail.stderr @@ -19,8 +19,6 @@ LL | 10 ..= "what" => () error[E0308]: mismatched types --> $DIR/match-range-fail.rs:17:9 | -LL | match 5 { - | - this match expression has type `{integer}` LL | 'c' ..= 100 => { } | ^^^^^^^^^^^ expected integer, found char | diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr index a73f9ab4dfdda..08f132efd0526 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -9,8 +9,6 @@ LL | (0, ref y) | (y, 0) => {} //~ ERROR E0409 error[E0308]: mismatched types --> $DIR/E0409.rs:5:23 | -LL | match x { - | - this match expression has type `_` 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 c3a203cf3ab6e..731b2090a7ba0 100644 --- a/src/test/ui/or-pattern-mismatch.stderr +++ b/src/test/ui/or-pattern-mismatch.stderr @@ -2,9 +2,7 @@ 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 - | | - | this match expression has type `_` + | ^ expected usize, found isize | = note: expected type `usize` found type `isize` diff --git a/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr b/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr index 148f084e401ac..a14d3d67b10a3 100644 --- a/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr +++ b/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr @@ -23,8 +23,6 @@ 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 has type `_` LL | Opts::A(ref i) | Opts::B(i) => {} | ^ expected &isize, found isize | @@ -34,8 +32,6 @@ 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 has type `_` LL | Opts::A(ref i) | Opts::B(i) => {} | ^ expected &isize, found isize | @@ -45,8 +41,6 @@ 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 has type `_` LL | Opts::A(ref mut i) | Opts::B(ref i) => {} | ^^^^^ types differ in mutability | From 10fbdbf949f3ca171a52010eb2c53547c3e5b4f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 8 Jan 2019 16:32:52 -0800 Subject: [PATCH 5/5] Update documentation comment --- src/librustc_typeck/check/_match.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 85292dc1f13c3..1767af4870d3b 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -20,10 +20,23 @@ use std::cmp; use super::report_unexpected_variant_def; impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { - /// The `is_arg` argument indicates whether this pattern is the - /// *outermost* pattern in an argument (e.g., in `fn foo(&x: - /// &u32)`, it is true for the `&x` pattern but not `x`). This is - /// used to tailor error reporting. + /// `match_discrim_span` argument having a `Span` indicates that this pattern is part of + /// a match expression arm guard, and it points to the match discriminant to add context + /// in type errors. In the folloowing example, `match_discrim_span` corresponds to the + /// `a + b` expression: + /// + /// ```text + /// error[E0308]: mismatched types + /// --> src/main.rs:5:9 + /// | + /// 4 | let temp: usize = match a + b { + /// | ----- this expression has type `usize` + /// 5 | Ok(num) => num, + /// | ^^^^^^^ expected usize, found enum `std::result::Result` + /// | + /// = note: expected type `usize` + /// found type `std::result::Result<_, _>` + /// ``` pub fn check_pat_walk( &self, pat: &'gcx hir::Pat,