Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/next_solver/infer/errors.rs80
-rw-r--r--crates/hir-ty/src/solver_errors.rs5
2 files changed, 27 insertions, 58 deletions
diff --git a/crates/hir-ty/src/next_solver/infer/errors.rs b/crates/hir-ty/src/next_solver/infer/errors.rs
index c5eccdafd5..c3e9caa1c6 100644
--- a/crates/hir-ty/src/next_solver/infer/errors.rs
+++ b/crates/hir-ty/src/next_solver/infer/errors.rs
@@ -32,19 +32,10 @@ use crate::{
pub struct FulfillmentError<'db> {
pub obligation: PredicateObligation<'db>,
pub code: FulfillmentErrorCode<'db>,
- pub trait_obligation_chain: Vec<Predicate<'db>>,
+ pub parent_trait_obligations: Vec<Predicate<'db>>,
}
-impl<'db> FulfillmentError<'db> {
- pub fn new(
- obligation: PredicateObligation<'db>,
- code: FulfillmentErrorCode<'db>,
- root_obligation: PredicateObligation<'db>,
- ) -> FulfillmentError<'db> {
- let trait_obligation_chain = trait_obligation_chain(&root_obligation, &obligation);
- FulfillmentError { obligation, code, trait_obligation_chain }
- }
-
+impl FulfillmentError<'_> {
pub fn is_true_error(&self) -> bool {
match self.code {
FulfillmentErrorCode::Select(_)
@@ -128,7 +119,7 @@ fn fulfillment_error_for_no_solution<'db>(
) -> FulfillmentError<'db> {
let interner = infcx.interner;
let db = interner.db;
- let (obligation, trait_obligation_chain) =
+ let (obligation, parent_trait_obligations) =
find_best_leaf_obligation(infcx, &root_obligation, false);
let code = match obligation.predicate.kind().skip_binder() {
@@ -188,7 +179,7 @@ fn fulfillment_error_for_no_solution<'db>(
}
};
- FulfillmentError { obligation, code, trait_obligation_chain }
+ FulfillmentError { obligation, code, parent_trait_obligations }
}
fn fulfillment_error_for_stalled<'db>(
@@ -238,27 +229,25 @@ fn fulfillment_error_for_stalled<'db>(
}
});
- let (obligation, trait_obligation_chain) = if refine_obligation {
+ let (obligation, parent_trait_obligations) = if refine_obligation {
find_best_leaf_obligation(infcx, &root_obligation, true)
} else {
- let obligation = root_obligation.clone();
- let trait_obligation_chain = trait_obligation_chain(&root_obligation, &obligation);
- (obligation, trait_obligation_chain)
+ (root_obligation, Vec::new())
};
- FulfillmentError { obligation, code, trait_obligation_chain }
+ FulfillmentError { obligation, code, parent_trait_obligations }
}
fn fulfillment_error_for_overflow<'db>(
infcx: &InferCtxt<'db>,
root_obligation: PredicateObligation<'db>,
) -> FulfillmentError<'db> {
- let (obligation, trait_obligation_chain) =
+ let (obligation, parent_trait_obligations) =
find_best_leaf_obligation(infcx, &root_obligation, true);
FulfillmentError {
obligation,
code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
- trait_obligation_chain,
+ parent_trait_obligations,
}
}
@@ -274,12 +263,12 @@ fn find_best_leaf_obligation<'db>(
//
// We should probably fix the visitor to not do so instead, as this also
// means the leaf obligation may be incorrect.
- let (obligation, trait_obligation_chain) = infcx
+ let (obligation, parent_trait_obligations) = infcx
.fudge_inference_if_ok(|| {
let mut visitor = BestObligation {
obligation: obligation.clone(),
consider_ambiguities,
- trait_obligation_chain: trait_obligation_chain(&obligation, &obligation),
+ parent_trait_obligations: Vec::new(),
};
infcx
.visit_proof_tree(obligation.as_goal(), &mut visitor)
@@ -287,42 +276,24 @@ fn find_best_leaf_obligation<'db>(
.ok_or(())
// walk around the fact that the cause in `Obligation` is ignored by folders so that
// we can properly fudge the infer vars in cause code.
- .map(|(obligation, trait_obligation_chain)| {
- (obligation.cause, obligation, trait_obligation_chain)
+ .map(|(obligation, parent_trait_obligations)| {
+ (obligation.cause, obligation, parent_trait_obligations)
})
})
- .map(|(cause, obligation, trait_obligation_chain)| {
- (PredicateObligation { cause, ..obligation }, trait_obligation_chain)
+ .map(|(cause, obligation, parent_trait_obligations)| {
+ (PredicateObligation { cause, ..obligation }, parent_trait_obligations)
})
- .unwrap_or_else(|()| {
- let trait_obligation_chain = trait_obligation_chain(&obligation, &obligation);
- (obligation, trait_obligation_chain)
- });
- let trait_obligation_chain =
- deeply_normalize_for_diagnostics(infcx, obligation.param_env, trait_obligation_chain);
+ .unwrap_or((obligation, Vec::new()));
+ let parent_trait_obligations =
+ deeply_normalize_for_diagnostics(infcx, obligation.param_env, parent_trait_obligations);
let obligation = deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation);
- (obligation, trait_obligation_chain)
-}
-
-fn trait_obligation_chain<'db>(
- root_obligation: &PredicateObligation<'db>,
- obligation: &PredicateObligation<'db>,
-) -> Vec<Predicate<'db>> {
- let mut chain = Vec::new();
- if root_obligation.predicate.as_trait_clause().is_none() {
- return chain;
- }
- chain.push(root_obligation.predicate);
- if chain.last() != Some(&obligation.predicate) {
- chain.push(obligation.predicate);
- }
- chain
+ (obligation, parent_trait_obligations)
}
struct BestObligation<'db> {
obligation: PredicateObligation<'db>,
consider_ambiguities: bool,
- trait_obligation_chain: Vec<Predicate<'db>>,
+ parent_trait_obligations: Vec<Predicate<'db>>,
}
impl<'db> BestObligation<'db> {
@@ -331,16 +302,17 @@ impl<'db> BestObligation<'db> {
derived_obligation: PredicateObligation<'db>,
and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'db>>::Result,
) -> <Self as ProofTreeVisitor<'db>>::Result {
- let should_push = derived_obligation.predicate.as_trait_clause().is_some()
- && self.trait_obligation_chain.last() != Some(&derived_obligation.predicate);
+ let parent_predicate = self.obligation.predicate;
+ let should_push = parent_predicate.as_trait_clause().is_some()
+ && self.parent_trait_obligations.last() != Some(&parent_predicate);
if should_push {
- self.trait_obligation_chain.push(derived_obligation.predicate);
+ self.parent_trait_obligations.push(parent_predicate);
}
let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation);
let result = and_then(self);
self.obligation = old_obligation;
if should_push {
- self.trait_obligation_chain.pop();
+ self.parent_trait_obligations.pop();
}
result
}
@@ -348,7 +320,7 @@ impl<'db> BestObligation<'db> {
fn break_with_current_obligation(&mut self) -> <Self as ProofTreeVisitor<'db>>::Result {
ControlFlow::Break((
self.obligation.clone(),
- std::mem::take(&mut self.trait_obligation_chain),
+ std::mem::take(&mut self.parent_trait_obligations),
))
}
diff --git a/crates/hir-ty/src/solver_errors.rs b/crates/hir-ty/src/solver_errors.rs
index 75f1de3288..ab2dca0455 100644
--- a/crates/hir-ty/src/solver_errors.rs
+++ b/crates/hir-ty/src/solver_errors.rs
@@ -79,7 +79,7 @@ fn handle_trait_unimplemented<'db>(
};
let mut parent_trait_predicates = error
- .trait_obligation_chain
+ .parent_trait_obligations
.iter()
.filter_map(|predicate| predicate.as_trait_clause())
.map(|trait_predicate| {
@@ -90,9 +90,6 @@ fn handle_trait_unimplemented<'db>(
}
})
.collect::<Vec<_>>();
- if parent_trait_predicates.last() == Some(&trait_predicate) {
- parent_trait_predicates.pop();
- }
parent_trait_predicates.reverse();
Some(SolverDiagnosticKind::TraitUnimplemented { trait_predicate, parent_trait_predicates })