aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r--crates/ra_hir/src/ty/infer.rs63
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, &param_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, &param_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 }