diff options
Diffstat (limited to 'crates/hir_ty/src/infer/unify.rs')
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 55 |
1 files changed, 30 insertions, 25 deletions
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 5ea4b7481..0efc62e53 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -129,29 +129,28 @@ impl<T> Canonicalized<T> { | |||
129 | solution: Canonical<Substitution>, | 129 | solution: Canonical<Substitution>, |
130 | ) { | 130 | ) { |
131 | // the solution may contain new variables, which we need to convert to new inference vars | 131 | // the solution may contain new variables, which we need to convert to new inference vars |
132 | let new_vars = Substitution( | 132 | let new_vars = Substitution::from_iter( |
133 | solution | 133 | &Interner, |
134 | .binders | 134 | solution.binders.iter(&Interner).map(|k| match k.kind { |
135 | .iter(&Interner) | 135 | VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), |
136 | .map(|k| match k.kind { | 136 | VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), |
137 | VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), | 137 | VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), |
138 | VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), | 138 | // HACK: Chalk can sometimes return new lifetime variables. We |
139 | VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), | 139 | // want to just skip them, but to not mess up the indices of |
140 | // HACK: Chalk can sometimes return new lifetime variables. We | 140 | // other variables, we'll just create a new type variable in |
141 | // want to just skip them, but to not mess up the indices of | 141 | // their place instead. This should not matter (we never see the |
142 | // other variables, we'll just create a new type variable in | 142 | // actual *uses* of the lifetime variable). |
143 | // their place instead. This should not matter (we never see the | 143 | VariableKind::Lifetime => ctx.table.new_type_var(), |
144 | // actual *uses* of the lifetime variable). | 144 | _ => panic!("const variable in solution"), |
145 | VariableKind::Lifetime => ctx.table.new_type_var(), | 145 | }), |
146 | _ => panic!("const variable in solution"), | ||
147 | }) | ||
148 | .collect(), | ||
149 | ); | 146 | ); |
150 | for (i, ty) in solution.value.into_iter().enumerate() { | 147 | for (i, ty) in solution.value.iter(&Interner).enumerate() { |
151 | let (v, k) = self.free_vars[i]; | 148 | let (v, k) = self.free_vars[i]; |
152 | // eagerly replace projections in the type; we may be getting types | 149 | // eagerly replace projections in the type; we may be getting types |
153 | // e.g. from where clauses where this hasn't happened yet | 150 | // e.g. from where clauses where this hasn't happened yet |
154 | let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); | 151 | let ty = ctx.normalize_associated_types_in( |
152 | ty.assert_ty_ref(&Interner).clone().subst_bound_vars(&new_vars), | ||
153 | ); | ||
155 | ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty); | 154 | ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty); |
156 | } | 155 | } |
157 | } | 156 | } |
@@ -163,13 +162,13 @@ pub fn could_unify(t1: &Ty, t2: &Ty) -> bool { | |||
163 | 162 | ||
164 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | 163 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { |
165 | let mut table = InferenceTable::new(); | 164 | let mut table = InferenceTable::new(); |
166 | let vars = Substitution( | 165 | let vars = Substitution::from_iter( |
166 | &Interner, | ||
167 | tys.binders | 167 | tys.binders |
168 | .iter(&Interner) | 168 | .iter(&Interner) |
169 | // we always use type vars here because we want everything to | 169 | // we always use type vars here because we want everything to |
170 | // fallback to Unknown in the end (kind of hacky, as below) | 170 | // fallback to Unknown in the end (kind of hacky, as below) |
171 | .map(|_| table.new_type_var()) | 171 | .map(|_| table.new_type_var()), |
172 | .collect(), | ||
173 | ); | 172 | ); |
174 | let ty1_with_vars = tys.value.0.clone().subst_bound_vars(&vars); | 173 | let ty1_with_vars = tys.value.0.clone().subst_bound_vars(&vars); |
175 | let ty2_with_vars = tys.value.1.clone().subst_bound_vars(&vars); | 174 | let ty2_with_vars = tys.value.1.clone().subst_bound_vars(&vars); |
@@ -178,7 +177,8 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | |||
178 | } | 177 | } |
179 | // default any type vars that weren't unified back to their original bound vars | 178 | // default any type vars that weren't unified back to their original bound vars |
180 | // (kind of hacky) | 179 | // (kind of hacky) |
181 | for (i, var) in vars.iter().enumerate() { | 180 | for (i, var) in vars.iter(&Interner).enumerate() { |
181 | let var = var.assert_ty_ref(&Interner); | ||
182 | if &*table.resolve_ty_shallow(var) == var { | 182 | if &*table.resolve_ty_shallow(var) == var { |
183 | table.unify( | 183 | table.unify( |
184 | var, | 184 | var, |
@@ -188,7 +188,10 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | |||
188 | } | 188 | } |
189 | Some( | 189 | Some( |
190 | Substitution::builder(tys.binders.len(&Interner)) | 190 | Substitution::builder(tys.binders.len(&Interner)) |
191 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) | 191 | .fill( |
192 | vars.iter(&Interner) | ||
193 | .map(|v| table.resolve_ty_completely(v.assert_ty_ref(&Interner).clone())), | ||
194 | ) | ||
192 | .build(), | 195 | .build(), |
193 | ) | 196 | ) |
194 | } | 197 | } |
@@ -284,7 +287,9 @@ impl InferenceTable { | |||
284 | substs2: &Substitution, | 287 | substs2: &Substitution, |
285 | depth: usize, | 288 | depth: usize, |
286 | ) -> bool { | 289 | ) -> bool { |
287 | substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) | 290 | substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| { |
291 | self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth) | ||
292 | }) | ||
288 | } | 293 | } |
289 | 294 | ||
290 | fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { | 295 | fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { |