Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only point out non-diverging arms for match suggestions #121146

Merged
merged 2 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
CoerceMany::with_coercion_sites(coerce_first, arms)
};

let mut other_arms = vec![]; // Used only for diagnostics.
let mut prior_non_diverging_arms = vec![]; // Used only for diagnostics.
let mut prior_arm = None;
for arm in arms {
if let Some(e) = &arm.guard {
Expand Down Expand Up @@ -118,9 +118,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
prior_arm_ty,
prior_arm_span,
scrut_span: scrut.span,
scrut_hir_id: scrut.hir_id,
source: match_src,
prior_arms: other_arms.clone(),
prior_non_diverging_arms: prior_non_diverging_arms.clone(),
opt_suggest_box_span,
})),
),
Expand All @@ -142,16 +141,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
false,
);

other_arms.push(arm_span);
if other_arms.len() > 5 {
other_arms.remove(0);
}

if !arm_ty.is_never() {
// When a match arm has type `!`, then it doesn't influence the expected type for
// the following arm. If all of the prior arms are `!`, then the influence comes
// from elsewhere and we shouldn't point to any previous arm.
prior_arm = Some((arm_block_id, arm_ty, arm_span));

prior_non_diverging_arms.push(arm_span);
if prior_non_diverging_arms.len() > 5 {
prior_non_diverging_arms.remove(0);
}
}
}

Expand Down
26 changes: 8 additions & 18 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,10 +777,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
prior_arm_span,
prior_arm_ty,
source,
ref prior_arms,
ref prior_non_diverging_arms,
opt_suggest_box_span,
scrut_span,
scrut_hir_id,
..
}) => match source {
hir::MatchSource::TryDesugar(scrut_hir_id) => {
Expand Down Expand Up @@ -817,12 +816,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
});
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 {
if prior_non_diverging_arms.len() <= 4 {
for sp in prior_non_diverging_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() {
} else if let Some(sp) = prior_non_diverging_arms.last() {
any_multiline_arm |= source_map.is_multiline(*sp);
err.span_label(
*sp,
Expand All @@ -848,24 +847,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
) {
err.subdiagnostic(subdiag);
}
if let hir::Node::Expr(m) = self.tcx.parent_hir_node(scrut_hir_id)
&& let hir::Node::Stmt(stmt) = self.tcx.parent_hir_node(m.hir_id)
&& let hir::StmtKind::Expr(_) = stmt.kind
{
err.span_suggestion_verbose(
stmt.span.shrink_to_hi(),
"consider using a semicolon here, but this will discard any values \
in the match arms",
";",
Applicability::MaybeIncorrect,
);
}
if let Some(ret_sp) = opt_suggest_box_span {
// Get return type span and point to it.
self.suggest_boxing_for_return_impl_trait(
err,
ret_sp,
prior_arms.iter().chain(std::iter::once(&arm_span)).copied(),
prior_non_diverging_arms
.iter()
.chain(std::iter::once(&arm_span))
.copied(),
);
}
}
Expand Down
11 changes: 7 additions & 4 deletions compiler/rustc_infer/src/infer/error_reporting/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
})
}
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
prior_arms,
prior_non_diverging_arms,
..
}) => {
if let [.., arm_span] = &prior_arms[..] {
if let [.., arm_span] = &prior_non_diverging_arms[..] {
Some(ConsiderAddingAwait::BothFuturesSugg {
first: arm_span.shrink_to_hi(),
second: exp_span.shrink_to_hi(),
Expand Down Expand Up @@ -234,11 +234,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
}
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
ref prior_arms,
ref prior_non_diverging_arms,
..
}) => Some({
ConsiderAddingAwait::FutureSuggMultiple {
spans: prior_arms.iter().map(|arm| arm.shrink_to_hi()).collect(),
spans: prior_non_diverging_arms
.iter()
.map(|arm| arm.shrink_to_hi())
.collect(),
}
}),
_ => None,
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -569,9 +569,8 @@ pub struct MatchExpressionArmCause<'tcx> {
pub prior_arm_ty: Ty<'tcx>,
pub prior_arm_span: Span,
pub scrut_span: Span,
pub scrut_hir_id: hir::HirId,
pub source: hir::MatchSource,
pub prior_arms: Vec<Span>,
pub prior_non_diverging_arms: Vec<Span>,
pub opt_suggest_box_span: Option<Span>,
}

Expand Down
17 changes: 17 additions & 0 deletions tests/ui/match/dont-highlight-diverging-arms.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
fn main() {
let m = 42u32;

let value = 'out: {
match m {
1 => break 'out Some(1u16),
2 => Some(2u16),
3 => break 'out Some(3u16),
4 => break 'out Some(4u16),
5 => break 'out Some(5u16),
_ => {}
//~^ ERROR `match` arms have incompatible types
}

None
};
}
21 changes: 21 additions & 0 deletions tests/ui/match/dont-highlight-diverging-arms.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0308]: `match` arms have incompatible types
--> $DIR/dont-highlight-diverging-arms.rs:11:18
|
LL | / match m {
LL | | 1 => break 'out Some(1u16),
LL | | 2 => Some(2u16),
| | ---------- this is found to be of type `Option<u16>`
LL | | 3 => break 'out Some(3u16),
... |
LL | | _ => {}
| | ^^ expected `Option<u16>`, found `()`
LL | |
LL | | }
| |_________- `match` arms have incompatible types
|
= note: expected enum `Option<u16>`
found unit type `()`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
5 changes: 4 additions & 1 deletion tests/ui/match/match-arm-resolving-to-never.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ error[E0308]: `match` arms have incompatible types
|
LL | / match E::F {
LL | | E::A => 1,
| | - this is found to be of type `{integer}`
LL | | E::B => 2,
| | - this is found to be of type `{integer}`
LL | | E::C => 3,
| | - this is found to be of type `{integer}`
LL | | E::D => 4,
| | - this is found to be of type `{integer}`
LL | | E::E => unimplemented!(""),
| | ------------------ this and all prior arms are found to be of type `{integer}`
LL | | E::F => "",
| | ^^ expected integer, found `&str`
LL | | };
Expand Down
15 changes: 4 additions & 11 deletions tests/ui/suggestions/issue-81839.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,15 @@ error[E0308]: `match` arms have incompatible types
LL | / match num {
LL | | 1 => {
LL | | cx.answer_str("hi");
| | -------------------- this is found to be of type `()`
| | --------------------
| | | |
| | | help: consider removing this semicolon
| | this is found to be of type `()`
LL | | }
LL | | _ => cx.answer_str("hi"),
| | ^^^^^^^^^^^^^^^^^^^ expected `()`, found future
LL | | }
| |_____- `match` arms have incompatible types
|
help: consider removing this semicolon
|
LL - cx.answer_str("hi");
LL + cx.answer_str("hi")
|
help: consider using a semicolon here, but this will discard any values in the match arms
|
LL | };
| +

error: aborting due to 1 previous error

Expand Down
4 changes: 0 additions & 4 deletions tests/ui/wf/wf-unsafe-trait-obj-match.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ LL | | }
|
= note: expected reference `&S`
found reference `&R`
help: consider using a semicolon here, but this will discard any values in the match arms
|
LL | };
| +

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