diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 594c5bc79..675df4a22 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -245,7 +245,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
245 | &self.resolver, | 245 | &self.resolver, |
246 | type_ref, | 246 | type_ref, |
247 | ); | 247 | ); |
248 | self.insert_type_vars(ty) | 248 | let ty = self.insert_type_vars(ty); |
249 | self.normalize_associated_types_in(ty) | ||
249 | } | 250 | } |
250 | 251 | ||
251 | fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool { | 252 | fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool { |
@@ -411,6 +412,32 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
411 | ty | 412 | ty |
412 | } | 413 | } |
413 | 414 | ||
415 | /// Recurses through the given type, normalizing associated types mentioned | ||
416 | /// in it by replacing them by type variables and registering obligations to | ||
417 | /// resolve later. This should be done once for every type we get from some | ||
418 | /// type annotation (e.g. from a let type annotation, field type or function | ||
419 | /// call). `make_ty` handles this already, but e.g. for field types we need | ||
420 | /// to do it as well. | ||
421 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { | ||
422 | let ty = self.resolve_ty_as_possible(&mut vec![], ty); | ||
423 | ty.fold(&mut |ty| match ty { | ||
424 | Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty), | ||
425 | Ty::UnselectedProjection(proj_ty) => { | ||
426 | // FIXME use Chalk's unselected projection support | ||
427 | Ty::UnselectedProjection(proj_ty) | ||
428 | } | ||
429 | _ => ty, | ||
430 | }) | ||
431 | } | ||
432 | |||
433 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { | ||
434 | let var = self.new_type_var(); | ||
435 | let predicate = ProjectionPredicate { projection_ty: proj_ty.clone(), ty: var.clone() }; | ||
436 | let obligation = Obligation::Projection(predicate); | ||
437 | self.obligations.push(obligation); | ||
438 | var | ||
439 | } | ||
440 | |||
414 | /// Resolves the type completely; type variables without known type are | 441 | /// Resolves the type completely; type variables without known type are |
415 | /// replaced by Ty::Unknown. | 442 | /// replaced by Ty::Unknown. |
416 | fn resolve_ty_completely(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | 443 | fn resolve_ty_completely(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
@@ -549,6 +576,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
549 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | 576 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); |
550 | let ty = ty.subst(&substs); | 577 | let ty = ty.subst(&substs); |
551 | let ty = self.insert_type_vars(ty); | 578 | let ty = self.insert_type_vars(ty); |
579 | let ty = self.normalize_associated_types_in(ty); | ||
552 | Some(ty) | 580 | Some(ty) |
553 | } | 581 | } |
554 | Resolution::LocalBinding(pat) => { | 582 | Resolution::LocalBinding(pat) => { |
@@ -670,6 +698,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
670 | .and_then(|d| d.field(self.db, &Name::tuple_field_name(i))) | 698 | .and_then(|d| d.field(self.db, &Name::tuple_field_name(i))) |
671 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | 699 | .map_or(Ty::Unknown, |field| field.ty(self.db)) |
672 | .subst(&substs); | 700 | .subst(&substs); |
701 | let expected_ty = self.normalize_associated_types_in(expected_ty); | ||
673 | self.infer_pat(subpat, &expected_ty, default_bm); | 702 | self.infer_pat(subpat, &expected_ty, default_bm); |
674 | } | 703 | } |
675 | 704 | ||
@@ -697,6 +726,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
697 | let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); | 726 | let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); |
698 | let expected_ty = | 727 | let expected_ty = |
699 | matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs); | 728 | matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs); |
729 | let expected_ty = self.normalize_associated_types_in(expected_ty); | ||
700 | self.infer_pat(subpat.pat, &expected_ty, default_bm); | 730 | self.infer_pat(subpat.pat, &expected_ty, default_bm); |
701 | } | 731 | } |
702 | 732 | ||
@@ -927,9 +957,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
927 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | 957 | self.unify(&expected_receiver_ty, &actual_receiver_ty); |
928 | 958 | ||
929 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 959 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); |
930 | for (arg, param) in args.iter().zip(param_iter) { | 960 | for (arg, param_ty) in args.iter().zip(param_iter) { |
931 | self.infer_expr(*arg, &Expectation::has_type(param)); | 961 | let param_ty = self.normalize_associated_types_in(param_ty); |
962 | self.infer_expr(*arg, &Expectation::has_type(param_ty)); | ||
932 | } | 963 | } |
964 | let ret_ty = self.normalize_associated_types_in(ret_ty); | ||
933 | ret_ty | 965 | ret_ty |
934 | } | 966 | } |
935 | 967 | ||
@@ -1020,9 +1052,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1020 | }; | 1052 | }; |
1021 | self.register_obligations_for_call(&callee_ty); | 1053 | self.register_obligations_for_call(&callee_ty); |
1022 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 1054 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); |
1023 | for (arg, param) in args.iter().zip(param_iter) { | 1055 | for (arg, param_ty) in args.iter().zip(param_iter) { |
1024 | self.infer_expr(*arg, &Expectation::has_type(param)); | 1056 | let param_ty = self.normalize_associated_types_in(param_ty); |
1057 | self.infer_expr(*arg, &Expectation::has_type(param_ty)); | ||
1025 | } | 1058 | } |
1059 | let ret_ty = self.normalize_associated_types_in(ret_ty); | ||
1026 | ret_ty | 1060 | ret_ty |
1027 | } | 1061 | } |
1028 | Expr::MethodCall { receiver, args, method_name, generic_args } => self | 1062 | Expr::MethodCall { receiver, args, method_name, generic_args } => self |
@@ -1120,7 +1154,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1120 | _ => None, | 1154 | _ => None, |
1121 | }) | 1155 | }) |
1122 | .unwrap_or(Ty::Unknown); | 1156 | .unwrap_or(Ty::Unknown); |
1123 | self.insert_type_vars(ty) | 1157 | let ty = self.insert_type_vars(ty); |
1158 | self.normalize_associated_types_in(ty) | ||
1124 | } | 1159 | } |
1125 | Expr::Await { expr } => { | 1160 | Expr::Await { expr } => { |
1126 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 1161 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); |