diff options
Diffstat (limited to 'crates/hir_ty/src/infer/unify.rs')
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 72 |
1 files changed, 37 insertions, 35 deletions
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 5ea4b7481..a04b935ef 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -49,7 +49,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
49 | 49 | ||
50 | fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { | 50 | fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { |
51 | t.fold_binders( | 51 | t.fold_binders( |
52 | &mut |ty, binders| match ty.interned(&Interner) { | 52 | &mut |ty, binders| match ty.kind(&Interner) { |
53 | &TyKind::InferenceVar(var, kind) => { | 53 | &TyKind::InferenceVar(var, kind) => { |
54 | let inner = var.to_inner(); | 54 | let inner = var.to_inner(); |
55 | if self.var_stack.contains(&inner) { | 55 | if self.var_stack.contains(&inner) { |
@@ -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, |
@@ -186,11 +186,11 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | |||
186 | ); | 186 | ); |
187 | } | 187 | } |
188 | } | 188 | } |
189 | Some( | 189 | Some(Substitution::from_iter( |
190 | Substitution::builder(tys.binders.len(&Interner)) | 190 | &Interner, |
191 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) | 191 | vars.iter(&Interner) |
192 | .build(), | 192 | .map(|v| table.resolve_ty_completely(v.assert_ty_ref(&Interner).clone())), |
193 | ) | 193 | )) |
194 | } | 194 | } |
195 | 195 | ||
196 | #[derive(Clone, Debug)] | 196 | #[derive(Clone, Debug)] |
@@ -284,7 +284,9 @@ impl InferenceTable { | |||
284 | substs2: &Substitution, | 284 | substs2: &Substitution, |
285 | depth: usize, | 285 | depth: usize, |
286 | ) -> bool { | 286 | ) -> bool { |
287 | substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) | 287 | substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| { |
288 | self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth) | ||
289 | }) | ||
288 | } | 290 | } |
289 | 291 | ||
290 | fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { | 292 | fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { |
@@ -299,7 +301,7 @@ impl InferenceTable { | |||
299 | let ty1 = self.resolve_ty_shallow(ty1); | 301 | let ty1 = self.resolve_ty_shallow(ty1); |
300 | let ty2 = self.resolve_ty_shallow(ty2); | 302 | let ty2 = self.resolve_ty_shallow(ty2); |
301 | if ty1.equals_ctor(&ty2) { | 303 | if ty1.equals_ctor(&ty2) { |
302 | match (ty1.interned(&Interner), ty2.interned(&Interner)) { | 304 | match (ty1.kind(&Interner), ty2.kind(&Interner)) { |
303 | (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2)) | 305 | (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2)) |
304 | | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2)) | 306 | | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2)) |
305 | | ( | 307 | | ( |
@@ -324,7 +326,7 @@ impl InferenceTable { | |||
324 | } | 326 | } |
325 | 327 | ||
326 | pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { | 328 | pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { |
327 | match (ty1.interned(&Interner), ty2.interned(&Interner)) { | 329 | match (ty1.kind(&Interner), ty2.kind(&Interner)) { |
328 | (TyKind::Unknown, _) | (_, TyKind::Unknown) => true, | 330 | (TyKind::Unknown, _) | (_, TyKind::Unknown) => true, |
329 | 331 | ||
330 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, | 332 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, |
@@ -453,7 +455,7 @@ impl InferenceTable { | |||
453 | if i > 0 { | 455 | if i > 0 { |
454 | cov_mark::hit!(type_var_resolves_to_int_var); | 456 | cov_mark::hit!(type_var_resolves_to_int_var); |
455 | } | 457 | } |
456 | match ty.interned(&Interner) { | 458 | match ty.kind(&Interner) { |
457 | TyKind::InferenceVar(tv, _) => { | 459 | TyKind::InferenceVar(tv, _) => { |
458 | let inner = tv.to_inner(); | 460 | let inner = tv.to_inner(); |
459 | match self.var_unification_table.inlined_probe_value(inner).known() { | 461 | match self.var_unification_table.inlined_probe_value(inner).known() { |
@@ -476,7 +478,7 @@ impl InferenceTable { | |||
476 | /// be resolved as far as possible, i.e. contain no type variables with | 478 | /// be resolved as far as possible, i.e. contain no type variables with |
477 | /// known type. | 479 | /// known type. |
478 | fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | 480 | fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
479 | ty.fold(&mut |ty| match ty.interned(&Interner) { | 481 | ty.fold(&mut |ty| match ty.kind(&Interner) { |
480 | &TyKind::InferenceVar(tv, kind) => { | 482 | &TyKind::InferenceVar(tv, kind) => { |
481 | let inner = tv.to_inner(); | 483 | let inner = tv.to_inner(); |
482 | if tv_stack.contains(&inner) { | 484 | if tv_stack.contains(&inner) { |
@@ -503,7 +505,7 @@ impl InferenceTable { | |||
503 | /// Resolves the type completely; type variables without known type are | 505 | /// Resolves the type completely; type variables without known type are |
504 | /// replaced by TyKind::Unknown. | 506 | /// replaced by TyKind::Unknown. |
505 | fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | 507 | fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
506 | ty.fold(&mut |ty| match ty.interned(&Interner) { | 508 | ty.fold(&mut |ty| match ty.kind(&Interner) { |
507 | &TyKind::InferenceVar(tv, kind) => { | 509 | &TyKind::InferenceVar(tv, kind) => { |
508 | let inner = tv.to_inner(); | 510 | let inner = tv.to_inner(); |
509 | if tv_stack.contains(&inner) { | 511 | if tv_stack.contains(&inner) { |