Skip to content

Commit 7ba519e

Browse files
authored
Rollup merge of #78255 - dtolnay:match, r=lcnr
Reduce diagram mess in 'match arms have incompatible types' error I noticed this wild diagram in https://twitter.com/a_hoverbear/status/1318960787105353728 which I think does not benefit from the big outer vertical span. This PR shrinks the outer span to cover just the `match` keyword and scrutinee expression *if* at least one of the highlighted match arms involved in the error is multiline. **Before:** <pre> <b>error[E0308]: `match` arms have incompatible types</b> <b>--&gt;</b> src/topology/builder.rs:141:35 <b>|</b> <b>120 |</b> let transform = match transform { <b>| _________________________-</b> <b>121 | |</b> Transform::Function(t) =&gt; { <b>| _|_______________________________________-</b> <b>122 | | |</b> filter_event_type(input_rx, input_type).compat().flat_map(|v| { <b>123 | | |</b> futures::stream::iter(match v { <b>124 | | |</b> Err(e) =&gt; { <b>... | |</b> <b>139 | | |</b> .compat(); <b>140 | | |</b> } <b>| |_|_____________- this is found to be of type `()`</b> <b>141 | |</b> Transform::Task(t) =&gt; t <b>| _|___________________________________^</b> <b>142 | | |</b> .transform(filter_event_type(input_rx, input_type)) <b>143 | | |</b> .forward(output) <b>144 | | |</b> .map(|_| debug!("Finished")) <b>145 | | |</b> .compat(), <b>| |_|_________________________^ expected `()`, found struct `futures::compat::Compat01As03`</b> <b>146 | |</b> }; <b>| |_________- `match` arms have incompatible types</b> <b>|</b> <b>= note:</b> expected type `<b>()</b>` found struct `<b>futures::compat::Compat01As03&lt;futures::Map&lt;futures::stream::Forward&lt;std::boxed::Box&lt;dyn futures::Stream&lt;Error = (), Item = event::Event&gt; + std::marker::Send&gt;, topology::fanout::Fanout&gt;, [closure@src/topology/builder.rs:144:22: 144:44]&gt;&gt;</b>` </pre> **After:** <pre> <b>error[E0308]: `match` arms have incompatible types</b> <b>--&gt;</b> src/topology/builder.rs:141:35 <b>|</b> <b>120 |</b> let transform = match transform { <b>| --------------- `match` arms have incompatible types</b> <b>121 |</b> Transform::Function(t) =&gt; { <b>| _________________________________________-</b> <b>122 | |</b> filter_event_type(input_rx, input_type).compat().flat_map(|v| { <b>123 | |</b> futures::stream::iter(match v { <b>124 | |</b> Err(e) =&gt; { <b>... |</b> <b>139 | |</b> .compat(); <b>140 | |</b> } <b>| |_______________- this is found to be of type `()`</b> <b>141 |</b> Transform::Task(t) =&gt; t <b>| _____________________________________^</b> <b>142 | |</b> .transform(filter_event_type(input_rx, input_type)) <b>143 | |</b> .forward(output) <b>144 | |</b> .map(|_| debug!("Finished")) <b>145 | |</b> .compat(), <b>| |___________________________^ expected `()`, found struct `futures::compat::Compat01As03`</b> <b>|</b> <b>= note:</b> expected type `<b>()</b>` found struct `<b>futures::compat::Compat01As03&lt;futures::Map&lt;futures::stream::Forward&lt;std::boxed::Box&lt;dyn futures::Stream&lt;Error = (), Item = event::Event&gt; + std::marker::Send&gt;, topology::fanout::Fanout&gt;, [closure@src/topology/builder.rs:144:22: 144:44]&gt;&gt;</b>` </pre> FYI @Hoverbear
2 parents 3f462c2 + b005950 commit 7ba519e

File tree

5 files changed

+53
-15
lines changed

5 files changed

