diff options
Diffstat (limited to 'crates/ra_hir_ty/src/infer')
-rw-r--r-- | crates/ra_hir_ty/src/infer/coerce.rs | 27 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 247 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/pat.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/path.rs | 86 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/unify.rs | 276 |
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 | |||
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | use test_utils::tested_by; | 9 | use test_utils::tested_by; |
10 | 10 | ||
11 | use crate::{autoderef, db::HirDatabase, ImplTy, Substs, Ty, TypeCtor, TypeWalk}; | 11 | use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk}; |
12 | 12 | ||
13 | use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; | 13 | use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext}; |
14 | 14 | ||
15 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 15 | impl<'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; | |||
6 | use hir_def::{ | 6 | use 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 | }; |
14 | use hir_expand::name::{self, Name}; | 13 | use hir_expand::name::{name, Name}; |
14 | use ra_syntax::ast::RangeOp; | ||
15 | 15 | ||
16 | use crate::{ | 16 | use 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 | ||
22 | use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; | 26 | use 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 | ||
3 | use std::iter; | ||
4 | |||
3 | use hir_def::{ | 5 | use 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 | }; |
8 | use hir_expand::name::Name; | 10 | use 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 | ||
3 | use std::borrow::Cow; | ||
4 | |||
5 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | ||
6 | |||
7 | use test_utils::tested_by; | ||
8 | |||
3 | use super::{InferenceContext, Obligation}; | 9 | use super::{InferenceContext, Obligation}; |
4 | use crate::{ | 10 | use 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 | ||
9 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 15 | impl<'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 | ||
30 | pub(super) struct Canonicalized<T> { | 36 | pub(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 | |||
170 | pub 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)] | ||
186 | pub(crate) struct InferenceTable { | ||
187 | pub(super) var_unification_table: InPlaceUnificationTable<TypeVarId>, | ||
188 | } | ||
189 | |||
190 | impl 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)] | ||
372 | pub struct TypeVarId(pub(super) u32); | ||
373 | |||
374 | impl 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)] | ||
393 | pub enum TypeVarValue { | ||
394 | Known(Ty), | ||
395 | Unknown, | ||
396 | } | ||
397 | |||
398 | impl TypeVarValue { | ||
399 | fn known(&self) -> Option<&Ty> { | ||
400 | match self { | ||
401 | TypeVarValue::Known(ty) => Some(ty), | ||
402 | TypeVarValue::Unknown => None, | ||
403 | } | ||
404 | } | ||
405 | } | ||
406 | |||
407 | impl 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 | } |