diff options
author | Florian Diebold <[email protected]> | 2019-09-24 22:04:33 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-09-24 22:05:12 +0100 |
commit | 6a8670665032f6103ca14e38ed9106126b20063d (patch) | |
tree | ff9c2f3c665ef95ebf509dc69ff82d39ec42d176 /crates/ra_hir/src/ty/infer.rs | |
parent | a0aeb6e7ad7385811a4bb75577513339c9a9ed91 (diff) |
Implement the call argument checking order hack for closures
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 4784fad85..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 | } |
@@ -928,11 +924,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
928 | } | 924 | } |
929 | }; | 925 | }; |
930 | self.register_obligations_for_call(&callee_ty); | 926 | self.register_obligations_for_call(&callee_ty); |
931 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 927 | self.check_call_arguments(args, ¶m_tys); |
932 | for (arg, param_ty) in args.iter().zip(param_iter) { | ||
933 | let param_ty = self.normalize_associated_types_in(param_ty); | ||
934 | self.infer_expr(*arg, &Expectation::has_type(param_ty)); | ||
935 | } | ||
936 | let ret_ty = self.normalize_associated_types_in(ret_ty); | 928 | let ret_ty = self.normalize_associated_types_in(ret_ty); |
937 | ret_ty | 929 | ret_ty |
938 | } | 930 | } |
@@ -1274,6 +1266,30 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1274 | ty | 1266 | ty |
1275 | } | 1267 | } |
1276 | 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 | |||
1277 | fn collect_const(&mut self, data: &ConstData) { | 1293 | fn collect_const(&mut self, data: &ConstData) { |
1278 | self.return_ty = self.make_ty(data.type_ref()); | 1294 | self.return_ty = self.make_ty(data.type_ref()); |
1279 | } | 1295 | } |