diff options
| author | Michael Goulet <michael@errs.io> | 2024-02-15 14:34:42 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2024-02-15 15:44:46 +0000 |
| commit | c763f833d14d31fbe63e0b26370a23a51b4f11c5 (patch) | |
| tree | 98ebb10b438005f9e8d6c847f74eacdba3b17504 | |
| parent | fa9f77ff35b4b63ed0cef9a9642c8f881b33f14f (diff) | |
| download | rust-c763f833d14d31fbe63e0b26370a23a51b4f11c5.tar.gz rust-c763f833d14d31fbe63e0b26370a23a51b4f11c5.zip | |
Only point out non-diverging arms for match suggestions
| -rw-r--r-- | compiler/rustc_hir_typeck/src/_match.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/error_reporting/mod.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/error_reporting/suggest.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/traits/mod.rs | 2 | ||||
| -rw-r--r-- | tests/ui/match/dont-highlight-diverging-arms.rs | 17 | ||||
| -rw-r--r-- | tests/ui/match/dont-highlight-diverging-arms.stderr | 25 | ||||
| -rw-r--r-- | tests/ui/match/match-arm-resolving-to-never.stderr | 5 |
7 files changed, 69 insertions, 18 deletions
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 0311aa94cd4..21406681422 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -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 { @@ -120,7 +120,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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, })), ), @@ -142,16 +142,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); + } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b953b25d6c4..aa92f91f24f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -777,7 +777,7 @@ 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, @@ -817,12 +817,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, @@ -865,7 +865,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { 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(), ); } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 248e1c0fcc8..c6f6c32fe60 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -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(), @@ -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, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 8e5f026b4c2..683610ba3b6 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -571,7 +571,7 @@ pub struct MatchExpressionArmCause<'tcx> { 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>, } diff --git a/tests/ui/match/dont-highlight-diverging-arms.rs b/tests/ui/match/dont-highlight-diverging-arms.rs new file mode 100644 index 00000000000..dc3b4ca9caa --- /dev/null +++ b/tests/ui/match/dont-highlight-diverging-arms.rs @@ -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 + }; +} \ No newline at end of file diff --git a/tests/ui/match/dont-highlight-diverging-arms.stderr b/tests/ui/match/dont-highlight-diverging-arms.stderr new file mode 100644 index 00000000000..886c1af13fa --- /dev/null +++ b/tests/ui/match/dont-highlight-diverging-arms.stderr @@ -0,0 +1,25 @@ +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 `()` +help: consider using a semicolon here, but this will discard any values in the match arms + | +LL | }; + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/match-arm-resolving-to-never.stderr b/tests/ui/match/match-arm-resolving-to-never.stderr index 6cbdf03d4c2..fd0c8708b8c 100644 --- a/tests/ui/match/match-arm-resolving-to-never.stderr +++ b/tests/ui/match/match-arm-resolving-to-never.stderr @@ -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 | | }; |
