Skip to content

Commit 77eaa80

Browse files
authoredFeb 15, 2024
Rollup merge of #121146 - compiler-errors:ignore-diverging-arms, r=estebank
Only point out non-diverging arms for match suggestions Fixes #121144 There is no reason to point at diverging arms, which will always coerce to whatever is the match block's evaluated type. This also removes the suggestion from #106601, since as I pointed out in #72634 (comment) the added suggestion is not firing in the right cases, but instead only when one of the match arms already *actually* evaluates to `()`. r? estebank
2 parents d6e2fc5 + 6018e21 commit 77eaa80

File tree

9 files changed

+69
-48
lines changed

9 files changed

+69
-48
lines changed
 

‎compiler/rustc_hir_typeck/src/_match.rs

+7-8
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 {
@@ -118,9 +118,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
118118
prior_arm_ty,
119119
prior_arm_span,
120120
scrut_span: scrut.span,
121-
scrut_hir_id: scrut.hir_id,
122121
source: match_src,
123-
prior_arms: other_arms.clone(),
122+
prior_non_diverging_arms: prior_non_diverging_arms.clone(),
124123
opt_suggest_box_span,
125124
})),
126125
),
@@ -142,16 +141,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
142141
false,
143142
);
144143

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

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

+8-18
Original file line numberDiff line numberDiff line change
@@ -777,10 +777,9 @@ 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,
783-
scrut_hir_id,
784783
..
785784
}) => match source {
786785
hir::MatchSource::TryDesugar(scrut_hir_id) => {
@@ -817,12 +816,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
817816
});
818817
let source_map = self.tcx.sess.source_map();
819818
let mut any_multiline_arm = source_map.is_multiline(arm_span);
820-
if prior_arms.len() <= 4 {
821-
for sp in prior_arms {
819+
if prior_non_diverging_arms.len() <= 4 {
820+
for sp in prior_non_diverging_arms {
822821
any_multiline_arm |= source_map.is_multiline(*sp);
823822
err.span_label(*sp, format!("this is found to be of type `{t}`"));
824823
}
825-
} else if let Some(sp) = prior_arms.last() {
824+
} else if let Some(sp) = prior_non_diverging_arms.last() {
826825
any_multiline_arm |= source_map.is_multiline(*sp);
827826
err.span_label(
828827
*sp,
@@ -848,24 +847,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
848847
) {
849848
err.subdiagnostic(subdiag);
850849
}
851-
if let hir::Node::Expr(m) = self.tcx.parent_hir_node(scrut_hir_id)
852-
&& let hir::Node::Stmt(stmt) = self.tcx.parent_hir_node(m.hir_id)
853-
&& let hir::StmtKind::Expr(_) = stmt.kind
854-
{
855-
err.span_suggestion_verbose(
856-
stmt.span.shrink_to_hi(),
857-
"consider using a semicolon here, but this will discard any values \
858-
in the match arms",
859-
";",
860-
Applicability::MaybeIncorrect,
861-
);
862-
}
863850
if let Some(ret_sp) = opt_suggest_box_span {
864851
// Get return type span and point to it.
865852
self.suggest_boxing_for_return_impl_trait(
866853
err,
867854
ret_sp,
868-
prior_arms.iter().chain(std::iter::once(&arm_span)).copied(),
855+
prior_non_diverging_arms
856+
.iter()
857+
.chain(std::iter::once(&arm_span))
858+
.copied(),
869859
);
870860
}
871861
}

‎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-2
Original file line numberDiff line numberDiff line change
@@ -569,9 +569,8 @@ pub struct MatchExpressionArmCause<'tcx> {
569569
pub prior_arm_ty: Ty<'tcx>,
570570
pub prior_arm_span: Span,
571571
pub scrut_span: Span,
572-
pub scrut_hir_id: hir::HirId,
573572
pub source: hir::MatchSource,
574-
pub prior_arms: Vec<Span>,
573+
pub prior_non_diverging_arms: Vec<Span>,
575574
pub opt_suggest_box_span: Option<Span>,
576575
}
577576

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,21 @@
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+
19+
error: aborting due to 1 previous error
20+
21+
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 | | };

‎tests/ui/suggestions/issue-81839.stderr

+4-11
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,15 @@ error[E0308]: `match` arms have incompatible types
44
LL | / match num {
55
LL | | 1 => {
66
LL | | cx.answer_str("hi");
7-
| | -------------------- this is found to be of type `()`
7+
| | --------------------
8+
| | | |
9+
| | | help: consider removing this semicolon
10+
| | this is found to be of type `()`
811
LL | | }
912
LL | | _ => cx.answer_str("hi"),
1013
| | ^^^^^^^^^^^^^^^^^^^ expected `()`, found future
1114
LL | | }
1215
| |_____- `match` arms have incompatible types
13-
|
14-
help: consider removing this semicolon
15-
|
16-
LL - cx.answer_str("hi");
17-
LL + cx.answer_str("hi")
18-
|
19-
help: consider using a semicolon here, but this will discard any values in the match arms
20-
|
21-
LL | };
22-
| +
2316

2417
error: aborting due to 1 previous error
2518

‎tests/ui/wf/wf-unsafe-trait-obj-match.stderr

-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ LL | | }
1111
|
1212
= note: expected reference `&S`
1313
found reference `&R`
14-
help: consider using a semicolon here, but this will discard any values in the match arms
15-
|
16-
LL | };
17-
| +
1814

1915
error[E0038]: the trait `Trait` cannot be made into an object
2016
--> $DIR/wf-unsafe-trait-obj-match.rs:26:21

0 commit comments

Comments
 (0)
Please sign in to comment.