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.rs55
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
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,
@@ -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 {