aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/infer
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/infer')
-rw-r--r--crates/hir_ty/src/infer/coerce.rs6
-rw-r--r--crates/hir_ty/src/infer/expr.rs27
-rw-r--r--crates/hir_ty/src/infer/pat.rs34
-rw-r--r--crates/hir_ty/src/infer/unify.rs66
4 files changed, 89 insertions, 44 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 79bbc5dab..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};
13use hir_expand::name::{name, Name}; 13use hir_expand::name::{name, Name};
14use stdx::always;
14use syntax::ast::RangeOp; 15use syntax::ast::RangeOp;
15 16
16use crate::{ 17use 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| {
@@ -513,10 +514,10 @@ impl<'a> InferenceContext<'a> {
513 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 514 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
514 if let Some(box_) = self.resolve_boxed_box() { 515 if let Some(box_) = self.resolve_boxed_box() {
515 let mut sb = 516 let mut sb =
516 Substitution::builder(generics(self.db.upcast(), box_.into()).len()); 517 Substitution::build_for_generics(&generics(self.db.upcast(), box_.into()));
517 sb = sb.push(inner_ty); 518 sb = sb.push(inner_ty);
518 match self.db.generic_defaults(box_.into()).as_ref() { 519 match self.db.generic_defaults(box_.into()).get(1) {
519 [_, alloc_ty, ..] if !alloc_ty.value.is_unknown() => { 520 Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => {
520 sb = sb.push(alloc_ty.value.clone()); 521 sb = sb.push(alloc_ty.value.clone());
521 } 522 }
522 _ => (), 523 _ => (),
@@ -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/pat.rs b/crates/hir_ty/src/infer/pat.rs
index befa0d69b..474363709 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -13,7 +13,9 @@ use hir_expand::name::Name;
13 13
14use super::{BindingMode, Expectation, InferenceContext}; 14use super::{BindingMode, Expectation, InferenceContext};
15use crate::{ 15use crate::{
16 lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyKind, 16 lower::lower_to_chalk_mutability,
17 utils::{generics, variant_data},
18 Interner, Substitution, Ty, TyKind,
17}; 19};
18 20
19impl<'a> InferenceContext<'a> { 21impl<'a> InferenceContext<'a> {
@@ -38,7 +40,7 @@ impl<'a> InferenceContext<'a> {
38 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 40 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
39 let (pre, post) = match ellipsis { 41 let (pre, post) = match ellipsis {
40 Some(idx) => subpats.split_at(idx), 42 Some(idx) => subpats.split_at(idx),
41 None => (&subpats[..], &[][..]), 43 None => (subpats, &[][..]),
42 }; 44 };
43 let post_idx_offset = field_tys.iter().count() - post.len(); 45 let post_idx_offset = field_tys.iter().count() - post.len();
44 46
@@ -233,13 +235,31 @@ impl<'a> InferenceContext<'a> {
233 Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), 235 Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())),
234 Pat::Box { inner } => match self.resolve_boxed_box() { 236 Pat::Box { inner } => match self.resolve_boxed_box() {
235 Some(box_adt) => { 237 Some(box_adt) => {
236 let inner_expected = match expected.as_adt() { 238 let (inner_ty, alloc_ty) = match expected.as_adt() {
237 Some((adt, substs)) if adt == box_adt => substs.as_single().clone(), 239 Some((adt, subst)) if adt == box_adt => {
238 _ => self.result.standard_types.unknown.clone(), 240 (subst[0].clone(), subst.get(1).cloned())
241 }
242 _ => (self.result.standard_types.unknown.clone(), None),
239 }; 243 };
240 244
241 let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm); 245 let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm);
242 Ty::adt_ty(box_adt, Substitution::single(inner_ty)) 246 let mut sb = Substitution::build_for_generics(&generics(
247 self.db.upcast(),
248 box_adt.into(),
249 ));
250 sb = sb.push(inner_ty);
251 if sb.remaining() == 1 {
252 sb = sb.push(match alloc_ty {
253 Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty,
254 _ => match self.db.generic_defaults(box_adt.into()).get(1) {
255 Some(alloc_ty) if !alloc_ty.value.is_unknown() => {
256 alloc_ty.value.clone()
257 }
258 _ => self.table.new_type_var(),
259 },
260 });
261 }
262 Ty::adt_ty(box_adt, sb.build())
243 } 263 }
244 None => self.err_ty(), 264 None => self.err_ty(),
245 }, 265 },
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
3use std::borrow::Cow; 3use std::borrow::Cow;
4 4
5use chalk_ir::{FloatTy, IntTy, TyVariableKind}; 5use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind};
6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 7
8use super::{DomainGoal, InferenceContext}; 8use super::{DomainGoal, InferenceContext};
9use crate::{ 9use 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
14impl<'a> InferenceContext<'a> { 14impl<'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> {
147pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { 160pub(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 }