diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 27 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 12 |
2 files changed, 27 insertions, 12 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 74fc77cfb..675df4a22 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -412,11 +412,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
412 | ty | 412 | ty |
413 | } | 413 | } |
414 | 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. | ||
415 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { | 421 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { |
422 | let ty = self.resolve_ty_as_possible(&mut vec![], ty); | ||
416 | ty.fold(&mut |ty| match ty { | 423 | ty.fold(&mut |ty| match ty { |
417 | Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty), | 424 | Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty), |
418 | Ty::UnselectedProjection(proj_ty) => { | 425 | Ty::UnselectedProjection(proj_ty) => { |
419 | // FIXME | 426 | // FIXME use Chalk's unselected projection support |
420 | Ty::UnselectedProjection(proj_ty) | 427 | Ty::UnselectedProjection(proj_ty) |
421 | } | 428 | } |
422 | _ => ty, | 429 | _ => ty, |
@@ -569,6 +576,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
569 | 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); |
570 | let ty = ty.subst(&substs); | 577 | let ty = ty.subst(&substs); |
571 | let ty = self.insert_type_vars(ty); | 578 | let ty = self.insert_type_vars(ty); |
579 | let ty = self.normalize_associated_types_in(ty); | ||
572 | Some(ty) | 580 | Some(ty) |
573 | } | 581 | } |
574 | Resolution::LocalBinding(pat) => { | 582 | Resolution::LocalBinding(pat) => { |
@@ -690,6 +698,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
690 | .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))) |
691 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | 699 | .map_or(Ty::Unknown, |field| field.ty(self.db)) |
692 | .subst(&substs); | 700 | .subst(&substs); |
701 | let expected_ty = self.normalize_associated_types_in(expected_ty); | ||
693 | self.infer_pat(subpat, &expected_ty, default_bm); | 702 | self.infer_pat(subpat, &expected_ty, default_bm); |
694 | } | 703 | } |
695 | 704 | ||
@@ -717,6 +726,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
717 | 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)); |
718 | let expected_ty = | 727 | let expected_ty = |
719 | 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); | ||
720 | self.infer_pat(subpat.pat, &expected_ty, default_bm); | 730 | self.infer_pat(subpat.pat, &expected_ty, default_bm); |
721 | } | 731 | } |
722 | 732 | ||
@@ -947,9 +957,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
947 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | 957 | self.unify(&expected_receiver_ty, &actual_receiver_ty); |
948 | 958 | ||
949 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 959 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); |
950 | for (arg, param) in args.iter().zip(param_iter) { | 960 | for (arg, param_ty) in args.iter().zip(param_iter) { |
951 | 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)); | ||
952 | } | 963 | } |
964 | let ret_ty = self.normalize_associated_types_in(ret_ty); | ||
953 | ret_ty | 965 | ret_ty |
954 | } | 966 | } |
955 | 967 | ||
@@ -1040,9 +1052,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1040 | }; | 1052 | }; |
1041 | self.register_obligations_for_call(&callee_ty); | 1053 | self.register_obligations_for_call(&callee_ty); |
1042 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 1054 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); |
1043 | for (arg, param) in args.iter().zip(param_iter) { | 1055 | for (arg, param_ty) in args.iter().zip(param_iter) { |
1044 | 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)); | ||
1045 | } | 1058 | } |
1059 | let ret_ty = self.normalize_associated_types_in(ret_ty); | ||
1046 | ret_ty | 1060 | ret_ty |
1047 | } | 1061 | } |
1048 | Expr::MethodCall { receiver, args, method_name, generic_args } => self | 1062 | Expr::MethodCall { receiver, args, method_name, generic_args } => self |
@@ -1140,7 +1154,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1140 | _ => None, | 1154 | _ => None, |
1141 | }) | 1155 | }) |
1142 | .unwrap_or(Ty::Unknown); | 1156 | .unwrap_or(Ty::Unknown); |
1143 | self.insert_type_vars(ty) | 1157 | let ty = self.insert_type_vars(ty); |
1158 | self.normalize_associated_types_in(ty) | ||
1144 | } | 1159 | } |
1145 | Expr::Await { expr } => { | 1160 | Expr::Await { expr } => { |
1146 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 1161 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 01b358335..e6a09cc67 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -2515,10 +2515,10 @@ fn test<T: Iterable>() { | |||
2515 | @r###" | 2515 | @r###" |
2516 | ⋮ | 2516 | ⋮ |
2517 | ⋮[108; 227) '{ ...ter; }': () | 2517 | ⋮[108; 227) '{ ...ter; }': () |
2518 | ⋮[118; 119) 'x': <S as Iterable>::Item | 2518 | ⋮[118; 119) 'x': u32 |
2519 | ⋮[145; 146) '1': <S as Iterable>::Item | 2519 | ⋮[145; 146) '1': u32 |
2520 | ⋮[156; 157) 'y': <T as Iterable>::Item | 2520 | ⋮[156; 157) 'y': {unknown} |
2521 | ⋮[183; 192) 'no_matter': <T as Iterable>::Item | 2521 | ⋮[183; 192) 'no_matter': {unknown} |
2522 | ⋮[202; 203) 'z': {unknown} | 2522 | ⋮[202; 203) 'z': {unknown} |
2523 | ⋮[215; 224) 'no_matter': {unknown} | 2523 | ⋮[215; 224) 'no_matter': {unknown} |
2524 | "### | 2524 | "### |
@@ -2552,9 +2552,9 @@ fn test() { | |||
2552 | ⋮[205; 209) 'foo1': fn foo1<S>(T) -> {unknown} | 2552 | ⋮[205; 209) 'foo1': fn foo1<S>(T) -> {unknown} |
2553 | ⋮[205; 212) 'foo1(S)': {unknown} | 2553 | ⋮[205; 212) 'foo1(S)': {unknown} |
2554 | ⋮[210; 211) 'S': S | 2554 | ⋮[210; 211) 'S': S |
2555 | ⋮[222; 223) 'y': <S as Iterable>::Item | 2555 | ⋮[222; 223) 'y': u32 |
2556 | ⋮[226; 230) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item | 2556 | ⋮[226; 230) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item |
2557 | ⋮[226; 233) 'foo2(S)': <S as Iterable>::Item | 2557 | ⋮[226; 233) 'foo2(S)': u32 |
2558 | ⋮[231; 232) 'S': S | 2558 | ⋮[231; 232) 'S': S |
2559 | "### | 2559 | "### |
2560 | ); | 2560 | ); |