From 2507e83d7bb0dd9e7217b10b13afc61763dc1eca Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 27 Oct 2024 22:35:17 +0000 Subject: [PATCH] Stop using the whole match expr span for an arm's obligation span --- compiler/rustc_hir_typeck/src/_match.rs | 16 +++++++--------- compiler/rustc_middle/src/traits/mod.rs | 2 ++ .../src/error_reporting/infer/mod.rs | 7 ++++--- tests/ui/wf/wf-dyn-incompat-trait-obj-match.rs | 4 ++-- .../ui/wf/wf-dyn-incompat-trait-obj-match.stderr | 10 +++------- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index e68caa3e2e3..3372cae7a51 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -94,14 +94,11 @@ pub(crate) fn check_match( (None, arm.body.span) }; - let (span, code) = match prior_arm { + let code = match prior_arm { // The reason for the first arm to fail is not that the match arms diverge, // but rather that there's a prior obligation that doesn't hold. - None => { - (arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id, match_src)) - } - Some((prior_arm_block_id, prior_arm_ty, prior_arm_span)) => ( - expr.span, + None => ObligationCauseCode::BlockTailExpression(arm.body.hir_id, match_src), + Some((prior_arm_block_id, prior_arm_ty, prior_arm_span)) => { ObligationCauseCode::MatchExpressionArm(Box::new(MatchExpressionArmCause { arm_block_id, arm_span, @@ -110,13 +107,14 @@ pub(crate) fn check_match( prior_arm_ty, prior_arm_span, scrut_span: scrut.span, + expr_span: expr.span, source: match_src, prior_non_diverging_arms: prior_non_diverging_arms.clone(), tail_defines_return_position_impl_trait, - })), - ), + })) + } }; - let cause = self.cause(span, code); + let cause = self.cause(arm_span, code); // This is the moral equivalent of `coercion.coerce(self, cause, arm.body, arm_ty)`. // We use it this way to be able to expand on the potential error and detect when a diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 8ee8b4c4823..7237a7014e8 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -519,6 +519,8 @@ pub struct MatchExpressionArmCause<'tcx> { pub prior_arm_span: Span, pub scrut_span: Span, pub source: hir::MatchSource, + // Span of the *whole* match expr + pub expr_span: Span, pub prior_non_diverging_arms: Vec, // Is the expectation of this match expression an RPIT? pub tail_defines_return_position_impl_trait: Option, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index b9a569d25e3..0cbb43b8763 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -412,6 +412,7 @@ fn note_error_origin( source, ref prior_non_diverging_arms, scrut_span, + expr_span, .. }) => match source { hir::MatchSource::TryDesugar(scrut_hir_id) => { @@ -460,12 +461,12 @@ fn note_error_origin( format!("this and all prior arms are found to be of type `{t}`"), ); } - let outer = if any_multiline_arm || !source_map.is_multiline(cause.span) { + let outer = if any_multiline_arm || !source_map.is_multiline(expr_span) { // Cover just `match` and the scrutinee expression, not // the entire match body, to reduce diagram noise. - cause.span.shrink_to_lo().to(scrut_span) + expr_span.shrink_to_lo().to(scrut_span) } else { - cause.span + expr_span }; let msg = "`match` arms have incompatible types"; err.span_label(outer, msg); diff --git a/tests/ui/wf/wf-dyn-incompat-trait-obj-match.rs b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.rs index 07e90538b85..6eba6b7abec 100644 --- a/tests/ui/wf/wf-dyn-incompat-trait-obj-match.rs +++ b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.rs @@ -22,8 +22,8 @@ fn main() { Some(()) => &S, None => &R, //~ ERROR E0308 } - let t: &dyn Trait = match opt() { //~ ERROR E0038 + let t: &dyn Trait = match opt() { Some(()) => &S, //~ ERROR E0038 - None => &R, + None => &R, //~ ERROR E0038 }; } diff --git a/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr index d7366e12256..6cd4ebf8412 100644 --- a/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr +++ b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr @@ -31,14 +31,10 @@ LL | trait Trait: Sized {} = note: required for the cast from `&S` to `&dyn Trait` error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/wf-dyn-incompat-trait-obj-match.rs:25:25 + --> $DIR/wf-dyn-incompat-trait-obj-match.rs:27:17 | -LL | let t: &dyn Trait = match opt() { - | _________________________^ -LL | | Some(()) => &S, -LL | | None => &R, -LL | | }; - | |_____^ `Trait` cannot be made into an object +LL | None => &R, + | ^^ `Trait` cannot be made into an object | note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $DIR/wf-dyn-incompat-trait-obj-match.rs:6:14