diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 63 |
1 files changed, 49 insertions, 14 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 81a8623bf..378d2f829 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -790,11 +790,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
790 | }; | 790 | }; |
791 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | 791 | self.unify(&expected_receiver_ty, &actual_receiver_ty); |
792 | 792 | ||
793 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 793 | self.check_call_arguments(args, ¶m_tys); |
794 | for (arg, param_ty) in args.iter().zip(param_iter) { | ||
795 | let param_ty = self.normalize_associated_types_in(param_ty); | ||
796 | self.infer_expr(*arg, &Expectation::has_type(param_ty)); | ||
797 | } | ||
798 | let ret_ty = self.normalize_associated_types_in(ret_ty); | 794 | let ret_ty = self.normalize_associated_types_in(ret_ty); |
799 | ret_ty | 795 | ret_ty |
800 | } | 796 | } |
@@ -885,18 +881,37 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
885 | Expr::Lambda { body, args, arg_types } => { | 881 | Expr::Lambda { body, args, arg_types } => { |
886 | assert_eq!(args.len(), arg_types.len()); | 882 | assert_eq!(args.len(), arg_types.len()); |
887 | 883 | ||
884 | let mut sig_tys = Vec::new(); | ||
885 | |||
888 | for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { | 886 | for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { |
889 | let expected = if let Some(type_ref) = arg_type { | 887 | let expected = if let Some(type_ref) = arg_type { |
890 | self.make_ty(type_ref) | 888 | self.make_ty(type_ref) |
891 | } else { | 889 | } else { |
892 | Ty::Unknown | 890 | Ty::Unknown |
893 | }; | 891 | }; |
894 | self.infer_pat(*arg_pat, &expected, BindingMode::default()); | 892 | let arg_ty = self.infer_pat(*arg_pat, &expected, BindingMode::default()); |
893 | sig_tys.push(arg_ty); | ||
895 | } | 894 | } |
896 | 895 | ||
897 | // FIXME: infer lambda type etc. | 896 | // add return type |
898 | let _body_ty = self.infer_expr(*body, &Expectation::none()); | 897 | let ret_ty = self.new_type_var(); |
899 | Ty::Unknown | 898 | sig_tys.push(ret_ty.clone()); |
899 | let sig_ty = Ty::apply( | ||
900 | TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, | ||
901 | sig_tys.into(), | ||
902 | ); | ||
903 | let closure_ty = Ty::apply_one( | ||
904 | TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr }, | ||
905 | sig_ty, | ||
906 | ); | ||
907 | |||
908 | // Eagerly try to relate the closure type with the expected | ||
909 | // type, otherwise we often won't have enough information to | ||
910 | // infer the body. | ||
911 | self.coerce(&closure_ty, &expected.ty); | ||
912 | |||
913 | self.infer_expr(*body, &Expectation::has_type(ret_ty)); | ||
914 | closure_ty | ||
900 | } | 915 | } |
901 | Expr::Call { callee, args } => { | 916 | Expr::Call { callee, args } => { |
902 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); | 917 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); |
@@ -909,11 +924,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
909 | } | 924 | } |
910 | }; | 925 | }; |
911 | self.register_obligations_for_call(&callee_ty); | 926 | self.register_obligations_for_call(&callee_ty); |
912 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 927 | self.check_call_arguments(args, ¶m_tys); |
913 | for (arg, param_ty) in args.iter().zip(param_iter) { | ||
914 | let param_ty = self.normalize_associated_types_in(param_ty); | ||
915 | self.infer_expr(*arg, &Expectation::has_type(param_ty)); | ||
916 | } | ||
917 | let ret_ty = self.normalize_associated_types_in(ret_ty); | 928 | let ret_ty = self.normalize_associated_types_in(ret_ty); |
918 | ret_ty | 929 | ret_ty |
919 | } | 930 | } |
@@ -1255,6 +1266,30 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1255 | ty | 1266 | ty |
1256 | } | 1267 | } |
1257 | 1268 | ||
1269 | fn check_call_arguments(&mut self, args: &[ExprId], param_tys: &[Ty]) { | ||
1270 | // Quoting https://github.com/rust-lang/rust/blob/6ef275e6c3cb1384ec78128eceeb4963ff788dca/src/librustc_typeck/check/mod.rs#L3325 -- | ||
1271 | // We do this in a pretty awful way: first we type-check any arguments | ||
1272 | // that are not closures, then we type-check the closures. This is so | ||
1273 | // that we have more information about the types of arguments when we | ||
1274 | // type-check the functions. This isn't really the right way to do this. | ||
1275 | for &check_closures in &[false, true] { | ||
1276 | let param_iter = param_tys.iter().cloned().chain(repeat(Ty::Unknown)); | ||
1277 | for (&arg, param_ty) in args.iter().zip(param_iter) { | ||
1278 | let is_closure = match &self.body[arg] { | ||
1279 | Expr::Lambda { .. } => true, | ||
1280 | _ => false, | ||
1281 | }; | ||
1282 | |||
1283 | if is_closure != check_closures { | ||
1284 | continue; | ||
1285 | } | ||
1286 | |||
1287 | let param_ty = self.normalize_associated_types_in(param_ty); | ||
1288 | self.infer_expr(arg, &Expectation::has_type(param_ty)); | ||
1289 | } | ||
1290 | } | ||
1291 | } | ||
1292 | |||
1258 | fn collect_const(&mut self, data: &ConstData) { | 1293 | fn collect_const(&mut self, data: &ConstData) { |
1259 | self.return_ty = self.make_ty(data.type_ref()); | 1294 | self.return_ty = self.make_ty(data.type_ref()); |
1260 | } | 1295 | } |