+53
-15
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
619619
scrut_hir_id,
620620
opt_suggest_box_span,
621621
arm_span,
622+
scrut_span,
622623
..
623624
}) => match source {
624625
hir::MatchSource::IfLetDesugar { .. } => {
@@ -664,18 +665,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
664665
Some(ty::error::ExpectedFound { expected, .. }) => expected,
665666
_ => last_ty,
666667
});
667-
let msg = "`match` arms have incompatible types";
668-
err.span_label(cause.span, msg);
668+
let source_map = self.tcx.sess.source_map();
669+
let mut any_multiline_arm = source_map.is_multiline(arm_span);
669670
if prior_arms.len() <= 4 {
670671
for sp in prior_arms {
672+
any_multiline_arm |= source_map.is_multiline(*sp);
671673
err.span_label(*sp, format!("this is found to be of type `{}`", t));
672674
}
673675
} else if let Some(sp) = prior_arms.last() {
676+
any_multiline_arm |= source_map.is_multiline(*sp);
674677
err.span_label(
675678
*sp,
676679
format!("this and all prior arms are found to be of type `{}`", t),
677680
);
678681
}
682+
let outer_error_span = if any_multiline_arm {
683+
// Cover just `match` and the scrutinee expression, not
684+
// the entire match body, to reduce diagram noise.
685+
cause.span.shrink_to_lo().to(scrut_span)
686+
} else {
687+
cause.span
688+
};
689+
let msg = "`match` arms have incompatible types";
690+
err.span_label(outer_error_span, msg);
679691
if let Some(sp) = semi_span {
680692
err.span_suggestion_short(
681693
sp,

compiler/rustc_middle/src/traits/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ static_assert_size!(ObligationCauseCode<'_>, 32);
343343
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
344344
pub struct MatchExpressionArmCause<'tcx> {
345345
pub arm_span: Span,
346+
pub scrut_span: Span,
346347
pub semi_span: Option<Span>,
347348
pub source: hir::MatchSource,
348349
pub prior_arms: Vec<Span>,

compiler/rustc_typeck/src/check/_match.rs

+1
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
201201
expr.span,
202202
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
203203
arm_span,
204+
scrut_span: scrut.span,
204205
semi_span,
205206
source: match_src,
206207
prior_arms: other_arms.clone(),

src/test/ui/match/match-incompat-type-semi.rs

+10
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,14 @@ fn main() {
3939
None => { //~ ERROR incompatible types
4040
},
4141
};
42+
43+
let _ = match Some(42) {
44+
Some(x) => "rust-lang.org"
45+
.chars()
46+
.skip(1)
47+
.chain(Some(x as u8 as char))
48+
.take(10)
49+
.any(char::is_alphanumeric),
50+
None => {} //~ ERROR incompatible types
51+
};
4252
}

src/test/ui/match/match-incompat-type-semi.stderr

+27-13
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,33 @@ LL | | };
5656
error[E0308]: `match` arms have incompatible types
5757
--> $DIR/match-incompat-type-semi.rs:39:17
5858
|
59-
LL | let _ = match Some(42) {
60-
| _____________-
61-
LL | | Some(x) => {
62-
LL | | x
63-
| | - this is found to be of type `{integer}`
64-
LL | | },
65-
LL | | None => {
66-
| |_________________^
67-
LL | || },
68-
| ||_________^ expected integer, found `()`
69-
LL | | };
70-
| |_____- `match` arms have incompatible types
59+
LL | let _ = match Some(42) {
60+
| -------------- `match` arms have incompatible types
61+
LL | Some(x) => {
62+
LL | x
63+
| - this is found to be of type `{integer}`
64+
LL | },
65+
LL | None => {
66+
| _________________^
67+
LL | | },
68+
| |_________^ expected integer, found `()`
69+
70+
error[E0308]: `match` arms have incompatible types
71+
--> $DIR/match-incompat-type-semi.rs:50:17
72+
|
73+
LL | let _ = match Some(42) {
74+
| -------------- `match` arms have incompatible types
75+
LL | Some(x) => "rust-lang.org"
76+
| ____________________-
77+
LL | | .chars()
78+
LL | | .skip(1)
79+
LL | | .chain(Some(x as u8 as char))
80+
LL | | .take(10)
81+
LL | | .any(char::is_alphanumeric),
82+
| |_______________________________________- this is found to be of type `bool`
83+
LL | None => {}
84+
| ^^ expected `bool`, found `()`
7185

72-
error: aborting due to 4 previous errors
86+
error: aborting due to 5 previous errors
7387

7488
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)