1
Fork 0

Stop using the whole match expr span for an arm's obligation span

This commit is contained in:
Michael Goulet 2024-10-27 22:35:17 +00:00
parent 5f5c243ca0
commit 2507e83d7b
5 changed files with 18 additions and 21 deletions

View file

@ -94,14 +94,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(None, arm.body.span) (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, // 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. // but rather that there's a prior obligation that doesn't hold.
None => { None => ObligationCauseCode::BlockTailExpression(arm.body.hir_id, match_src),
(arm_span, ObligationCauseCode::BlockTailExpression(arm.body.hir_id, match_src)) Some((prior_arm_block_id, prior_arm_ty, prior_arm_span)) => {
}
Some((prior_arm_block_id, prior_arm_ty, prior_arm_span)) => (
expr.span,
ObligationCauseCode::MatchExpressionArm(Box::new(MatchExpressionArmCause { ObligationCauseCode::MatchExpressionArm(Box::new(MatchExpressionArmCause {
arm_block_id, arm_block_id,
arm_span, arm_span,
@ -110,13 +107,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
prior_arm_ty, prior_arm_ty,
prior_arm_span, prior_arm_span,
scrut_span: scrut.span, scrut_span: scrut.span,
expr_span: expr.span,
source: match_src, source: match_src,
prior_non_diverging_arms: prior_non_diverging_arms.clone(), prior_non_diverging_arms: prior_non_diverging_arms.clone(),
tail_defines_return_position_impl_trait, 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)`. // 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 // We use it this way to be able to expand on the potential error and detect when a

View file

@ -519,6 +519,8 @@ pub struct MatchExpressionArmCause<'tcx> {
pub prior_arm_span: Span, pub prior_arm_span: Span,
pub scrut_span: Span, pub scrut_span: Span,
pub source: hir::MatchSource, pub source: hir::MatchSource,
// Span of the *whole* match expr
pub expr_span: Span,
pub prior_non_diverging_arms: Vec<Span>, pub prior_non_diverging_arms: Vec<Span>,
// Is the expectation of this match expression an RPIT? // Is the expectation of this match expression an RPIT?
pub tail_defines_return_position_impl_trait: Option<LocalDefId>, pub tail_defines_return_position_impl_trait: Option<LocalDefId>,

View file

@ -412,6 +412,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
source, source,
ref prior_non_diverging_arms, ref prior_non_diverging_arms,
scrut_span, scrut_span,
expr_span,
.. ..
}) => match source { }) => match source {
hir::MatchSource::TryDesugar(scrut_hir_id) => { hir::MatchSource::TryDesugar(scrut_hir_id) => {
@ -460,12 +461,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
format!("this and all prior arms are found to be of type `{t}`"), 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 // Cover just `match` and the scrutinee expression, not
// the entire match body, to reduce diagram noise. // 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 { } else {
cause.span expr_span
}; };
let msg = "`match` arms have incompatible types"; let msg = "`match` arms have incompatible types";
err.span_label(outer, msg); err.span_label(outer, msg);

View file

@ -22,8 +22,8 @@ fn main() {
Some(()) => &S, Some(()) => &S,
None => &R, //~ ERROR E0308 None => &R, //~ ERROR E0308
} }
let t: &dyn Trait = match opt() { //~ ERROR E0038 let t: &dyn Trait = match opt() {
Some(()) => &S, //~ ERROR E0038 Some(()) => &S, //~ ERROR E0038
None => &R, None => &R, //~ ERROR E0038
}; };
} }

View file

@ -31,14 +31,10 @@ LL | trait Trait: Sized {}
= note: required for the cast from `&S` to `&dyn Trait` = note: required for the cast from `&S` to `&dyn Trait`
error[E0038]: the trait `Trait` cannot be made into an object 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 | None => &R,
| _________________________^ | ^^ `Trait` cannot be made into an object
LL | | Some(()) => &S,
LL | | None => &R,
LL | | };
| |_____^ `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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety> 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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/wf-dyn-incompat-trait-obj-match.rs:6:14 --> $DIR/wf-dyn-incompat-trait-obj-match.rs:6:14