aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/infer
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/infer')
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs133
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs42
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs5
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs55
4 files changed, 166 insertions, 69 deletions
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 4a98e2deb..731b062c2 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -10,15 +10,15 @@ use hir_def::{
10 resolver::resolver_for_expr, 10 resolver::resolver_for_expr,
11 AdtId, AssocContainerId, FieldId, Lookup, 11 AdtId, AssocContainerId, FieldId, Lookup,
12}; 12};
13use hir_expand::name::Name; 13use hir_expand::name::{name, Name};
14use ra_syntax::ast::RangeOp; 14use ra_syntax::ast::RangeOp;
15 15
16use crate::{ 16use crate::{
17 autoderef, method_resolution, op, 17 autoderef, method_resolution, op,
18 traits::InEnvironment, 18 traits::{FnTrait, InEnvironment},
19 utils::{generics, variant_data, Generics}, 19 utils::{generics, variant_data, Generics},
20 ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, 20 ApplicationTy, Binders, CallableDefId, InferTy, IntTy, Mutability, Obligation, Rawness, Substs,
21 TraitRef, Ty, TypeCtor, Uncertain, 21 TraitRef, Ty, TypeCtor,
22}; 22};
23 23
24use super::{ 24use super::{
@@ -63,6 +63,56 @@ impl<'a> InferenceContext<'a> {
63 self.resolve_ty_as_possible(ty) 63 self.resolve_ty_as_possible(ty)
64 } 64 }
65 65
66 fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
67 let krate = self.resolver.krate()?;
68 let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
69 let output_assoc_type =
70 self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
71 let generic_params = generics(self.db.upcast(), fn_once_trait.into());
72 if generic_params.len() != 2 {
73 return None;
74 }
75
76 let mut param_builder = Substs::builder(num_args);
77 let mut arg_tys = vec![];
78 for _ in 0..num_args {
79 let arg = self.table.new_type_var();
80 param_builder = param_builder.push(arg.clone());
81 arg_tys.push(arg);
82 }
83 let parameters = param_builder.build();
84 let arg_ty = Ty::Apply(ApplicationTy {
85 ctor: TypeCtor::Tuple { cardinality: num_args as u16 },
86 parameters,
87 });
88 let substs =
89 Substs::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
90
91 let trait_env = Arc::clone(&self.trait_env);
92 let implements_fn_trait =
93 Obligation::Trait(TraitRef { trait_: fn_once_trait, substs: substs.clone() });
94 let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
95 value: implements_fn_trait.clone(),
96 environment: trait_env,
97 });
98 if self.db.trait_solve(krate, goal.value).is_some() {
99 self.obligations.push(implements_fn_trait);
100 let output_proj_ty =
101 crate::ProjectionTy { associated_ty: output_assoc_type, parameters: substs };
102 let return_ty = self.normalize_projection_ty(output_proj_ty);
103 Some((arg_tys, return_ty))
104 } else {
105 None
106 }
107 }
108
109 pub fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
110 match ty.callable_sig(self.db) {
111 Some(sig) => Some((sig.params().to_vec(), sig.ret().clone())),
112 None => self.callable_sig_from_fn_trait(ty, num_args),
113 }
114 }
115
66 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 116 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
67 let body = Arc::clone(&self.body); // avoid borrow checker problem 117 let body = Arc::clone(&self.body); // avoid borrow checker problem
68 let ty = match &body[tgt_expr] { 118 let ty = match &body[tgt_expr] {
@@ -90,6 +140,7 @@ impl<'a> InferenceContext<'a> {
90 // FIXME: Breakable block inference 140 // FIXME: Breakable block inference
91 self.infer_block(statements, *tail, expected) 141 self.infer_block(statements, *tail, expected)
92 } 142 }
143 Expr::Unsafe { body } => self.infer_expr(*body, expected),
93 Expr::TryBlock { body } => { 144 Expr::TryBlock { body } => {
94 let _inner = self.infer_expr(*body, expected); 145 let _inner = self.infer_expr(*body, expected);
95 // FIXME should be std::result::Result<{inner}, _> 146 // FIXME should be std::result::Result<{inner}, _>
@@ -169,7 +220,7 @@ impl<'a> InferenceContext<'a> {
169 }; 220 };
170 sig_tys.push(ret_ty.clone()); 221 sig_tys.push(ret_ty.clone());
171 let sig_ty = Ty::apply( 222 let sig_ty = Ty::apply(
172 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 223 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1, is_varargs: false },
173 Substs(sig_tys.clone().into()), 224 Substs(sig_tys.clone().into()),
174 ); 225 );
175 let closure_ty = 226 let closure_ty =
@@ -198,14 +249,23 @@ impl<'a> InferenceContext<'a> {
198 } 249 }
199 Expr::Call { callee, args } => { 250 Expr::Call { callee, args } => {
200 let callee_ty = self.infer_expr(*callee, &Expectation::none()); 251 let callee_ty = self.infer_expr(*callee, &Expectation::none());
201 let (param_tys, ret_ty) = match callee_ty.callable_sig(self.db) { 252 let canonicalized = self.canonicalizer().canonicalize_ty(callee_ty.clone());
202 Some(sig) => (sig.params().to_vec(), sig.ret().clone()), 253 let mut derefs = autoderef(
203 None => { 254 self.db,
204 // Not callable 255 self.resolver.krate(),
205 // FIXME: report an error 256 InEnvironment {
206 (Vec::new(), Ty::Unknown) 257 value: canonicalized.value.clone(),
207 } 258 environment: self.trait_env.clone(),
208 }; 259 },
260 );
261 let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs
262 .find_map(|callee_deref_ty| {
263 self.callable_sig(
264 &canonicalized.decanonicalize_ty(callee_deref_ty.value),
265 args.len(),
266 )
267 })
268 .unwrap_or((Vec::new(), Ty::Unknown));
209 self.register_obligations_for_call(&callee_ty); 269 self.register_obligations_for_call(&callee_ty);
210 self.check_call_arguments(args, &param_tys); 270 self.check_call_arguments(args, &param_tys);
211 self.normalize_associated_types_in(ret_ty) 271 self.normalize_associated_types_in(ret_ty)
@@ -345,8 +405,15 @@ impl<'a> InferenceContext<'a> {
345 .subst(&a_ty.parameters) 405 .subst(&a_ty.parameters)
346 }) 406 })
347 } 407 }
348 // FIXME: 408 TypeCtor::Adt(AdtId::UnionId(u)) => {
349 TypeCtor::Adt(AdtId::UnionId(_)) => None, 409 self.db.union_data(u).variant_data.field(name).map(|local_id| {
410 let field = FieldId { parent: u.into(), local_id };
411 self.write_field_resolution(tgt_expr, field);
412 self.db.field_types(u.into())[field.local_id]
413 .clone()
414 .subst(&a_ty.parameters)
415 })
416 }
350 _ => None, 417 _ => None,
351 }, 418 },
352 _ => None, 419 _ => None,
@@ -426,15 +493,7 @@ impl<'a> InferenceContext<'a> {
426 match &inner_ty { 493 match &inner_ty {
427 // Fast path for builtins 494 // Fast path for builtins
428 Ty::Apply(ApplicationTy { 495 Ty::Apply(ApplicationTy {
429 ctor: 496 ctor: TypeCtor::Int(IntTy { signedness: Signedness::Signed, .. }),
430 TypeCtor::Int(Uncertain::Known(IntTy {
431 signedness: Signedness::Signed,
432 ..
433 })),
434 ..
435 })
436 | Ty::Apply(ApplicationTy {
437 ctor: TypeCtor::Int(Uncertain::Unknown),
438 .. 497 ..
439 }) 498 })
440 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. }) 499 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. })
@@ -577,9 +636,7 @@ impl<'a> InferenceContext<'a> {
577 ); 636 );
578 self.infer_expr( 637 self.infer_expr(
579 *repeat, 638 *repeat,
580 &Expectation::has_type(Ty::simple(TypeCtor::Int(Uncertain::Known( 639 &Expectation::has_type(Ty::simple(TypeCtor::Int(IntTy::usize()))),
581 IntTy::usize(),
582 )))),
583 ); 640 );
584 } 641 }
585 } 642 }
@@ -592,13 +649,19 @@ impl<'a> InferenceContext<'a> {
592 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), Ty::simple(TypeCtor::Str)) 649 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), Ty::simple(TypeCtor::Str))
593 } 650 }
594 Literal::ByteString(..) => { 651 Literal::ByteString(..) => {
595 let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8()))); 652 let byte_type = Ty::simple(TypeCtor::Int(IntTy::u8()));
596 let array_type = Ty::apply_one(TypeCtor::Array, byte_type); 653 let array_type = Ty::apply_one(TypeCtor::Array, byte_type);
597 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), array_type) 654 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), array_type)
598 } 655 }
599 Literal::Char(..) => Ty::simple(TypeCtor::Char), 656 Literal::Char(..) => Ty::simple(TypeCtor::Char),
600 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int((*ty).into())), 657 Literal::Int(_v, ty) => match ty {
601 Literal::Float(_v, ty) => Ty::simple(TypeCtor::Float((*ty).into())), 658 Some(int_ty) => Ty::simple(TypeCtor::Int((*int_ty).into())),
659 None => self.table.new_integer_var(),
660 },
661 Literal::Float(_v, ty) => match ty {
662 Some(float_ty) => Ty::simple(TypeCtor::Float((*float_ty).into())),
663 None => self.table.new_float_var(),
664 },
602 }, 665 },
603 }; 666 };
604 // use a new type variable if we got Ty::Unknown here 667 // use a new type variable if we got Ty::Unknown here
@@ -727,11 +790,7 @@ impl<'a> InferenceContext<'a> {
727 for &check_closures in &[false, true] { 790 for &check_closures in &[false, true] {
728 let param_iter = param_tys.iter().cloned().chain(repeat(Ty::Unknown)); 791 let param_iter = param_tys.iter().cloned().chain(repeat(Ty::Unknown));
729 for (&arg, param_ty) in args.iter().zip(param_iter) { 792 for (&arg, param_ty) in args.iter().zip(param_iter) {
730 let is_closure = match &self.body[arg] { 793 let is_closure = matches!(&self.body[arg], Expr::Lambda { .. });
731 Expr::Lambda { .. } => true,
732 _ => false,
733 };
734
735 if is_closure != check_closures { 794 if is_closure != check_closures {
736 continue; 795 continue;
737 } 796 }
@@ -795,7 +854,7 @@ impl<'a> InferenceContext<'a> {
795 } 854 }
796 // add obligation for trait implementation, if this is a trait method 855 // add obligation for trait implementation, if this is a trait method
797 match def { 856 match def {
798 CallableDef::FunctionId(f) => { 857 CallableDefId::FunctionId(f) => {
799 if let AssocContainerId::TraitId(trait_) = 858 if let AssocContainerId::TraitId(trait_) =
800 f.lookup(self.db.upcast()).container 859 f.lookup(self.db.upcast()).container
801 { 860 {
@@ -806,7 +865,7 @@ impl<'a> InferenceContext<'a> {
806 self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); 865 self.obligations.push(Obligation::Trait(TraitRef { trait_, substs }));
807 } 866 }
808 } 867 }
809 CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => {} 868 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
810 } 869 }
811 } 870 }
812 } 871 }
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index 4006f595d..4dd4f9802 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -4,7 +4,7 @@ use std::iter::repeat;
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use hir_def::{ 6use hir_def::{
7 expr::{BindingAnnotation, Pat, PatId, RecordFieldPat}, 7 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
8 path::Path, 8 path::Path,
9 type_ref::Mutability, 9 type_ref::Mutability,
10 FieldId, 10 FieldId,
@@ -90,18 +90,7 @@ impl<'a> InferenceContext<'a> {
90 ) -> Ty { 90 ) -> Ty {
91 let body = Arc::clone(&self.body); // avoid borrow checker problem 91 let body = Arc::clone(&self.body); // avoid borrow checker problem
92 92
93 let is_non_ref_pat = match &body[pat] { 93 if is_non_ref_pat(&body, pat) {
94 Pat::Tuple { .. }
95 | Pat::Or(..)
96 | Pat::TupleStruct { .. }
97 | Pat::Record { .. }
98 | Pat::Range { .. }
99 | Pat::Slice { .. } => true,
100 // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented.
101 Pat::Path(..) | Pat::Lit(..) => true,
102 Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false,
103 };
104 if is_non_ref_pat {
105 while let Some((inner, mutability)) = expected.as_reference() { 94 while let Some((inner, mutability)) = expected.as_reference() {
106 expected = inner; 95 expected = inner;
107 default_bm = match default_bm { 96 default_bm = match default_bm {
@@ -195,7 +184,7 @@ impl<'a> InferenceContext<'a> {
195 self.write_pat_ty(pat, bound_ty); 184 self.write_pat_ty(pat, bound_ty);
196 return inner_ty; 185 return inner_ty;
197 } 186 }
198 Pat::Slice { prefix, slice: _slice, suffix } => { 187 Pat::Slice { prefix, slice, suffix } => {
199 let (container_ty, elem_ty) = match &expected { 188 let (container_ty, elem_ty) = match &expected {
200 ty_app!(TypeCtor::Array, st) => (TypeCtor::Array, st.as_single().clone()), 189 ty_app!(TypeCtor::Array, st) => (TypeCtor::Array, st.as_single().clone()),
201 ty_app!(TypeCtor::Slice, st) => (TypeCtor::Slice, st.as_single().clone()), 190 ty_app!(TypeCtor::Slice, st) => (TypeCtor::Slice, st.as_single().clone()),
@@ -206,7 +195,12 @@ impl<'a> InferenceContext<'a> {
206 self.infer_pat(*pat_id, &elem_ty, default_bm); 195 self.infer_pat(*pat_id, &elem_ty, default_bm);
207 } 196 }
208 197
209 Ty::apply_one(container_ty, elem_ty) 198 let pat_ty = Ty::apply_one(container_ty, elem_ty);
199 if let Some(slice_pat_id) = slice {
200 self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
201 }
202
203 pat_ty
210 } 204 }
211 Pat::Wild => expected.clone(), 205 Pat::Wild => expected.clone(),
212 Pat::Range { start, end } => { 206 Pat::Range { start, end } => {
@@ -227,3 +221,21 @@ impl<'a> InferenceContext<'a> {
227 ty 221 ty
228 } 222 }
229} 223}
224
225fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool {
226 match &body[pat] {
227 Pat::Tuple { .. }
228 | Pat::TupleStruct { .. }
229 | Pat::Record { .. }
230 | Pat::Range { .. }
231 | Pat::Slice { .. } => true,
232 Pat::Or(pats) => pats.iter().all(|p| is_non_ref_pat(body, *p)),
233 // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented.
234 Pat::Path(..) => true,
235 Pat::Lit(expr) => match body[*expr] {
236 Expr::Literal(Literal::String(..)) => false,
237 _ => true,
238 },
239 Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Missing => false,
240 }
241}
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index 1c2e56fb0..80d7ed10e 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -81,7 +81,7 @@ impl<'a> InferenceContext<'a> {
81 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 81 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
82 let substs = Substs::type_params_for_generics(&generics); 82 let substs = Substs::type_params_for_generics(&generics);
83 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 83 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
84 if let Some((AdtId::StructId(struct_id), _)) = ty.as_adt() { 84 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
85 let ty = self.db.value_ty(struct_id.into()).subst(&substs); 85 let ty = self.db.value_ty(struct_id.into()).subst(&substs);
86 return Some(ty); 86 return Some(ty);
87 } else { 87 } else {
@@ -95,7 +95,7 @@ impl<'a> InferenceContext<'a> {
95 // self_subst is just for the parent 95 // self_subst is just for the parent
96 let parent_substs = self_subst.unwrap_or_else(Substs::empty); 96 let parent_substs = self_subst.unwrap_or_else(Substs::empty);
97 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); 97 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
98 let substs = Ty::substs_from_path(&ctx, path, typable); 98 let substs = Ty::substs_from_path(&ctx, path, typable, true);
99 let full_substs = Substs::builder(substs.len()) 99 let full_substs = Substs::builder(substs.len())
100 .use_parent_substs(&parent_substs) 100 .use_parent_substs(&parent_substs)
101 .fill(substs.0[parent_substs.len()..].iter().cloned()) 101 .fill(substs.0[parent_substs.len()..].iter().cloned())
@@ -141,6 +141,7 @@ impl<'a> InferenceContext<'a> {
141 def, 141 def,
142 resolved_segment, 142 resolved_segment,
143 remaining_segments_for_ty, 143 remaining_segments_for_ty,
144 true,
144 ); 145 );
145 if let Ty::Unknown = ty { 146 if let Ty::Unknown = ty {
146 return None; 147 return None;
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index 269495ca0..2e895d911 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -9,7 +9,7 @@ use test_utils::mark;
9use super::{InferenceContext, Obligation}; 9use super::{InferenceContext, Obligation};
10use crate::{ 10use crate::{
11 BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Substs, Ty, 11 BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Substs, Ty,
12 TypeCtor, TypeWalk, 12 TyKind, TypeCtor, TypeWalk,
13}; 13};
14 14
15impl<'a> InferenceContext<'a> { 15impl<'a> InferenceContext<'a> {
@@ -86,10 +86,20 @@ where
86 } 86 }
87 87
88 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { 88 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> {
89 Canonicalized { 89 let kinds = self
90 value: Canonical { value: result, num_vars: self.free_vars.len() }, 90 .free_vars
91 free_vars: self.free_vars, 91 .iter()
92 } 92 .map(|v| match v {
93 // mapping MaybeNeverTypeVar to the same kind as general ones
94 // should be fine, because as opposed to int or float type vars,
95 // they don't restrict what kind of type can go into them, they
96 // just affect fallback.
97 InferTy::TypeVar(_) | InferTy::MaybeNeverTypeVar(_) => TyKind::General,
98 InferTy::IntVar(_) => TyKind::Integer,
99 InferTy::FloatVar(_) => TyKind::Float,
100 })
101 .collect();
102 Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars }
93 } 103 }
94 104
95 pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { 105 pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> {
@@ -131,26 +141,41 @@ impl<T> Canonicalized<T> {
131 ty 141 ty
132 } 142 }
133 143
134 pub fn apply_solution(&self, ctx: &mut InferenceContext<'_>, solution: Canonical<Vec<Ty>>) { 144 pub fn apply_solution(&self, ctx: &mut InferenceContext<'_>, solution: Canonical<Substs>) {
135 // the solution may contain new variables, which we need to convert to new inference vars 145 // the solution may contain new variables, which we need to convert to new inference vars
136 let new_vars = Substs((0..solution.num_vars).map(|_| ctx.table.new_type_var()).collect()); 146 let new_vars = Substs(
147 solution
148 .kinds
149 .iter()
150 .map(|k| match k {
151 TyKind::General => ctx.table.new_type_var(),
152 TyKind::Integer => ctx.table.new_integer_var(),
153 TyKind::Float => ctx.table.new_float_var(),
154 })
155 .collect(),
156 );
137 for (i, ty) in solution.value.into_iter().enumerate() { 157 for (i, ty) in solution.value.into_iter().enumerate() {
138 let var = self.free_vars[i]; 158 let var = self.free_vars[i];
139 // eagerly replace projections in the type; we may be getting types 159 // eagerly replace projections in the type; we may be getting types
140 // e.g. from where clauses where this hasn't happened yet 160 // e.g. from where clauses where this hasn't happened yet
141 let ty = ctx.normalize_associated_types_in(ty.subst_bound_vars(&new_vars)); 161 let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars));
142 ctx.table.unify(&Ty::Infer(var), &ty); 162 ctx.table.unify(&Ty::Infer(var), &ty);
143 } 163 }
144 } 164 }
145} 165}
146 166
147pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> { 167pub fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substs> {
148 let mut table = InferenceTable::new(); 168 let mut table = InferenceTable::new();
149 let num_vars = ty1.num_vars.max(ty2.num_vars); 169 let vars = Substs(
150 let vars = 170 tys.kinds
151 Substs::builder(num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build(); 171 .iter()
152 let ty1_with_vars = ty1.value.clone().subst_bound_vars(&vars); 172 // we always use type vars here because we want everything to
153 let ty2_with_vars = ty2.value.clone().subst_bound_vars(&vars); 173 // fallback to Unknown in the end (kind of hacky, as below)
174 .map(|_| table.new_type_var())
175 .collect(),
176 );
177 let ty1_with_vars = tys.value.0.clone().subst_bound_vars(&vars);
178 let ty2_with_vars = tys.value.1.clone().subst_bound_vars(&vars);
154 if !table.unify(&ty1_with_vars, &ty2_with_vars) { 179 if !table.unify(&ty1_with_vars, &ty2_with_vars) {
155 return None; 180 return None;
156 } 181 }
@@ -162,7 +187,7 @@ pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> {
162 } 187 }
163 } 188 }
164 Some( 189 Some(
165 Substs::builder(ty1.num_vars) 190 Substs::builder(tys.kinds.len())
166 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) 191 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
167 .build(), 192 .build(),
168 ) 193 )