Use MaybeCause::or to allow constraints from overflows if they are combined with ambiguity

This commit is contained in:
Michael Goulet
2025-05-06 18:32:44 +00:00
parent 3ef8e64ce9
commit a910329c67
7 changed files with 130 additions and 24 deletions

View File

@@ -132,12 +132,14 @@ where
(Certainty::Yes, NestedNormalizationGoals(goals))
}
_ => {
let certainty = shallow_certainty.unify_with(goals_certainty);
let certainty = shallow_certainty.and(goals_certainty);
(certainty, NestedNormalizationGoals::empty())
}
};
if let Certainty::Maybe(cause @ MaybeCause::Overflow { .. }) = certainty {
if let Certainty::Maybe(cause @ MaybeCause::Overflow { keep_constraints: false, .. }) =
certainty
{
// If we have overflow, it's probable that we're substituting a type
// into itself infinitely and any partial substitutions in the query
// response are probably not useful anyways, so just return an empty
@@ -193,6 +195,7 @@ where
debug!(?num_non_region_vars, "too many inference variables -> overflow");
return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow {
suggest_increasing_limit: true,
keep_constraints: false,
}));
}
}

View File

@@ -666,7 +666,7 @@ where
Certainty::Yes => {}
Certainty::Maybe(_) => {
self.nested_goals.push((source, with_resolved_vars));
unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
}
}
} else {
@@ -680,7 +680,7 @@ where
Certainty::Yes => {}
Certainty::Maybe(_) => {
self.nested_goals.push((source, goal));
unchanged_certainty = unchanged_certainty.map(|c| c.unify_with(certainty));
unchanged_certainty = unchanged_certainty.map(|c| c.and(certainty));
}
}
}

View File

@@ -253,16 +253,18 @@ where
}
fn bail_with_ambiguity(&mut self, responses: &[CanonicalResponse<I>]) -> CanonicalResponse<I> {
debug_assert!(!responses.is_empty());
if let Certainty::Maybe(maybe_cause) =
responses.iter().fold(Certainty::AMBIGUOUS, |certainty, response| {
certainty.unify_with(response.value.certainty)
})
{
self.make_ambiguous_response_no_constraints(maybe_cause)
} else {
panic!("expected flounder response to be ambiguous")
}
debug_assert!(responses.len() > 1);
let maybe_cause = responses.iter().fold(MaybeCause::Ambiguity, |maybe_cause, response| {
// Pull down the certainty of `Certainty::Yes` to ambiguity when combining
// these responses, b/c we're combining more than one response and this we
// don't know which one applies.
let candidate = match response.value.certainty {
Certainty::Yes => MaybeCause::Ambiguity,
Certainty::Maybe(candidate) => candidate,
};
maybe_cause.or(candidate)
});
self.make_ambiguous_response_no_constraints(maybe_cause)
}
/// If we fail to merge responses we flounder and return overflow or ambiguity.