aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2021-05-15 18:28:58 +0100
committerFlorian Diebold <[email protected]>2021-05-21 16:48:34 +0100
commit212f0477f29ec27a3981a916de432fc9ef872ff3 (patch)
tree5a8c5c7391a1fda399c909180b969abae2212435 /crates
parent32fc944263ae0b30eba130fbcf28f4eb5578fdb3 (diff)
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.
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_ty/src/infer.rs3
-rw-r--r--crates/hir_ty/src/infer/unify.rs20
2 files changed, 23 insertions, 0 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index f3cccca68..7898740be 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -284,6 +284,9 @@ impl<'a> InferenceContext<'a> {
284 284
285 fn resolve_all(mut self) -> InferenceResult { 285 fn resolve_all(mut self) -> InferenceResult {
286 // FIXME resolve obligations as well (use Guidance if necessary) 286 // FIXME resolve obligations as well (use Guidance if necessary)
287
288 // make sure diverging type variables are marked as such
289 self.table.propagate_diverging_flag();
287 let mut result = std::mem::take(&mut self.result); 290 let mut result = std::mem::take(&mut self.result);
288 for ty in result.type_of_expr.values_mut() { 291 for ty in result.type_of_expr.values_mut() {
289 let resolved = self.table.resolve_ty_completely(ty.clone()); 292 let resolved = self.table.resolve_ty_completely(ty.clone());
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index e7718aa22..56e06b7d0 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -179,8 +179,28 @@ impl<'a> InferenceTable<'a> {
179 } 179 }
180 } 180 }
181 181
182 /// Chalk doesn't know about the `diverging` flag, so when it unifies two
183 /// type variables of which one is diverging, the chosen root might not be
184 /// diverging and we have no way of marking it as such at that time. This
185 /// function goes through all type variables and make sure their root is
186 /// marked as diverging if necessary, so that resolving them gives the right
187 /// result.
188 pub(super) fn propagate_diverging_flag(&mut self) {
189 for i in 0..self.type_variable_table.inner.len() {
190 if !self.type_variable_table.inner[i].diverging {
191 continue;
192 }
193 let v = InferenceVar::from(i as u32);
194 let root = self.var_unification_table.inference_var_root(v);
195 if let Some(data) = self.type_variable_table.inner.get_mut(root.index() as usize) {
196 data.diverging = true;
197 }
198 }
199 }
200
182 fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty { 201 fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty {
183 let var = self.var_unification_table.new_variable(UniverseIndex::ROOT); 202 let var = self.var_unification_table.new_variable(UniverseIndex::ROOT);
203 // Chalk might have created some type variables for its own purposes that we don't know about...
184 self.type_variable_table.inner.extend( 204 self.type_variable_table.inner.extend(
185 (0..1 + var.index() as usize - self.type_variable_table.inner.len()) 205 (0..1 + var.index() as usize - self.type_variable_table.inner.len())
186 .map(|_| TypeVariableData { diverging: false }), 206 .map(|_| TypeVariableData { diverging: false }),