diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_ty/src/infer.rs | 3 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 20 |
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 }), |