diff options
Diffstat (limited to 'crates/hir_ty/src/infer/expr.rs')
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 49 |
1 files changed, 25 insertions, 24 deletions
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 08c05c67c..41ef45326 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -44,7 +44,7 @@ impl<'a> InferenceContext<'a> { | |||
44 | if !could_unify { | 44 | if !could_unify { |
45 | self.result.type_mismatches.insert( | 45 | self.result.type_mismatches.insert( |
46 | tgt_expr.into(), | 46 | tgt_expr.into(), |
47 | TypeMismatch { expected: expected_ty.clone(), actual: ty.clone() }, | 47 | TypeMismatch { expected: expected_ty, actual: ty.clone() }, |
48 | ); | 48 | ); |
49 | } | 49 | } |
50 | } | 50 | } |
@@ -57,15 +57,14 @@ impl<'a> InferenceContext<'a> { | |||
57 | let ty = self.infer_expr_inner(expr, &expected); | 57 | let ty = self.infer_expr_inner(expr, &expected); |
58 | let ty = if let Some(target) = expected.only_has_type(&mut self.table) { | 58 | let ty = if let Some(target) = expected.only_has_type(&mut self.table) { |
59 | if !self.coerce(&ty, &target) { | 59 | if !self.coerce(&ty, &target) { |
60 | self.result.type_mismatches.insert( | 60 | self.result |
61 | expr.into(), | 61 | .type_mismatches |
62 | TypeMismatch { expected: target.clone(), actual: ty.clone() }, | 62 | .insert(expr.into(), TypeMismatch { expected: target, actual: ty.clone() }); |
63 | ); | ||
64 | // Return actual type when type mismatch. | 63 | // Return actual type when type mismatch. |
65 | // This is needed for diagnostic when return type mismatch. | 64 | // This is needed for diagnostic when return type mismatch. |
66 | ty | 65 | ty |
67 | } else { | 66 | } else { |
68 | target.clone() | 67 | target |
69 | } | 68 | } |
70 | } else { | 69 | } else { |
71 | ty | 70 | ty |
@@ -120,7 +119,7 @@ impl<'a> InferenceContext<'a> { | |||
120 | } | 119 | } |
121 | 120 | ||
122 | fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { | 121 | fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { |
123 | self.db.check_canceled(); | 122 | self.db.unwind_if_cancelled(); |
124 | 123 | ||
125 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 124 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
126 | let ty = match &body[tgt_expr] { | 125 | let ty = match &body[tgt_expr] { |
@@ -805,7 +804,7 @@ impl<'a> InferenceContext<'a> { | |||
805 | None => self.table.new_float_var(), | 804 | None => self.table.new_float_var(), |
806 | }, | 805 | }, |
807 | }, | 806 | }, |
808 | Expr::MacroStmts { tail } => self.infer_expr(*tail, expected), | 807 | Expr::MacroStmts { tail } => self.infer_expr_inner(*tail, expected), |
809 | }; | 808 | }; |
810 | // use a new type variable if we got unknown here | 809 | // use a new type variable if we got unknown here |
811 | let ty = self.insert_type_vars_shallow(ty); | 810 | let ty = self.insert_type_vars_shallow(ty); |
@@ -891,17 +890,21 @@ impl<'a> InferenceContext<'a> { | |||
891 | method_name, | 890 | method_name, |
892 | ) | 891 | ) |
893 | }); | 892 | }); |
894 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { | 893 | let (derefed_receiver_ty, method_ty, substs) = match resolved { |
895 | Some((ty, func)) => { | 894 | Some((ty, func)) => { |
896 | let ty = canonicalized_receiver.decanonicalize_ty(ty); | 895 | let ty = canonicalized_receiver.decanonicalize_ty(ty); |
897 | self.write_method_resolution(tgt_expr, func); | 896 | let generics = generics(self.db.upcast(), func.into()); |
898 | (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into()))) | 897 | let substs = self.substs_for_method_call(generics, generic_args, &ty); |
898 | self.write_method_resolution(tgt_expr, func, substs.clone()); | ||
899 | (ty, self.db.value_ty(func.into()), substs) | ||
899 | } | 900 | } |
900 | None => (receiver_ty, Binders::empty(&Interner, self.err_ty()), None), | 901 | None => ( |
902 | receiver_ty, | ||
903 | Binders::empty(&Interner, self.err_ty()), | ||
904 | Substitution::empty(&Interner), | ||
905 | ), | ||
901 | }; | 906 | }; |
902 | let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); | ||
903 | let method_ty = method_ty.substitute(&Interner, &substs); | 907 | let method_ty = method_ty.substitute(&Interner, &substs); |
904 | let method_ty = self.insert_type_vars(method_ty); | ||
905 | self.register_obligations_for_call(&method_ty); | 908 | self.register_obligations_for_call(&method_ty); |
906 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { | 909 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { |
907 | Some(sig) => { | 910 | Some(sig) => { |
@@ -950,23 +953,21 @@ impl<'a> InferenceContext<'a> { | |||
950 | 953 | ||
951 | fn substs_for_method_call( | 954 | fn substs_for_method_call( |
952 | &mut self, | 955 | &mut self, |
953 | def_generics: Option<Generics>, | 956 | def_generics: Generics, |
954 | generic_args: Option<&GenericArgs>, | 957 | generic_args: Option<&GenericArgs>, |
955 | receiver_ty: &Ty, | 958 | receiver_ty: &Ty, |
956 | ) -> Substitution { | 959 | ) -> Substitution { |
957 | let (parent_params, self_params, type_params, impl_trait_params) = | 960 | let (parent_params, self_params, type_params, impl_trait_params) = |
958 | def_generics.as_ref().map_or((0, 0, 0, 0), |g| g.provenance_split()); | 961 | def_generics.provenance_split(); |
959 | assert_eq!(self_params, 0); // method shouldn't have another Self param | 962 | assert_eq!(self_params, 0); // method shouldn't have another Self param |
960 | let total_len = parent_params + type_params + impl_trait_params; | 963 | let total_len = parent_params + type_params + impl_trait_params; |
961 | let mut substs = Vec::with_capacity(total_len); | 964 | let mut substs = Vec::with_capacity(total_len); |
962 | // Parent arguments are unknown, except for the receiver type | 965 | // Parent arguments are unknown, except for the receiver type |
963 | if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { | 966 | for (_id, param) in def_generics.iter_parent() { |
964 | for (_id, param) in parent_generics { | 967 | if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { |
965 | if param.provenance == hir_def::generics::TypeParamProvenance::TraitSelf { | 968 | substs.push(receiver_ty.clone()); |
966 | substs.push(receiver_ty.clone()); | 969 | } else { |
967 | } else { | 970 | substs.push(self.table.new_type_var()); |
968 | substs.push(self.err_ty()); | ||
969 | } | ||
970 | } | 971 | } |
971 | } | 972 | } |
972 | // handle provided type arguments | 973 | // handle provided type arguments |
@@ -989,7 +990,7 @@ impl<'a> InferenceContext<'a> { | |||
989 | }; | 990 | }; |
990 | let supplied_params = substs.len(); | 991 | let supplied_params = substs.len(); |
991 | for _ in supplied_params..total_len { | 992 | for _ in supplied_params..total_len { |
992 | substs.push(self.err_ty()); | 993 | substs.push(self.table.new_type_var()); |
993 | } | 994 | } |
994 | assert_eq!(substs.len(), total_len); | 995 | assert_eq!(substs.len(), total_len); |
995 | Substitution::from_iter(&Interner, substs) | 996 | Substitution::from_iter(&Interner, substs) |