Skip to content

Commit c763f83

Browse files
Only point out non-diverging arms for match suggestions
1 parent fa9f77f commit c763f83

File tree

7 files changed

+69
-18
lines changed

7 files changed

+69
-18
lines changed

compiler/rustc_hir_typeck/src/_match.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7979
CoerceMany::with_coercion_sites(coerce_first, arms)
8080
};
8181

82-
let mut other_arms = vec![]; // Used only for diagnostics.
82+
let mut prior_non_diverging_arms = vec![]; // Used only for diagnostics.
8383
let mut prior_arm = None;
8484
for arm in arms {
8585
if let Some(e) = &arm.guard {
@@ -120,7 +120,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
120120
scrut_span: scrut.span,
121121
scrut_hir_id: scrut.hir_id,
122122
source: match_src,
123-
prior_arms: other_arms.clone(),
123+
prior_non_diverging_arms: prior_non_diverging_arms.clone(),
124124
opt_suggest_box_span,
125125
})),
126126
),
@@ -142,16 +142,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
142142
false,
143143
);
144144

145-
other_arms.push(arm_span);
146-
if other_arms.len() > 5 {
147-
other_arms.remove(0);
148-
}
149-
150145
if !arm_ty.is_never() {
151146
// When a match arm has type `!`, then it doesn't influence the expected type for
152147
// the following arm. If all of the prior arms are `!`, then the influence comes
153148
// from elsewhere and we shouldn't point to any previous arm.
154149
prior_arm = Some((arm_block_id, arm_ty, arm_span));
150+
151+
prior_non_diverging_arms.push(arm_span);
152+
if prior_non_diverging_arms.len() > 5 {
153+
prior_non_diverging_arms.remove(0);
154+
}
155155
}
156156
}
157157

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

+8-5
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
777777
prior_arm_span,
778778
prior_arm_ty,
779779
source,
780-
ref prior_arms,
780+
ref prior_non_diverging_arms,
781781
opt_suggest_box_span,
782782
scrut_span,
783783
scrut_hir_id,
@@ -817,12 +817,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
817817
});
818818
let source_map = self.tcx.sess.source_map();
819819
let mut any_multiline_arm = source_map.is_multiline(arm_span);
820-
if prior_arms.len() <= 4 {
821-
for sp in prior_arms {
820+
if prior_non_diverging_arms.len() <= 4 {
821+
for sp in prior_non_diverging_arms {
822822
any_multiline_arm |= source_map.is_multiline(*sp);
823823
err.span_label(*sp, format!("this is found to be of type `{t}`"));
824824
}
825-
} else if let Some(sp) = prior_arms.last() {
825+
} else if let Some(sp) = prior_non_diverging_arms.last() {
826826
any_multiline_arm |= source_map.is_multiline(*sp);
827827
err.span_label(
828828
*sp,
@@ -865,7 +865,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
865865
self.suggest_boxing_for_return_impl_trait(
866866
err,
867867
ret_sp,
868-
prior_arms.iter().chain(std::iter::once(&arm_span)).copied(),
868+
prior_non_diverging_arms
869+
.iter()
870+
.chain(std::iter::once(&arm_span))
871+
.copied(),
869872
);
870873
}
871874
}

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

+7-4
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
203203
})
204204
}
205205
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
206-
prior_arms,
206+
prior_non_diverging_arms,
207207
..
208208
}) => {
209-
if let [.., arm_span] = &prior_arms[..] {
209+
if let [.., arm_span] = &prior_non_diverging_arms[..] {
210210
Some(ConsiderAddingAwait::BothFuturesSugg {
211211
first: arm_span.shrink_to_hi(),
212212
second: exp_span.shrink_to_hi(),
@@ -234,11 +234,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
234234
Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
235235
}
236236
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
237-
ref prior_arms,
237+
ref prior_non_diverging_arms,
238238
..
239239
}) => Some({
240240
ConsiderAddingAwait::FutureSuggMultiple {
241-
spans: prior_arms.iter().map(|arm| arm.shrink_to_hi()).collect(),
241+
spans: prior_non_diverging_arms
242+
.iter()
243+
.map(|arm| arm.shrink_to_hi())
244+
.collect(),
242245
}
243246
}),
244247
_ => None,

compiler/rustc_middle/src/traits/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ pub struct MatchExpressionArmCause<'tcx> {
571571
pub scrut_span: Span,
572572
pub scrut_hir_id: hir::HirId,
573573
pub source: hir::MatchSource,
574-
pub prior_arms: Vec<Span>,
574+
pub prior_non_diverging_arms: Vec<Span>,
575575
pub opt_suggest_box_span: Option<Span>,
576576
}
577577

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
fn main() {
2+
let m = 42u32;
3+
4+
let value = 'out: {
5+
match m {
6+
1 => break 'out Some(1u16),
7+
2 => Some(2u16),
8+
3 => break 'out Some(3u16),
9+
4 => break 'out Some(4u16),
10+
5 => break 'out Some(5u16),
11+
_ => {}
12+
//~^ ERROR `match` arms have incompatible types
13+
}
14+
15+
None
16+
};
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0308]: `match` arms have incompatible types
2+
--> $DIR/dont-highlight-diverging-arms.rs:11:18
3+
|
4+
LL | / match m {
5+
LL | | 1 => break 'out Some(1u16),
6+
LL | | 2 => Some(2u16),
7+
| | ---------- this is found to be of type `Option<u16>`
8+
LL | | 3 => break 'out Some(3u16),
9+
... |
10+
LL | | _ => {}
11+
| | ^^ expected `Option<u16>`, found `()`
12+
LL | |
13+
LL | | }
14+
| |_________- `match` arms have incompatible types
15+
|
16+
= note: expected enum `Option<u16>`
17+
found unit type `()`
18+
help: consider using a semicolon here, but this will discard any values in the match arms
19+
|
20+
LL | };
21+
| +
22+
23+
error: aborting due to 1 previous error
24+
25+
For more information about this error, try `rustc --explain E0308`.

tests/ui/match/match-arm-resolving-to-never.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ error[E0308]: `match` arms have incompatible types
33
|
44
LL | / match E::F {
55
LL | | E::A => 1,
6+
| | - this is found to be of type `{integer}`
67
LL | | E::B => 2,
8+
| | - this is found to be of type `{integer}`
79
LL | | E::C => 3,
10+
| | - this is found to be of type `{integer}`
811
LL | | E::D => 4,
12+
| | - this is found to be of type `{integer}`
913
LL | | E::E => unimplemented!(""),
10-
| | ------------------ this and all prior arms are found to be of type `{integer}`
1114
LL | | E::F => "",
1215
| | ^^ expected integer, found `&str`
1316
LL | | };

0 commit comments

Comments
 (0)