1
Fork 0

Add a helper function for a common piece of code

This commit is contained in:
Oli Scherer 2022-05-10 11:03:52 +00:00
parent 05a62c5527
commit 5b5b549580
3 changed files with 32 additions and 68 deletions

View file

@ -427,25 +427,27 @@ pub struct ImplDerivedObligationCause<'tcx> {
pub span: Span, pub span: Span,
} }
impl ObligationCauseCode<'_> { impl<'tcx> ObligationCauseCode<'tcx> {
// Return the base obligation, ignoring derived obligations. // Return the base obligation, ignoring derived obligations.
pub fn peel_derives(&self) -> &Self { pub fn peel_derives(&self) -> &Self {
let mut base_cause = self; let mut base_cause = self;
loop { while let Some((parent_code, _)) = base_cause.parent() {
match base_cause { base_cause = parent_code;
BuiltinDerivedObligation(DerivedObligationCause { parent_code, .. })
| DerivedObligation(DerivedObligationCause { parent_code, .. })
| FunctionArgumentObligation { parent_code, .. } => {
base_cause = &parent_code;
}
ImplDerivedObligation(obligation_cause) => {
base_cause = &*obligation_cause.derived.parent_code;
}
_ => break,
}
} }
base_cause base_cause
} }
pub fn parent(&self) -> Option<(&Self, Option<ty::PolyTraitPredicate<'tcx>>)> {
match self {
FunctionArgumentObligation { parent_code, .. } => Some((parent_code, None)),
BuiltinDerivedObligation(derived)
| DerivedObligation(derived)
| ImplDerivedObligation(box ImplDerivedObligationCause { derived, .. }) => {
Some((&derived.parent_code, Some(derived.parent_trait_pred)))
}
_ => None,
}
}
} }
// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.

View file

@ -2,11 +2,10 @@ pub mod on_unimplemented;
pub mod suggestions; pub mod suggestions;
use super::{ use super::{
DerivedObligationCause, EvaluationResult, FulfillmentContext, FulfillmentError, EvaluationResult, FulfillmentContext, FulfillmentError, FulfillmentErrorCode,
FulfillmentErrorCode, ImplDerivedObligationCause, MismatchedProjectionTypes, Obligation, MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
ObligationCause, ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow,
OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError, PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
TraitNotObjectSafe,
}; };
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
@ -684,32 +683,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let mut code = obligation.cause.code(); let mut code = obligation.cause.code();
let mut trait_pred = trait_predicate; let mut trait_pred = trait_predicate;
let mut peeled = false; let mut peeled = false;
loop { while let Some((parent_code, parent_trait_pred)) = code.parent() {
match &*code { code = parent_code;
ObligationCauseCode::FunctionArgumentObligation { if let Some(parent_trait_pred) = parent_trait_pred {
parent_code, trait_pred = parent_trait_pred;
.. peeled = true;
} => { }
code = &parent_code;
}
ObligationCauseCode::ImplDerivedObligation(
box ImplDerivedObligationCause {
derived,
..
},
)
| ObligationCauseCode::BuiltinDerivedObligation(
derived,
)
| ObligationCauseCode::DerivedObligation(
derived,
) => {
peeled = true;
code = &derived.parent_code;
trait_pred = derived.parent_trait_pred;
}
_ => break,
};
} }
let def_id = trait_pred.def_id(); let def_id = trait_pred.def_id();
// Mention *all* the `impl`s for the *top most* obligation, the // Mention *all* the `impl`s for the *top most* obligation, the

View file

@ -1,6 +1,6 @@
use super::{ use super::{
DerivedObligationCause, EvaluationResult, ImplDerivedObligationCause, Obligation, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
ObligationCause, ObligationCauseCode, PredicateObligation, SelectionContext, SelectionContext,
}; };
use crate::autoderef::Autoderef; use crate::autoderef::Autoderef;
@ -623,28 +623,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let span = obligation.cause.span; let span = obligation.cause.span;
let mut real_trait_pred = trait_pred; let mut real_trait_pred = trait_pred;
let mut code = obligation.cause.code(); let mut code = obligation.cause.code();
loop { while let Some((parent_code, parent_trait_pred)) = code.parent() {
match &code { code = parent_code;
ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => { if let Some(parent_trait_pred) = parent_trait_pred {
code = &parent_code; real_trait_pred = parent_trait_pred;
} }
ObligationCauseCode::ImplDerivedObligation(box ImplDerivedObligationCause {
derived: DerivedObligationCause { parent_code, parent_trait_pred },
..
})
| ObligationCauseCode::BuiltinDerivedObligation(DerivedObligationCause {
parent_code,
parent_trait_pred,
})
| ObligationCauseCode::DerivedObligation(DerivedObligationCause {
parent_code,
parent_trait_pred,
}) => {
code = &parent_code;
real_trait_pred = *parent_trait_pred;
}
_ => break,
};
let Some(real_ty) = real_trait_pred.self_ty().no_bound_vars() else { let Some(real_ty) = real_trait_pred.self_ty().no_bound_vars() else {
continue; continue;
}; };