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/coerce.rs27
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs247
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs4
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs86
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs276
5 files changed, 454 insertions, 186 deletions
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 719a0f395..83c0c2c3f 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -8,9 +8,9 @@ use hir_def::{lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutabilit
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9use test_utils::tested_by; 9use test_utils::tested_by;
10 10
11use crate::{autoderef, db::HirDatabase, ImplTy, Substs, Ty, TypeCtor, TypeWalk}; 11use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk};
12 12
13use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; 13use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext};
14 14
15impl<'a, D: HirDatabase> InferenceContext<'a, D> { 15impl<'a, D: HirDatabase> InferenceContext<'a, D> {
16 /// Unify two types, but may coerce the first one to the second one 16 /// Unify two types, but may coerce the first one to the second one
@@ -54,10 +54,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
54 impls 54 impls
55 .iter() 55 .iter()
56 .filter_map(|&impl_id| { 56 .filter_map(|&impl_id| {
57 let trait_ref = match db.impl_ty(impl_id) { 57 let trait_ref = db.impl_trait(impl_id)?;
58 ImplTy::TraitRef(it) => it,
59 ImplTy::Inherent(_) => return None,
60 };
61 58
62 // `CoerseUnsized` has one generic parameter for the target type. 59 // `CoerseUnsized` has one generic parameter for the target type.
63 let cur_from_ty = trait_ref.substs.0.get(0)?; 60 let cur_from_ty = trait_ref.substs.0.get(0)?;
@@ -88,8 +85,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
88 match (&from_ty, to_ty) { 85 match (&from_ty, to_ty) {
89 // Never type will make type variable to fallback to Never Type instead of Unknown. 86 // Never type will make type variable to fallback to Never Type instead of Unknown.
90 (ty_app!(TypeCtor::Never), Ty::Infer(InferTy::TypeVar(tv))) => { 87 (ty_app!(TypeCtor::Never), Ty::Infer(InferTy::TypeVar(tv))) => {
91 let var = self.new_maybe_never_type_var(); 88 let var = self.table.new_maybe_never_type_var();
92 self.var_unification_table.union_value(*tv, TypeVarValue::Known(var)); 89 self.table.var_unification_table.union_value(*tv, TypeVarValue::Known(var));
93 return true; 90 return true;
94 } 91 }
95 (ty_app!(TypeCtor::Never), _) => return true, 92 (ty_app!(TypeCtor::Never), _) => return true,
@@ -97,7 +94,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
97 // Trivial cases, this should go after `never` check to 94 // Trivial cases, this should go after `never` check to
98 // avoid infer result type to be never 95 // avoid infer result type to be never
99 _ => { 96 _ => {
100 if self.unify_inner_trivial(&from_ty, &to_ty) { 97 if self.table.unify_inner_trivial(&from_ty, &to_ty) {
101 return true; 98 return true;
102 } 99 }
103 } 100 }
@@ -137,6 +134,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
137 } 134 }
138 } 135 }
139 136
137 (ty_app!(TypeCtor::Closure { .. }, params), ty_app!(TypeCtor::FnPtr { .. })) => {
138 from_ty = params[0].clone();
139 }
140
140 _ => {} 141 _ => {}
141 } 142 }
142 143
@@ -333,9 +334,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
333 // Stop when constructor matches. 334 // Stop when constructor matches.
334 (ty_app!(from_ctor, st1), ty_app!(to_ctor, st2)) if from_ctor == to_ctor => { 335 (ty_app!(from_ctor, st1), ty_app!(to_ctor, st2)) if from_ctor == to_ctor => {
335 // It will not recurse to `coerce`. 336 // It will not recurse to `coerce`.
336 return self.unify_substs(st1, st2, 0); 337 return self.table.unify_substs(st1, st2, 0);
338 }
339 _ => {
340 if self.table.unify_inner_trivial(&derefed_ty, &to_ty) {
341 return true;
342 }
337 } 343 }
338 _ => {}
339 } 344 }
340 } 345 }
341 346
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 2f9ca4bbb..3af05394c 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -6,17 +6,21 @@ use std::sync::Arc;
6use hir_def::{ 6use hir_def::{
7 builtin_type::Signedness, 7 builtin_type::Signedness,
8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
9 generics::GenericParams,
10 path::{GenericArg, GenericArgs}, 9 path::{GenericArg, GenericArgs},
11 resolver::resolver_for_expr, 10 resolver::resolver_for_expr,
12 AdtId, ContainerId, Lookup, StructFieldId, 11 AdtId, AssocContainerId, Lookup, StructFieldId,
13}; 12};
14use hir_expand::name::{self, Name}; 13use hir_expand::name::{name, Name};
14use ra_syntax::ast::RangeOp;
15 15
16use crate::{ 16use crate::{
17 autoderef, db::HirDatabase, method_resolution, op, traits::InEnvironment, utils::variant_data, 17 autoderef,
18 CallableDef, InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, 18 db::HirDatabase,
19 TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, 19 method_resolution, op,
20 traits::InEnvironment,
21 utils::{generics, variant_data, Generics},
22 ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty,
23 TypeCtor, TypeWalk, Uncertain,
20}; 24};
21 25
22use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; 26use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
@@ -31,13 +35,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
31 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }, 35 TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() },
32 ); 36 );
33 } 37 }
34 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 38 let ty = self.resolve_ty_as_possible(ty);
35 ty 39 ty
36 } 40 }
37 41
38 /// Infer type of expression with possibly implicit coerce to the expected type. 42 /// Infer type of expression with possibly implicit coerce to the expected type.
39 /// Return the type after possible coercion. 43 /// Return the type after possible coercion.
40 fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty { 44 pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
41 let ty = self.infer_expr_inner(expr, &expected); 45 let ty = self.infer_expr_inner(expr, &expected);
42 let ty = if !self.coerce(&ty, &expected.ty) { 46 let ty = if !self.coerce(&ty, &expected.ty) {
43 self.result 47 self.result
@@ -52,7 +56,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
52 expected.ty.clone() 56 expected.ty.clone()
53 }; 57 };
54 58
55 self.resolve_ty_as_possible(&mut vec![], ty) 59 self.resolve_ty_as_possible(ty)
56 } 60 }
57 61
58 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 62 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
@@ -91,27 +95,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
91 Expr::For { iterable, body, pat } => { 95 Expr::For { iterable, body, pat } => {
92 let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 96 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
93 97
94 let pat_ty = match self.resolve_into_iter_item() { 98 let pat_ty =
95 Some(into_iter_item_alias) => { 99 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
96 let pat_ty = self.new_type_var();
97 let projection = ProjectionPredicate {
98 ty: pat_ty.clone(),
99 projection_ty: ProjectionTy {
100 associated_ty: into_iter_item_alias,
101 parameters: Substs::single(iterable_ty),
102 },
103 };
104 self.obligations.push(Obligation::Projection(projection));
105 self.resolve_ty_as_possible(&mut vec![], pat_ty)
106 }
107 None => Ty::Unknown,
108 };
109 100
110 self.infer_pat(*pat, &pat_ty, BindingMode::default()); 101 self.infer_pat(*pat, &pat_ty, BindingMode::default());
111 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 102 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
112 Ty::unit() 103 Ty::unit()
113 } 104 }
114 Expr::Lambda { body, args, arg_types } => { 105 Expr::Lambda { body, args, ret_type, arg_types } => {
115 assert_eq!(args.len(), arg_types.len()); 106 assert_eq!(args.len(), arg_types.len());
116 107
117 let mut sig_tys = Vec::new(); 108 let mut sig_tys = Vec::new();
@@ -127,7 +118,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
127 } 118 }
128 119
129 // add return type 120 // add return type
130 let ret_ty = self.new_type_var(); 121 let ret_ty = match ret_type {
122 Some(type_ref) => self.make_ty(type_ref),
123 None => self.table.new_type_var(),
124 };
131 sig_tys.push(ret_ty.clone()); 125 sig_tys.push(ret_ty.clone());
132 let sig_ty = Ty::apply( 126 let sig_ty = Ty::apply(
133 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 127 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
@@ -143,7 +137,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
143 // infer the body. 137 // infer the body.
144 self.coerce(&closure_ty, &expected.ty); 138 self.coerce(&closure_ty, &expected.ty);
145 139
146 self.infer_expr(*body, &Expectation::has_type(ret_ty)); 140 let prev_ret_ty = std::mem::replace(&mut self.return_ty, ret_ty.clone());
141
142 self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
143
144 self.return_ty = prev_ret_ty;
145
147 closure_ty 146 closure_ty
148 } 147 }
149 Expr::Call { callee, args } => { 148 Expr::Call { callee, args } => {
@@ -166,7 +165,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
166 Expr::Match { expr, arms } => { 165 Expr::Match { expr, arms } => {
167 let input_ty = self.infer_expr(*expr, &Expectation::none()); 166 let input_ty = self.infer_expr(*expr, &Expectation::none());
168 167
169 let mut result_ty = self.new_maybe_never_type_var(); 168 let mut result_ty = self.table.new_maybe_never_type_var();
170 169
171 for arm in arms { 170 for arm in arms {
172 for &pat in &arm.pats { 171 for &pat in &arm.pats {
@@ -200,7 +199,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
200 } 199 }
201 Expr::Return { expr } => { 200 Expr::Return { expr } => {
202 if let Some(expr) = expr { 201 if let Some(expr) = expr {
203 self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone())); 202 self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone()));
203 } else {
204 let unit = Ty::unit();
205 self.coerce(&unit, &self.return_ty.clone());
204 } 206 }
205 Ty::simple(TypeCtor::Never) 207 Ty::simple(TypeCtor::Never)
206 } 208 }
@@ -244,7 +246,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
244 ty 246 ty
245 } 247 }
246 Expr::Field { expr, name } => { 248 Expr::Field { expr, name } => {
247 let receiver_ty = self.infer_expr(*expr, &Expectation::none()); 249 let receiver_ty = self.infer_expr_inner(*expr, &Expectation::none());
248 let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); 250 let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty);
249 let ty = autoderef::autoderef( 251 let ty = autoderef::autoderef(
250 self.db, 252 self.db,
@@ -279,45 +281,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
279 self.normalize_associated_types_in(ty) 281 self.normalize_associated_types_in(ty)
280 } 282 }
281 Expr::Await { expr } => { 283 Expr::Await { expr } => {
282 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 284 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
283 let ty = match self.resolve_future_future_output() { 285 let ty =
284 Some(future_future_output_alias) => { 286 self.resolve_associated_type(inner_ty, self.resolve_future_future_output());
285 let ty = self.new_type_var();
286 let projection = ProjectionPredicate {
287 ty: ty.clone(),
288 projection_ty: ProjectionTy {
289 associated_ty: future_future_output_alias,
290 parameters: Substs::single(inner_ty),
291 },
292 };
293 self.obligations.push(Obligation::Projection(projection));
294 self.resolve_ty_as_possible(&mut vec![], ty)
295 }
296 None => Ty::Unknown,
297 };
298 ty 287 ty
299 } 288 }
300 Expr::Try { expr } => { 289 Expr::Try { expr } => {
301 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 290 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
302 let ty = match self.resolve_ops_try_ok() { 291 let ty = self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok());
303 Some(ops_try_ok_alias) => {
304 let ty = self.new_type_var();
305 let projection = ProjectionPredicate {
306 ty: ty.clone(),
307 projection_ty: ProjectionTy {
308 associated_ty: ops_try_ok_alias,
309 parameters: Substs::single(inner_ty),
310 },
311 };
312 self.obligations.push(Obligation::Projection(projection));
313 self.resolve_ty_as_possible(&mut vec![], ty)
314 }
315 None => Ty::Unknown,
316 };
317 ty 292 ty
318 } 293 }
319 Expr::Cast { expr, type_ref } => { 294 Expr::Cast { expr, type_ref } => {
320 let _inner_ty = self.infer_expr(*expr, &Expectation::none()); 295 let _inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
321 let cast_ty = self.make_ty(type_ref); 296 let cast_ty = self.make_ty(type_ref);
322 // FIXME check the cast... 297 // FIXME check the cast...
323 cast_ty 298 cast_ty
@@ -333,12 +308,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
333 } else { 308 } else {
334 Expectation::none() 309 Expectation::none()
335 }; 310 };
336 // FIXME reference coercions etc. 311 let inner_ty = self.infer_expr_inner(*expr, &expectation);
337 let inner_ty = self.infer_expr(*expr, &expectation);
338 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) 312 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty)
339 } 313 }
340 Expr::Box { expr } => { 314 Expr::Box { expr } => {
341 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 315 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
342 if let Some(box_) = self.resolve_boxed_box() { 316 if let Some(box_) = self.resolve_boxed_box() {
343 Ty::apply_one(TypeCtor::Adt(box_), inner_ty) 317 Ty::apply_one(TypeCtor::Adt(box_), inner_ty)
344 } else { 318 } else {
@@ -346,7 +320,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
346 } 320 }
347 } 321 }
348 Expr::UnaryOp { expr, op } => { 322 Expr::UnaryOp { expr, op } => {
349 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 323 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
350 match op { 324 match op {
351 UnaryOp::Deref => match self.resolver.krate() { 325 UnaryOp::Deref => match self.resolver.krate() {
352 Some(krate) => { 326 Some(krate) => {
@@ -369,31 +343,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
369 }, 343 },
370 UnaryOp::Neg => { 344 UnaryOp::Neg => {
371 match &inner_ty { 345 match &inner_ty {
372 Ty::Apply(a_ty) => match a_ty.ctor { 346 // Fast path for builtins
373 TypeCtor::Int(Uncertain::Unknown) 347 Ty::Apply(ApplicationTy {
374 | TypeCtor::Int(Uncertain::Known(IntTy { 348 ctor:
375 signedness: Signedness::Signed, 349 TypeCtor::Int(Uncertain::Known(IntTy {
376 .. 350 signedness: Signedness::Signed,
377 })) 351 ..
378 | TypeCtor::Float(..) => inner_ty, 352 })),
379 _ => Ty::Unknown, 353 ..
380 }, 354 })
381 Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => { 355 | Ty::Apply(ApplicationTy {
382 inner_ty 356 ctor: TypeCtor::Int(Uncertain::Unknown),
383 } 357 ..
384 // FIXME: resolve ops::Neg trait 358 })
385 _ => Ty::Unknown, 359 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. })
360 | Ty::Infer(InferTy::IntVar(..))
361 | Ty::Infer(InferTy::FloatVar(..)) => inner_ty,
362 // Otherwise we resolve via the std::ops::Neg trait
363 _ => self
364 .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
386 } 365 }
387 } 366 }
388 UnaryOp::Not => { 367 UnaryOp::Not => {
389 match &inner_ty { 368 match &inner_ty {
390 Ty::Apply(a_ty) => match a_ty.ctor { 369 // Fast path for builtins
391 TypeCtor::Bool | TypeCtor::Int(_) => inner_ty, 370 Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })
392 _ => Ty::Unknown, 371 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(_), .. })
393 }, 372 | Ty::Infer(InferTy::IntVar(..)) => inner_ty,
394 Ty::Infer(InferTy::IntVar(..)) => inner_ty, 373 // Otherwise we resolve via the std::ops::Not trait
395 // FIXME: resolve ops::Not trait for inner_ty 374 _ => self
396 _ => Ty::Unknown, 375 .resolve_associated_type(inner_ty, self.resolve_ops_not_output()),
397 } 376 }
398 } 377 }
399 } 378 }
@@ -415,21 +394,63 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
415 } 394 }
416 _ => Ty::Unknown, 395 _ => Ty::Unknown,
417 }, 396 },
397 Expr::Range { lhs, rhs, range_type } => {
398 let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none()));
399 let rhs_expect = lhs_ty
400 .as_ref()
401 .map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone()));
402 let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect));
403 match (range_type, lhs_ty, rhs_ty) {
404 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
405 Some(adt) => Ty::simple(TypeCtor::Adt(adt)),
406 None => Ty::Unknown,
407 },
408 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
409 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
410 None => Ty::Unknown,
411 },
412 (RangeOp::Inclusive, None, Some(ty)) => {
413 match self.resolve_range_to_inclusive() {
414 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
415 None => Ty::Unknown,
416 }
417 }
418 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
419 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
420 None => Ty::Unknown,
421 },
422 (RangeOp::Inclusive, Some(_), Some(ty)) => {
423 match self.resolve_range_inclusive() {
424 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
425 None => Ty::Unknown,
426 }
427 }
428 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
429 Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty),
430 None => Ty::Unknown,
431 },
432 (RangeOp::Inclusive, _, None) => Ty::Unknown,
433 }
434 }
418 Expr::Index { base, index } => { 435 Expr::Index { base, index } => {
419 let _base_ty = self.infer_expr(*base, &Expectation::none()); 436 let base_ty = self.infer_expr_inner(*base, &Expectation::none());
420 let _index_ty = self.infer_expr(*index, &Expectation::none()); 437 let index_ty = self.infer_expr(*index, &Expectation::none());
421 // FIXME: use `std::ops::Index::Output` to figure out the real return type 438
422 Ty::Unknown 439 self.resolve_associated_type_with_params(
440 base_ty,
441 self.resolve_ops_index_output(),
442 &[index_ty],
443 )
423 } 444 }
424 Expr::Tuple { exprs } => { 445 Expr::Tuple { exprs } => {
425 let mut tys = match &expected.ty { 446 let mut tys = match &expected.ty {
426 ty_app!(TypeCtor::Tuple { .. }, st) => st 447 ty_app!(TypeCtor::Tuple { .. }, st) => st
427 .iter() 448 .iter()
428 .cloned() 449 .cloned()
429 .chain(repeat_with(|| self.new_type_var())) 450 .chain(repeat_with(|| self.table.new_type_var()))
430 .take(exprs.len()) 451 .take(exprs.len())
431 .collect::<Vec<_>>(), 452 .collect::<Vec<_>>(),
432 _ => (0..exprs.len()).map(|_| self.new_type_var()).collect(), 453 _ => (0..exprs.len()).map(|_| self.table.new_type_var()).collect(),
433 }; 454 };
434 455
435 for (expr, ty) in exprs.iter().zip(tys.iter_mut()) { 456 for (expr, ty) in exprs.iter().zip(tys.iter_mut()) {
@@ -443,7 +464,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
443 ty_app!(TypeCtor::Array, st) | ty_app!(TypeCtor::Slice, st) => { 464 ty_app!(TypeCtor::Array, st) | ty_app!(TypeCtor::Slice, st) => {
444 st.as_single().clone() 465 st.as_single().clone()
445 } 466 }
446 _ => self.new_type_var(), 467 _ => self.table.new_type_var(),
447 }; 468 };
448 469
449 match array { 470 match array {
@@ -485,7 +506,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
485 }; 506 };
486 // use a new type variable if we got Ty::Unknown here 507 // use a new type variable if we got Ty::Unknown here
487 let ty = self.insert_type_vars_shallow(ty); 508 let ty = self.insert_type_vars_shallow(ty);
488 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 509 let ty = self.resolve_ty_as_possible(ty);
489 self.write_expr_ty(tgt_expr, ty.clone()); 510 self.write_expr_ty(tgt_expr, ty.clone());
490 ty 511 ty
491 } 512 }
@@ -514,7 +535,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
514 } 535 }
515 } 536 }
516 537
517 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 538 let ty = self.resolve_ty_as_possible(ty);
518 self.infer_pat(*pat, &ty, BindingMode::default()); 539 self.infer_pat(*pat, &ty, BindingMode::default());
519 } 540 }
520 Statement::Expr(expr) => { 541 Statement::Expr(expr) => {
@@ -558,7 +579,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
558 Some((ty, func)) => { 579 Some((ty, func)) => {
559 let ty = canonicalized_receiver.decanonicalize_ty(ty); 580 let ty = canonicalized_receiver.decanonicalize_ty(ty);
560 self.write_method_resolution(tgt_expr, func); 581 self.write_method_resolution(tgt_expr, func);
561 (ty, self.db.value_ty(func.into()), Some(self.db.generic_params(func.into()))) 582 (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into())))
562 } 583 }
563 None => (receiver_ty, Ty::Unknown, None), 584 None => (receiver_ty, Ty::Unknown, None),
564 }; 585 };
@@ -607,6 +628,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
607 continue; 628 continue;
608 } 629 }
609 630
631 let param_ty = self.insert_vars_for_impl_trait(param_ty);
610 let param_ty = self.normalize_associated_types_in(param_ty); 632 let param_ty = self.normalize_associated_types_in(param_ty);
611 self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); 633 self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone()));
612 } 634 }
@@ -615,17 +637,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
615 637
616 fn substs_for_method_call( 638 fn substs_for_method_call(
617 &mut self, 639 &mut self,
618 def_generics: Option<Arc<GenericParams>>, 640 def_generics: Option<Generics>,
619 generic_args: Option<&GenericArgs>, 641 generic_args: Option<&GenericArgs>,
620 receiver_ty: &Ty, 642 receiver_ty: &Ty,
621 ) -> Substs { 643 ) -> Substs {
622 let (parent_param_count, param_count) = 644 let (total_len, _parent_len, child_len) =
623 def_generics.as_ref().map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); 645 def_generics.as_ref().map_or((0, 0, 0), |g| g.len_split());
624 let mut substs = Vec::with_capacity(parent_param_count + param_count); 646 let mut substs = Vec::with_capacity(total_len);
625 // Parent arguments are unknown, except for the receiver type 647 // Parent arguments are unknown, except for the receiver type
626 if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) { 648 if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) {
627 for param in &parent_generics.params { 649 for (_id, param) in parent_generics {
628 if param.name == name::SELF_TYPE { 650 if param.name == name![Self] {
629 substs.push(receiver_ty.clone()); 651 substs.push(receiver_ty.clone());
630 } else { 652 } else {
631 substs.push(Ty::Unknown); 653 substs.push(Ty::Unknown);
@@ -635,7 +657,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
635 // handle provided type arguments 657 // handle provided type arguments
636 if let Some(generic_args) = generic_args { 658 if let Some(generic_args) = generic_args {
637 // if args are provided, it should be all of them, but we can't rely on that 659 // if args are provided, it should be all of them, but we can't rely on that
638 for arg in generic_args.args.iter().take(param_count) { 660 for arg in generic_args.args.iter().take(child_len) {
639 match arg { 661 match arg {
640 GenericArg::Type(type_ref) => { 662 GenericArg::Type(type_ref) => {
641 let ty = self.make_ty(type_ref); 663 let ty = self.make_ty(type_ref);
@@ -645,10 +667,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
645 } 667 }
646 }; 668 };
647 let supplied_params = substs.len(); 669 let supplied_params = substs.len();
648 for _ in supplied_params..parent_param_count + param_count { 670 for _ in supplied_params..total_len {
649 substs.push(Ty::Unknown); 671 substs.push(Ty::Unknown);
650 } 672 }
651 assert_eq!(substs.len(), parent_param_count + param_count); 673 assert_eq!(substs.len(), total_len);
652 Substs(substs.into()) 674 Substs(substs.into())
653 } 675 }
654 676
@@ -665,13 +687,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
665 // add obligation for trait implementation, if this is a trait method 687 // add obligation for trait implementation, if this is a trait method
666 match def { 688 match def {
667 CallableDef::FunctionId(f) => { 689 CallableDef::FunctionId(f) => {
668 if let ContainerId::TraitId(trait_) = f.lookup(self.db).container { 690 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db).container {
669 // construct a TraitDef 691 // construct a TraitDef
670 let substs = a_ty.parameters.prefix( 692 let substs =
671 self.db 693 a_ty.parameters.prefix(generics(self.db, trait_.into()).len());
672 .generic_params(trait_.into())
673 .count_params_including_parent(),
674 );
675 self.obligations.push(Obligation::Trait(TraitRef { 694 self.obligations.push(Obligation::Trait(TraitRef {
676 trait_: trait_.into(), 695 trait_: trait_.into(),
677 substs, 696 substs,
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index 1ebb36239..a14662884 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -170,7 +170,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
170 } 170 }
171 BindingMode::Move => inner_ty.clone(), 171 BindingMode::Move => inner_ty.clone(),
172 }; 172 };
173 let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty); 173 let bound_ty = self.resolve_ty_as_possible(bound_ty);
174 self.write_pat_ty(pat, bound_ty); 174 self.write_pat_ty(pat, bound_ty);
175 return inner_ty; 175 return inner_ty;
176 } 176 }
@@ -179,7 +179,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
179 // use a new type variable if we got Ty::Unknown here 179 // use a new type variable if we got Ty::Unknown here
180 let ty = self.insert_type_vars_shallow(ty); 180 let ty = self.insert_type_vars_shallow(ty);
181 self.unify(&ty, expected); 181 self.unify(&ty, expected);
182 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 182 let ty = self.resolve_ty_as_possible(ty);
183 self.write_pat_ty(pat, ty.clone()); 183 self.write_pat_ty(pat, ty.clone());
184 ty 184 ty
185 } 185 }
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index 14be66836..ffd358367 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -1,9 +1,11 @@
1//! Path expression resolution. 1//! Path expression resolution.
2 2
3use std::iter;
4
3use hir_def::{ 5use hir_def::{
4 path::{Path, PathKind, PathSegment}, 6 path::{Path, PathSegment},
5 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 7 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
6 AssocItemId, ContainerId, Lookup, 8 AssocContainerId, AssocItemId, Lookup,
7}; 9};
8use hir_expand::name::Name; 10use hir_expand::name::Name;
9 11
@@ -30,21 +32,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
30 path: &Path, 32 path: &Path,
31 id: ExprOrPatId, 33 id: ExprOrPatId,
32 ) -> Option<Ty> { 34 ) -> Option<Ty> {
33 let (value, self_subst) = if let PathKind::Type(type_ref) = &path.kind { 35 let (value, self_subst) = if let Some(type_ref) = path.type_anchor() {
34 if path.segments.is_empty() { 36 if path.segments().is_empty() {
35 // This can't actually happen syntax-wise 37 // This can't actually happen syntax-wise
36 return None; 38 return None;
37 } 39 }
38 let ty = self.make_ty(type_ref); 40 let ty = self.make_ty(type_ref);
39 let remaining_segments_for_ty = &path.segments[..path.segments.len() - 1]; 41 let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1);
40 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); 42 let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty);
41 self.resolve_ty_assoc_item( 43 self.resolve_ty_assoc_item(
42 ty, 44 ty,
43 &path.segments.last().expect("path had at least one segment").name, 45 &path.segments().last().expect("path had at least one segment").name,
44 id, 46 id,
45 )? 47 )?
46 } else { 48 } else {
47 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?; 49 let value_or_partial = resolver.resolve_path_in_value_ns(self.db, path.mod_path())?;
48 50
49 match value_or_partial { 51 match value_or_partial {
50 ResolveValueResult::ValueNs(it) => (it, None), 52 ResolveValueResult::ValueNs(it) => (it, None),
@@ -57,7 +59,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
57 let typable: ValueTyDefId = match value { 59 let typable: ValueTyDefId = match value {
58 ValueNs::LocalBinding(pat) => { 60 ValueNs::LocalBinding(pat) => {
59 let ty = self.result.type_of_pat.get(pat)?.clone(); 61 let ty = self.result.type_of_pat.get(pat)?.clone();
60 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 62 let ty = self.resolve_ty_as_possible(ty);
61 return Some(ty); 63 return Some(ty);
62 } 64 }
63 ValueNs::FunctionId(it) => it.into(), 65 ValueNs::FunctionId(it) => it.into(),
@@ -83,13 +85,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
83 remaining_index: usize, 85 remaining_index: usize,
84 id: ExprOrPatId, 86 id: ExprOrPatId,
85 ) -> Option<(ValueNs, Option<Substs>)> { 87 ) -> Option<(ValueNs, Option<Substs>)> {
86 assert!(remaining_index < path.segments.len()); 88 assert!(remaining_index < path.segments().len());
87 // there may be more intermediate segments between the resolved one and 89 // there may be more intermediate segments between the resolved one and
88 // the end. Only the last segment needs to be resolved to a value; from 90 // the end. Only the last segment needs to be resolved to a value; from
89 // the segments before that, we need to get either a type or a trait ref. 91 // the segments before that, we need to get either a type or a trait ref.
90 92
91 let resolved_segment = &path.segments[remaining_index - 1]; 93 let resolved_segment = path.segments().get(remaining_index - 1).unwrap();
92 let remaining_segments = &path.segments[remaining_index..]; 94 let remaining_segments = path.segments().skip(remaining_index);
93 let is_before_last = remaining_segments.len() == 1; 95 let is_before_last = remaining_segments.len() == 1;
94 96
95 match (def, is_before_last) { 97 match (def, is_before_last) {
@@ -110,7 +112,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
110 // trait but it's not the last segment, so the next segment 112 // trait but it's not the last segment, so the next segment
111 // should resolve to an associated type of that trait (e.g. `<T 113 // should resolve to an associated type of that trait (e.g. `<T
112 // as Iterator>::Item::default`) 114 // as Iterator>::Item::default`)
113 let remaining_segments_for_ty = &remaining_segments[..remaining_segments.len() - 1]; 115 let remaining_segments_for_ty =
116 remaining_segments.take(remaining_segments.len() - 1);
114 let ty = Ty::from_partly_resolved_hir_path( 117 let ty = Ty::from_partly_resolved_hir_path(
115 self.db, 118 self.db,
116 &self.resolver, 119 &self.resolver,
@@ -136,7 +139,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
136 fn resolve_trait_assoc_item( 139 fn resolve_trait_assoc_item(
137 &mut self, 140 &mut self,
138 trait_ref: TraitRef, 141 trait_ref: TraitRef,
139 segment: &PathSegment, 142 segment: PathSegment<'_>,
140 id: ExprOrPatId, 143 id: ExprOrPatId,
141 ) -> Option<(ValueNs, Option<Substs>)> { 144 ) -> Option<(ValueNs, Option<Substs>)> {
142 let trait_ = trait_ref.trait_; 145 let trait_ = trait_ref.trait_;
@@ -148,7 +151,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
148 .map(|(_name, id)| (*id).into()) 151 .map(|(_name, id)| (*id).into())
149 .find_map(|item| match item { 152 .find_map(|item| match item {
150 AssocItemId::FunctionId(func) => { 153 AssocItemId::FunctionId(func) => {
151 if segment.name == self.db.function_data(func).name { 154 if segment.name == &self.db.function_data(func).name {
152 Some(AssocItemId::FunctionId(func)) 155 Some(AssocItemId::FunctionId(func))
153 } else { 156 } else {
154 None 157 None
@@ -156,7 +159,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
156 } 159 }
157 160
158 AssocItemId::ConstId(konst) => { 161 AssocItemId::ConstId(konst) => {
159 if self.db.const_data(konst).name.as_ref().map_or(false, |n| n == &segment.name) 162 if self.db.const_data(konst).name.as_ref().map_or(false, |n| n == segment.name)
160 { 163 {
161 Some(AssocItemId::ConstId(konst)) 164 Some(AssocItemId::ConstId(konst))
162 } else { 165 } else {
@@ -206,12 +209,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
206 AssocItemId::TypeAliasId(_) => unreachable!(), 209 AssocItemId::TypeAliasId(_) => unreachable!(),
207 }; 210 };
208 let substs = match container { 211 let substs = match container {
209 ContainerId::ImplId(_) => self.find_self_types(&def, ty.clone()), 212 AssocContainerId::ImplId(impl_id) => {
210 ContainerId::TraitId(trait_) => { 213 let impl_substs = Substs::build_for_def(self.db, impl_id)
214 .fill(iter::repeat_with(|| self.table.new_type_var()))
215 .build();
216 let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs);
217 let substs = Substs::build_for_def(self.db, item)
218 .use_parent_substs(&impl_substs)
219 .fill_with_params()
220 .build();
221 self.unify(&impl_self_ty, &ty);
222 Some(substs)
223 }
224 AssocContainerId::TraitId(trait_) => {
211 // we're picking this method 225 // we're picking this method
212 let trait_substs = Substs::build_for_def(self.db, trait_) 226 let trait_substs = Substs::build_for_def(self.db, trait_)
213 .push(ty.clone()) 227 .push(ty.clone())
214 .fill(std::iter::repeat_with(|| self.new_type_var())) 228 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
215 .build(); 229 .build();
216 let substs = Substs::build_for_def(self.db, item) 230 let substs = Substs::build_for_def(self.db, item)
217 .use_parent_substs(&trait_substs) 231 .use_parent_substs(&trait_substs)
@@ -223,7 +237,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
223 })); 237 }));
224 Some(substs) 238 Some(substs)
225 } 239 }
226 ContainerId::ModuleId(_) => None, 240 AssocContainerId::ContainerId(_) => None,
227 }; 241 };
228 242
229 self.write_assoc_resolution(id, item.into()); 243 self.write_assoc_resolution(id, item.into());
@@ -231,38 +245,4 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
231 }, 245 },
232 ) 246 )
233 } 247 }
234
235 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
236 if let ValueNs::FunctionId(func) = *def {
237 // We only do the infer if parent has generic params
238 let gen = self.db.generic_params(func.into());
239 if gen.count_parent_params() == 0 {
240 return None;
241 }
242
243 let impl_id = match func.lookup(self.db).container {
244 ContainerId::ImplId(it) => it,
245 _ => return None,
246 };
247 let self_ty = self.db.impl_ty(impl_id).self_type().clone();
248 let self_ty_substs = self_ty.substs()?;
249 let actual_substs = actual_def_ty.substs()?;
250
251 let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
252
253 // The following code *link up* the function actual parma type
254 // and impl_block type param index
255 self_ty_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| {
256 if let Ty::Param { idx, .. } = param {
257 if let Some(s) = new_substs.get_mut(*idx as usize) {
258 *s = pty.clone();
259 }
260 }
261 });
262
263 Some(Substs(new_substs.into()))
264 } else {
265 None
266 }
267 }
268} 248}
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index f3a875678..fe05642ae 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -1,9 +1,15 @@
1//! Unification and canonicalization logic. 1//! Unification and canonicalization logic.
2 2
3use std::borrow::Cow;
4
5use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
6
7use test_utils::tested_by;
8
3use super::{InferenceContext, Obligation}; 9use super::{InferenceContext, Obligation};
4use crate::{ 10use crate::{
5 db::HirDatabase, utils::make_mut_slice, Canonical, InEnvironment, InferTy, ProjectionPredicate, 11 db::HirDatabase, utils::make_mut_slice, Canonical, InEnvironment, InferTy, ProjectionPredicate,
6 ProjectionTy, Substs, TraitRef, Ty, TypeWalk, 12 ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
7}; 13};
8 14
9impl<'a, D: HirDatabase> InferenceContext<'a, D> { 15impl<'a, D: HirDatabase> InferenceContext<'a, D> {
@@ -24,7 +30,7 @@ where
24 /// A stack of type variables that is used to detect recursive types (which 30 /// A stack of type variables that is used to detect recursive types (which
25 /// are an error, but we need to protect against them to avoid stack 31 /// are an error, but we need to protect against them to avoid stack
26 /// overflows). 32 /// overflows).
27 var_stack: Vec<super::TypeVarId>, 33 var_stack: Vec<TypeVarId>,
28} 34}
29 35
30pub(super) struct Canonicalized<T> { 36pub(super) struct Canonicalized<T> {
@@ -53,14 +59,14 @@ where
53 return tv.fallback_value(); 59 return tv.fallback_value();
54 } 60 }
55 if let Some(known_ty) = 61 if let Some(known_ty) =
56 self.ctx.var_unification_table.inlined_probe_value(inner).known() 62 self.ctx.table.var_unification_table.inlined_probe_value(inner).known()
57 { 63 {
58 self.var_stack.push(inner); 64 self.var_stack.push(inner);
59 let result = self.do_canonicalize_ty(known_ty.clone()); 65 let result = self.do_canonicalize_ty(known_ty.clone());
60 self.var_stack.pop(); 66 self.var_stack.pop();
61 result 67 result
62 } else { 68 } else {
63 let root = self.ctx.var_unification_table.find(inner); 69 let root = self.ctx.table.var_unification_table.find(inner);
64 let free_var = match tv { 70 let free_var = match tv {
65 InferTy::TypeVar(_) => InferTy::TypeVar(root), 71 InferTy::TypeVar(_) => InferTy::TypeVar(root),
66 InferTy::IntVar(_) => InferTy::IntVar(root), 72 InferTy::IntVar(_) => InferTy::IntVar(root),
@@ -153,10 +159,268 @@ impl<T> Canonicalized<T> {
153 solution: Canonical<Vec<Ty>>, 159 solution: Canonical<Vec<Ty>>,
154 ) { 160 ) {
155 // the solution may contain new variables, which we need to convert to new inference vars 161 // the solution may contain new variables, which we need to convert to new inference vars
156 let new_vars = Substs((0..solution.num_vars).map(|_| ctx.new_type_var()).collect()); 162 let new_vars = Substs((0..solution.num_vars).map(|_| ctx.table.new_type_var()).collect());
157 for (i, ty) in solution.value.into_iter().enumerate() { 163 for (i, ty) in solution.value.into_iter().enumerate() {
158 let var = self.free_vars[i]; 164 let var = self.free_vars[i];
159 ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars)); 165 ctx.table.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars));
166 }
167 }
168}
169
170pub fn unify(ty1: &Canonical<Ty>, ty2: &Canonical<Ty>) -> Option<Substs> {
171 let mut table = InferenceTable::new();
172 let vars =
173 Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build();
174 let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars);
175 if !table.unify(&ty_with_vars, &ty2.value) {
176 return None;
177 }
178 Some(
179 Substs::builder(ty1.num_vars)
180 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
181 .build(),
182 )
183}
184
185#[derive(Clone, Debug)]
186pub(crate) struct InferenceTable {
187 pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>,
188}
189
190impl InferenceTable {
191 pub fn new() -> Self {
192 InferenceTable { var_unification_table: InPlaceUnificationTable::new() }
193 }
194
195 pub fn new_type_var(&mut self) -> Ty {
196 Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
197 }
198
199 pub fn new_integer_var(&mut self) -> Ty {
200 Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
201 }
202
203 pub fn new_float_var(&mut self) -> Ty {
204 Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
205 }
206
207 pub fn new_maybe_never_type_var(&mut self) -> Ty {
208 Ty::Infer(InferTy::MaybeNeverTypeVar(
209 self.var_unification_table.new_key(TypeVarValue::Unknown),
210 ))
211 }
212
213 pub fn resolve_ty_completely(&mut self, ty: Ty) -> Ty {
214 self.resolve_ty_completely_inner(&mut Vec::new(), ty)
215 }
216
217 pub fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
218 self.resolve_ty_as_possible_inner(&mut Vec::new(), ty)
219 }
220
221 pub fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
222 self.unify_inner(ty1, ty2, 0)
223 }
224
225 pub fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool {
226 substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth))
227 }
228
229 fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool {
230 if depth > 1000 {
231 // prevent stackoverflows
232 panic!("infinite recursion in unification");
233 }
234 if ty1 == ty2 {
235 return true;
236 }
237 // try to resolve type vars first
238 let ty1 = self.resolve_ty_shallow(ty1);
239 let ty2 = self.resolve_ty_shallow(ty2);
240 match (&*ty1, &*ty2) {
241 (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => {
242 self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1)
243 }
244 _ => self.unify_inner_trivial(&ty1, &ty2),
245 }
246 }
247
248 pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
249 match (ty1, ty2) {
250 (Ty::Unknown, _) | (_, Ty::Unknown) => true,
251
252 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
253 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
254 | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2)))
255 | (
256 Ty::Infer(InferTy::MaybeNeverTypeVar(tv1)),
257 Ty::Infer(InferTy::MaybeNeverTypeVar(tv2)),
258 ) => {
259 // both type vars are unknown since we tried to resolve them
260 self.var_unification_table.union(*tv1, *tv2);
261 true
262 }
263
264 // The order of MaybeNeverTypeVar matters here.
265 // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar.
266 // Unifying MaybeNeverTypeVar and other concrete type will let the former become it.
267 (Ty::Infer(InferTy::TypeVar(tv)), other)
268 | (other, Ty::Infer(InferTy::TypeVar(tv)))
269 | (Ty::Infer(InferTy::MaybeNeverTypeVar(tv)), other)
270 | (other, Ty::Infer(InferTy::MaybeNeverTypeVar(tv)))
271 | (Ty::Infer(InferTy::IntVar(tv)), other @ ty_app!(TypeCtor::Int(_)))
272 | (other @ ty_app!(TypeCtor::Int(_)), Ty::Infer(InferTy::IntVar(tv)))
273 | (Ty::Infer(InferTy::FloatVar(tv)), other @ ty_app!(TypeCtor::Float(_)))
274 | (other @ ty_app!(TypeCtor::Float(_)), Ty::Infer(InferTy::FloatVar(tv))) => {
275 // the type var is unknown since we tried to resolve it
276 self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone()));
277 true
278 }
279
280 _ => false,
281 }
282 }
283
284 /// If `ty` is a type variable with known type, returns that type;
285 /// otherwise, return ty.
286 pub fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
287 let mut ty = Cow::Borrowed(ty);
288 // The type variable could resolve to a int/float variable. Hence try
289 // resolving up to three times; each type of variable shouldn't occur
290 // more than once
291 for i in 0..3 {
292 if i > 0 {
293 tested_by!(type_var_resolves_to_int_var);
294 }
295 match &*ty {
296 Ty::Infer(tv) => {
297 let inner = tv.to_inner();
298 match self.var_unification_table.inlined_probe_value(inner).known() {
299 Some(known_ty) => {
300 // The known_ty can't be a type var itself
301 ty = Cow::Owned(known_ty.clone());
302 }
303 _ => return ty,
304 }
305 }
306 _ => return ty,
307 }
308 }
309 log::error!("Inference variable still not resolved: {:?}", ty);
310 ty
311 }
312
313 /// Resolves the type as far as currently possible, replacing type variables
314 /// by their known types. All types returned by the infer_* functions should
315 /// be resolved as far as possible, i.e. contain no type variables with
316 /// known type.
317 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
318 ty.fold(&mut |ty| match ty {
319 Ty::Infer(tv) => {
320 let inner = tv.to_inner();
321 if tv_stack.contains(&inner) {
322 tested_by!(type_var_cycles_resolve_as_possible);
323 // recursive type
324 return tv.fallback_value();
325 }
326 if let Some(known_ty) =
327 self.var_unification_table.inlined_probe_value(inner).known()
328 {
329 // known_ty may contain other variables that are known by now
330 tv_stack.push(inner);
331 let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone());
332 tv_stack.pop();
333 result
334 } else {
335 ty
336 }
337 }
338 _ => ty,
339 })
340 }
341
342 /// Resolves the type completely; type variables without known type are
343 /// replaced by Ty::Unknown.
344 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
345 ty.fold(&mut |ty| match ty {
346 Ty::Infer(tv) => {
347 let inner = tv.to_inner();
348 if tv_stack.contains(&inner) {
349 tested_by!(type_var_cycles_resolve_completely);
350 // recursive type
351 return tv.fallback_value();
352 }
353 if let Some(known_ty) =
354 self.var_unification_table.inlined_probe_value(inner).known()
355 {
356 // known_ty may contain other variables that are known by now
357 tv_stack.push(inner);
358 let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone());
359 tv_stack.pop();
360 result
361 } else {
362 tv.fallback_value()
363 }
364 }
365 _ => ty,
366 })
367 }
368}
369
370/// The ID of a type variable.
371#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
372pub struct TypeVarId(pub(super) u32);
373
374impl UnifyKey for TypeVarId {
375 type Value = TypeVarValue;
376
377 fn index(&self) -> u32 {
378 self.0
379 }
380
381 fn from_index(i: u32) -> Self {
382 TypeVarId(i)
383 }
384
385 fn tag() -> &'static str {
386 "TypeVarId"
387 }
388}
389
390/// The value of a type variable: either we already know the type, or we don't
391/// know it yet.
392#[derive(Clone, PartialEq, Eq, Debug)]
393pub enum TypeVarValue {
394 Known(Ty),
395 Unknown,
396}
397
398impl TypeVarValue {
399 fn known(&self) -> Option<&Ty> {
400 match self {
401 TypeVarValue::Known(ty) => Some(ty),
402 TypeVarValue::Unknown => None,
403 }
404 }
405}
406
407impl UnifyValue for TypeVarValue {
408 type Error = NoError;
409
410 fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
411 match (value1, value2) {
412 // We should never equate two type variables, both of which have
413 // known types. Instead, we recursively equate those types.
414 (TypeVarValue::Known(t1), TypeVarValue::Known(t2)) => panic!(
415 "equating two type variables, both of which have known types: {:?} and {:?}",
416 t1, t2
417 ),
418
419 // If one side is known, prefer that one.
420 (TypeVarValue::Known(..), TypeVarValue::Unknown) => Ok(value1.clone()),
421 (TypeVarValue::Unknown, TypeVarValue::Known(..)) => Ok(value2.clone()),
422
423 (TypeVarValue::Unknown, TypeVarValue::Unknown) => Ok(TypeVarValue::Unknown),
160 } 424 }
161 } 425 }
162} 426}