summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@gmail.com>2020-10-22 14:20:02 -0700
committerDavid Tolnay <dtolnay@gmail.com>2020-10-22 16:16:02 -0700
commitb0059500f6765612fbda6d33240116f7520d433a (patch)
treead06b9049f7c9502773745b5aa2bf7710530dbdb
parentf82adf5bdba6e2a9fe4a42c9d260f20b60b33960 (diff)
downloadrust-b0059500f6765612fbda6d33240116f7520d433a.tar.gz
Reduce diagram mess in 'match arms have incompatible types' error
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs16
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs1
-rw-r--r--compiler/rustc_typeck/src/check/_match.rs1
-rw-r--r--src/test/ui/match/match-incompat-type-semi.stderr48
4 files changed, 38 insertions, 28 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 795c5a64d26..3a0ec6327c1 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -619,6 +619,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
scrut_hir_id,
opt_suggest_box_span,
arm_span,
+ scrut_span,
..
}) => match source {
hir::MatchSource::IfLetDesugar { .. } => {
@@ -664,18 +665,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
Some(ty::error::ExpectedFound { expected, .. }) => expected,
_ => last_ty,
});
- let msg = "`match` arms have incompatible types";
- err.span_label(cause.span, msg);
+ let source_map = self.tcx.sess.source_map();
+ let mut any_multiline_arm = source_map.is_multiline(arm_span);
if prior_arms.len() <= 4 {
for sp in prior_arms {
+ any_multiline_arm |= source_map.is_multiline(*sp);
err.span_label(*sp, format!("this is found to be of type `{}`", t));
}
} else if let Some(sp) = prior_arms.last() {
+ any_multiline_arm |= source_map.is_multiline(*sp);
err.span_label(
*sp,
format!("this and all prior arms are found to be of type `{}`", t),
);
}
+ let outer_error_span = if any_multiline_arm {
+ // Cover just `match` and the scrutinee expression, not
+ // the entire match body, to reduce diagram noise.
+ cause.span.shrink_to_lo().to(scrut_span)
+ } else {
+ cause.span
+ };
+ let msg = "`match` arms have incompatible types";
+ err.span_label(outer_error_span, msg);
if let Some(sp) = semi_span {
err.span_suggestion_short(
sp,
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 26962aa1083..bbc46b8d608 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -343,6 +343,7 @@ static_assert_size!(ObligationCauseCode<'_>, 32);
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
pub struct MatchExpressionArmCause<'tcx> {
pub arm_span: Span,
+ pub scrut_span: Span,
pub semi_span: Option<Span>,
pub source: hir::MatchSource,
pub prior_arms: Vec<Span>,
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs
index 7cb23dc0537..398e013e62f 100644
--- a/compiler/rustc_typeck/src/check/_match.rs
+++ b/compiler/rustc_typeck/src/check/_match.rs
@@ -201,6 +201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr.span,
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
arm_span,
+ scrut_span: scrut.span,
semi_span,
source: match_src,
prior_arms: other_arms.clone(),
diff --git a/src/test/ui/match/match-incompat-type-semi.stderr b/src/test/ui/match/match-incompat-type-semi.stderr
index 1a2dbbcc29f..008b1c1e93d 100644
--- a/src/test/ui/match/match-incompat-type-semi.stderr
+++ b/src/test/ui/match/match-incompat-type-semi.stderr
@@ -56,36 +56,32 @@ LL | | };
error[E0308]: `match` arms have incompatible types
--> $DIR/match-incompat-type-semi.rs:39:17
|
-LL | let _ = match Some(42) {
- | _____________-
-LL | | Some(x) => {
-LL | | x
- | | - this is found to be of type `{integer}`
-LL | | },
-LL | | None => {
- | |_________________^
-LL | || },
- | ||_________^ expected integer, found `()`
-LL | | };
- | |_____- `match` arms have incompatible types
+LL | let _ = match Some(42) {
+ | -------------- `match` arms have incompatible types
+LL | Some(x) => {
+LL | x
+ | - this is found to be of type `{integer}`
+LL | },
+LL | None => {
+ | _________________^
+LL | | },
+ | |_________^ expected integer, found `()`
error[E0308]: `match` arms have incompatible types
--> $DIR/match-incompat-type-semi.rs:50:17
|
-LL | let _ = match Some(42) {
- | _____________-
-LL | | Some(x) => "rust-lang.org"
- | |____________________-
-LL | || .chars()
-LL | || .skip(1)
-LL | || .chain(Some(x as u8 as char))
-LL | || .take(10)
-LL | || .any(char::is_alphanumeric),
- | ||_______________________________________- this is found to be of type `bool`
-LL | | None => {}
- | | ^^ expected `bool`, found `()`
-LL | | };
- | |_____- `match` arms have incompatible types
+LL | let _ = match Some(42) {
+ | -------------- `match` arms have incompatible types
+LL | Some(x) => "rust-lang.org"
+ | ____________________-
+LL | | .chars()
+LL | | .skip(1)
+LL | | .chain(Some(x as u8 as char))
+LL | | .take(10)
+LL | | .any(char::is_alphanumeric),
+ | |_______________________________________- this is found to be of type `bool`
+LL | None => {}
+ | ^^ expected `bool`, found `()`
error: aborting due to 5 previous errors