Fix bugs in evaluating WellFormed predicates

- List the nestsed obligations in an order that works with the
  single pass used by evaluation
- Propagate recursion depth correctly
This commit is contained in:
Matthew Jasper 2020-07-22 22:43:18 +01:00
parent f52b2d8890
commit bc08b791bc
8 changed files with 117 additions and 42 deletions

View file

@ -343,7 +343,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Err(SelectionError::Overflow)
}
Err(e) => Err(e),
Ok(candidate) => Ok(Some(candidate)),
Ok(candidate) => {
debug!("select: candidate = {:?}", candidate);
Ok(Some(candidate))
}
}
}
@ -413,9 +416,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
predicates: I,
) -> Result<EvaluationResult, OverflowError>
where
I: IntoIterator<Item = PredicateObligation<'tcx>>,
I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
{
let mut result = EvaluatedToOk;
debug!("evaluate_predicates_recursively({:?})", predicates);
for obligation in predicates {
let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
debug!("evaluate_predicate_recursively({:?}) = {:?}", obligation, eval);
@ -436,7 +440,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
debug!(
"evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})",
"evaluate_predicate_recursively(obligation={:?}, previous_stack={:?})",
previous_stack.head(),
obligation
);
@ -479,15 +483,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.infcx,
obligation.param_env,
obligation.cause.body_id,
obligation.recursion_depth + 1,
arg,
obligation.cause.span,
) {
Some(mut obligations) => {
self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
self.evaluate_predicates_recursively(
previous_stack,
obligations.into_iter(),
)
self.evaluate_predicates_recursively(previous_stack, obligations)
}
None => Ok(EvaluatedToAmbig),
},
@ -511,10 +513,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
match project::poly_project_and_unify_type(self, &project_obligation) {
Ok(Ok(Some(mut subobligations))) => {
self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
let result = self.evaluate_predicates_recursively(
previous_stack,
subobligations.into_iter(),
);
let result = self
.evaluate_predicates_recursively(previous_stack, subobligations);
if let Some(key) =
ProjectionCacheKey::from_poly_projection_predicate(self, data)
{
@ -879,10 +879,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let result = self.evaluation_probe(|this| {
let candidate = (*candidate).clone();
match this.confirm_candidate(stack.obligation, candidate) {
Ok(selection) => this.evaluate_predicates_recursively(
stack.list(),
selection.nested_obligations().into_iter(),
),
Ok(selection) => {
debug!("evaluate_candidate: selection = {:?}", selection);
this.evaluate_predicates_recursively(
stack.list(),
selection.nested_obligations().into_iter(),
)
}
Err(..) => Ok(EvaluatedToErr),
}
})?;
@ -1231,9 +1234,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) -> Result<EvaluationResult, OverflowError> {
self.evaluation_probe(|this| {
match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
Ok(obligations) => {
this.evaluate_predicates_recursively(stack.list(), obligations.into_iter())
}
Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations),
Err(()) => Ok(EvaluatedToErr),
}
})