diff options
Diffstat (limited to 'crates/hir_ty/src/infer')
-rw-r--r-- | crates/hir_ty/src/infer/coerce.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 21 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 66 |
3 files changed, 59 insertions, 34 deletions
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 07eb96573..9c62932b1 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -142,7 +142,7 @@ impl<'a> InferenceContext<'a> { | |||
142 | .build(); | 142 | .build(); |
143 | let trait_ref = | 143 | let trait_ref = |
144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; | 144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; |
145 | let goal = InEnvironment::new(self.trait_env.clone(), trait_ref.cast(&Interner)); | 145 | let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); |
146 | 146 | ||
147 | let canonicalizer = self.canonicalizer(); | 147 | let canonicalizer = self.canonicalizer(); |
148 | let canonicalized = canonicalizer.canonicalize_obligation(goal); | 148 | let canonicalized = canonicalizer.canonicalize_obligation(goal); |
@@ -170,8 +170,8 @@ impl<'a> InferenceContext<'a> { | |||
170 | self.db, | 170 | self.db, |
171 | self.resolver.krate(), | 171 | self.resolver.krate(), |
172 | InEnvironment { | 172 | InEnvironment { |
173 | value: canonicalized.value.clone(), | 173 | goal: canonicalized.value.clone(), |
174 | environment: self.trait_env.clone(), | 174 | environment: self.trait_env.env.clone(), |
175 | }, | 175 | }, |
176 | ) { | 176 | ) { |
177 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 177 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 24deff707..19249973c 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -11,6 +11,7 @@ use hir_def::{ | |||
11 | AssocContainerId, FieldId, Lookup, | 11 | AssocContainerId, FieldId, Lookup, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{name, Name}; | 13 | use hir_expand::name::{name, Name}; |
14 | use stdx::always; | ||
14 | use syntax::ast::RangeOp; | 15 | use syntax::ast::RangeOp; |
15 | 16 | ||
16 | use crate::{ | 17 | use crate::{ |
@@ -89,12 +90,12 @@ impl<'a> InferenceContext<'a> { | |||
89 | let substs = | 90 | let substs = |
90 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); | 91 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); |
91 | 92 | ||
92 | let trait_env = Arc::clone(&self.trait_env); | 93 | let trait_env = self.trait_env.env.clone(); |
93 | let implements_fn_trait: DomainGoal = | 94 | let implements_fn_trait: DomainGoal = |
94 | TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } | 95 | TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } |
95 | .cast(&Interner); | 96 | .cast(&Interner); |
96 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { | 97 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { |
97 | value: implements_fn_trait.clone(), | 98 | goal: implements_fn_trait.clone(), |
98 | environment: trait_env, | 99 | environment: trait_env, |
99 | }); | 100 | }); |
100 | if self.db.trait_solve(krate, goal.value).is_some() { | 101 | if self.db.trait_solve(krate, goal.value).is_some() { |
@@ -298,8 +299,8 @@ impl<'a> InferenceContext<'a> { | |||
298 | self.db, | 299 | self.db, |
299 | self.resolver.krate(), | 300 | self.resolver.krate(), |
300 | InEnvironment { | 301 | InEnvironment { |
301 | value: canonicalized.value.clone(), | 302 | goal: canonicalized.value.clone(), |
302 | environment: self.trait_env.clone(), | 303 | environment: self.trait_env.env.clone(), |
303 | }, | 304 | }, |
304 | ); | 305 | ); |
305 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs | 306 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs |
@@ -437,8 +438,8 @@ impl<'a> InferenceContext<'a> { | |||
437 | self.db, | 438 | self.db, |
438 | self.resolver.krate(), | 439 | self.resolver.krate(), |
439 | InEnvironment { | 440 | InEnvironment { |
440 | value: canonicalized.value.clone(), | 441 | goal: canonicalized.value.clone(), |
441 | environment: self.trait_env.clone(), | 442 | environment: self.trait_env.env.clone(), |
442 | }, | 443 | }, |
443 | ) | 444 | ) |
444 | .find_map(|derefed_ty| { | 445 | .find_map(|derefed_ty| { |
@@ -537,8 +538,8 @@ impl<'a> InferenceContext<'a> { | |||
537 | self.db, | 538 | self.db, |
538 | krate, | 539 | krate, |
539 | InEnvironment { | 540 | InEnvironment { |
540 | value: &canonicalized.value, | 541 | goal: &canonicalized.value, |
541 | environment: self.trait_env.clone(), | 542 | environment: self.trait_env.env.clone(), |
542 | }, | 543 | }, |
543 | ) { | 544 | ) { |
544 | Some(derefed_ty) => { | 545 | Some(derefed_ty) => { |
@@ -936,7 +937,9 @@ impl<'a> InferenceContext<'a> { | |||
936 | let def: CallableDefId = from_chalk(self.db, *fn_def); | 937 | let def: CallableDefId = from_chalk(self.db, *fn_def); |
937 | let generic_predicates = self.db.generic_predicates(def.into()); | 938 | let generic_predicates = self.db.generic_predicates(def.into()); |
938 | for predicate in generic_predicates.iter() { | 939 | for predicate in generic_predicates.iter() { |
939 | let predicate = predicate.clone().subst(parameters); | 940 | let (predicate, binders) = |
941 | predicate.clone().subst(parameters).into_value_and_skipped_binders(); | ||
942 | always!(binders == 0); // quantified where clauses not yet handled | ||
940 | self.obligations.push(predicate.cast(&Interner)); | 943 | self.obligations.push(predicate.cast(&Interner)); |
941 | } | 944 | } |
942 | // add obligation for trait implementation, if this is a trait method | 945 | // add obligation for trait implementation, if this is a trait method |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 1fc03c8f4..75250a369 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -2,13 +2,13 @@ | |||
2 | 2 | ||
3 | use std::borrow::Cow; | 3 | use std::borrow::Cow; |
4 | 4 | ||
5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind}; | 5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind}; |
6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
7 | 7 | ||
8 | use super::{DomainGoal, InferenceContext}; | 8 | use super::{DomainGoal, InferenceContext}; |
9 | use crate::{ | 9 | use crate::{ |
10 | AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar, | 10 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, |
11 | Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, | 11 | InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | impl<'a> InferenceContext<'a> { | 14 | impl<'a> InferenceContext<'a> { |
@@ -76,8 +76,17 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
76 | } | 76 | } |
77 | 77 | ||
78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { | 78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { |
79 | let kinds = self.free_vars.iter().map(|&(_, k)| k).collect(); | 79 | let kinds = self |
80 | Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } | 80 | .free_vars |
81 | .iter() | ||
82 | .map(|&(_, k)| chalk_ir::WithKind::new(VariableKind::Ty(k), UniverseIndex::ROOT)); | ||
83 | Canonicalized { | ||
84 | value: Canonical { | ||
85 | value: result, | ||
86 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | ||
87 | }, | ||
88 | free_vars: self.free_vars, | ||
89 | } | ||
81 | } | 90 | } |
82 | 91 | ||
83 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { | 92 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { |
@@ -89,15 +98,12 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
89 | mut self, | 98 | mut self, |
90 | obligation: InEnvironment<DomainGoal>, | 99 | obligation: InEnvironment<DomainGoal>, |
91 | ) -> Canonicalized<InEnvironment<DomainGoal>> { | 100 | ) -> Canonicalized<InEnvironment<DomainGoal>> { |
92 | let result = match obligation.value { | 101 | let result = match obligation.goal { |
93 | DomainGoal::Holds(wc) => { | 102 | DomainGoal::Holds(wc) => { |
94 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) | 103 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) |
95 | } | 104 | } |
96 | }; | 105 | }; |
97 | self.into_canonicalized(InEnvironment { | 106 | self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) |
98 | value: result, | ||
99 | environment: obligation.environment, | ||
100 | }) | ||
101 | } | 107 | } |
102 | } | 108 | } |
103 | 109 | ||
@@ -125,12 +131,19 @@ impl<T> Canonicalized<T> { | |||
125 | // 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 |
126 | let new_vars = Substitution( | 132 | let new_vars = Substitution( |
127 | solution | 133 | solution |
128 | .kinds | 134 | .binders |
129 | .iter() | 135 | .iter(&Interner) |
130 | .map(|k| match k { | 136 | .map(|k| match k.kind { |
131 | TyVariableKind::General => ctx.table.new_type_var(), | 137 | VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), |
132 | TyVariableKind::Integer => ctx.table.new_integer_var(), | 138 | VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), |
133 | TyVariableKind::Float => ctx.table.new_float_var(), | 139 | VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), |
140 | // HACK: Chalk can sometimes return new lifetime variables. We | ||
141 | // want to just skip them, but to not mess up the indices of | ||
142 | // other variables, we'll just create a new type variable in | ||
143 | // their place instead. This should not matter (we never see the | ||
144 | // actual *uses* of the lifetime variable). | ||
145 | VariableKind::Lifetime => ctx.table.new_type_var(), | ||
146 | _ => panic!("const variable in solution"), | ||
134 | }) | 147 | }) |
135 | .collect(), | 148 | .collect(), |
136 | ); | 149 | ); |
@@ -147,8 +160,8 @@ impl<T> Canonicalized<T> { | |||
147 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | 160 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { |
148 | let mut table = InferenceTable::new(); | 161 | let mut table = InferenceTable::new(); |
149 | let vars = Substitution( | 162 | let vars = Substitution( |
150 | tys.kinds | 163 | tys.binders |
151 | .iter() | 164 | .iter(&Interner) |
152 | // we always use type vars here because we want everything to | 165 | // we always use type vars here because we want everything to |
153 | // fallback to Unknown in the end (kind of hacky, as below) | 166 | // fallback to Unknown in the end (kind of hacky, as below) |
154 | .map(|_| table.new_type_var()) | 167 | .map(|_| table.new_type_var()) |
@@ -170,7 +183,7 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | |||
170 | } | 183 | } |
171 | } | 184 | } |
172 | Some( | 185 | Some( |
173 | Substitution::builder(tys.kinds.len()) | 186 | Substitution::builder(tys.binders.len(&Interner)) |
174 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) | 187 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) |
175 | .build(), | 188 | .build(), |
176 | ) | 189 | ) |
@@ -310,9 +323,18 @@ impl InferenceTable { | |||
310 | 323 | ||
311 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, | 324 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, |
312 | 325 | ||
313 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) if dyn1.len() == dyn2.len() => { | 326 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) |
314 | for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) { | 327 | if dyn1.bounds.skip_binders().interned().len() |
315 | if !self.unify_preds(pred1, pred2, depth + 1) { | 328 | == dyn2.bounds.skip_binders().interned().len() => |
329 | { | ||
330 | for (pred1, pred2) in dyn1 | ||
331 | .bounds | ||
332 | .skip_binders() | ||
333 | .interned() | ||
334 | .iter() | ||
335 | .zip(dyn2.bounds.skip_binders().interned().iter()) | ||
336 | { | ||
337 | if !self.unify_preds(pred1.skip_binders(), pred2.skip_binders(), depth + 1) { | ||
316 | return false; | 338 | return false; |
317 | } | 339 | } |
318 | } | 340 | } |