Make diverging type variables work again

Chalk doesn't know about the `diverging` flag, so we need to instead
propagate it before fully resolving the variables.
This commit is contained in:
Florian Diebold 2021-05-15 19:28:58 +02:00
parent 32fc944263
commit 212f0477f2
2 changed files with 23 additions and 0 deletions

View File

@ -284,6 +284,9 @@ impl<'a> InferenceContext<'a> {
fn resolve_all(mut self) -> InferenceResult {
// FIXME resolve obligations as well (use Guidance if necessary)
// make sure diverging type variables are marked as such
self.table.propagate_diverging_flag();
let mut result = std::mem::take(&mut self.result);
for ty in result.type_of_expr.values_mut() {
let resolved = self.table.resolve_ty_completely(ty.clone());

View File

@ -179,8 +179,28 @@ impl<'a> InferenceTable<'a> {
}
}
/// Chalk doesn't know about the `diverging` flag, so when it unifies two
/// type variables of which one is diverging, the chosen root might not be
/// diverging and we have no way of marking it as such at that time. This
/// function goes through all type variables and make sure their root is
/// marked as diverging if necessary, so that resolving them gives the right
/// result.
pub(super) fn propagate_diverging_flag(&mut self) {
for i in 0..self.type_variable_table.inner.len() {
if !self.type_variable_table.inner[i].diverging {
continue;
}
let v = InferenceVar::from(i as u32);
let root = self.var_unification_table.inference_var_root(v);
if let Some(data) = self.type_variable_table.inner.get_mut(root.index() as usize) {
data.diverging = true;
}
}
}
fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty {
let var = self.var_unification_table.new_variable(UniverseIndex::ROOT);
// Chalk might have created some type variables for its own purposes that we don't know about...
self.type_variable_table.inner.extend(
(0..1 + var.index() as usize - self.type_variable_table.inner.len())
.map(|_| TypeVariableData { diverging: false }),