aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/infer/unify.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/infer/unify.rs')
-rw-r--r--crates/hir_ty/src/infer/unify.rs80
1 files changed, 44 insertions, 36 deletions
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 6e7b0f5a6..b7bc48569 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
164pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { 163pub(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)]
@@ -231,6 +231,7 @@ pub(crate) struct TypeVariableData {
231pub(crate) struct InferenceTable { 231pub(crate) struct InferenceTable {
232 pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>, 232 pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>,
233 pub(super) type_variable_table: TypeVariableTable, 233 pub(super) type_variable_table: TypeVariableTable,
234 pub(super) revision: u32,
234} 235}
235 236
236impl InferenceTable { 237impl InferenceTable {
@@ -238,6 +239,7 @@ impl InferenceTable {
238 InferenceTable { 239 InferenceTable {
239 var_unification_table: InPlaceUnificationTable::new(), 240 var_unification_table: InPlaceUnificationTable::new(),
240 type_variable_table: TypeVariableTable { inner: Vec::new() }, 241 type_variable_table: TypeVariableTable { inner: Vec::new() },
242 revision: 0,
241 } 243 }
242 } 244 }
243 245
@@ -282,7 +284,9 @@ impl InferenceTable {
282 substs2: &Substitution, 284 substs2: &Substitution,
283 depth: usize, 285 depth: usize,
284 ) -> bool { 286 ) -> bool {
285 substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) 287 substs1.iter(&Interner).zip(substs2.iter(&Interner)).all(|(t1, t2)| {
288 self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth)
289 })
286 } 290 }
287 291
288 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 {
@@ -297,7 +301,7 @@ impl InferenceTable {
297 let ty1 = self.resolve_ty_shallow(ty1); 301 let ty1 = self.resolve_ty_shallow(ty1);
298 let ty2 = self.resolve_ty_shallow(ty2); 302 let ty2 = self.resolve_ty_shallow(ty2);
299 if ty1.equals_ctor(&ty2) { 303 if ty1.equals_ctor(&ty2) {
300 match (ty1.interned(&Interner), ty2.interned(&Interner)) { 304 match (ty1.kind(&Interner), ty2.kind(&Interner)) {
301 (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2)) 305 (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2))
302 | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2)) 306 | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2))
303 | ( 307 | (
@@ -322,7 +326,7 @@ impl InferenceTable {
322 } 326 }
323 327
324 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 {
325 match (ty1.interned(&Interner), ty2.interned(&Interner)) { 329 match (ty1.kind(&Interner), ty2.kind(&Interner)) {
326 (TyKind::Unknown, _) | (_, TyKind::Unknown) => true, 330 (TyKind::Unknown, _) | (_, TyKind::Unknown) => true,
327 331
328 (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, 332 (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true,
@@ -360,7 +364,10 @@ impl InferenceTable {
360 == self.type_variable_table.is_diverging(*tv2) => 364 == self.type_variable_table.is_diverging(*tv2) =>
361 { 365 {
362 // both type vars are unknown since we tried to resolve them 366 // both type vars are unknown since we tried to resolve them
363 self.var_unification_table.union(tv1.to_inner(), tv2.to_inner()); 367 if !self.var_unification_table.unioned(tv1.to_inner(), tv2.to_inner()) {
368 self.var_unification_table.union(tv1.to_inner(), tv2.to_inner());
369 self.revision += 1;
370 }
364 true 371 true
365 } 372 }
366 373
@@ -398,6 +405,7 @@ impl InferenceTable {
398 tv.to_inner(), 405 tv.to_inner(),
399 TypeVarValue::Known(other.clone().intern(&Interner)), 406 TypeVarValue::Known(other.clone().intern(&Interner)),
400 ); 407 );
408 self.revision += 1;
401 true 409 true
402 } 410 }
403 411
@@ -447,7 +455,7 @@ impl InferenceTable {
447 if i > 0 { 455 if i > 0 {
448 cov_mark::hit!(type_var_resolves_to_int_var); 456 cov_mark::hit!(type_var_resolves_to_int_var);
449 } 457 }
450 match ty.interned(&Interner) { 458 match ty.kind(&Interner) {
451 TyKind::InferenceVar(tv, _) => { 459 TyKind::InferenceVar(tv, _) => {
452 let inner = tv.to_inner(); 460 let inner = tv.to_inner();
453 match self.var_unification_table.inlined_probe_value(inner).known() { 461 match self.var_unification_table.inlined_probe_value(inner).known() {
@@ -470,7 +478,7 @@ impl InferenceTable {
470 /// 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
471 /// known type. 479 /// known type.
472 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 {
473 ty.fold(&mut |ty| match ty.interned(&Interner) { 481 ty.fold(&mut |ty| match ty.kind(&Interner) {
474 &TyKind::InferenceVar(tv, kind) => { 482 &TyKind::InferenceVar(tv, kind) => {
475 let inner = tv.to_inner(); 483 let inner = tv.to_inner();
476 if tv_stack.contains(&inner) { 484 if tv_stack.contains(&inner) {
@@ -497,7 +505,7 @@ impl InferenceTable {
497 /// Resolves the type completely; type variables without known type are 505 /// Resolves the type completely; type variables without known type are
498 /// replaced by TyKind::Unknown. 506 /// replaced by TyKind::Unknown.
499 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 {
500 ty.fold(&mut |ty| match ty.interned(&Interner) { 508 ty.fold(&mut |ty| match ty.kind(&Interner) {
501 &TyKind::InferenceVar(tv, kind) => { 509 &TyKind::InferenceVar(tv, kind) => {
502 let inner = tv.to_inner(); 510 let inner = tv.to_inner();
503 if tv_stack.contains(&inner) { 511 if tv_stack.contains(&inner) {