diff options
author | uHOOCCOOHu <[email protected]> | 2019-09-17 21:15:31 +0100 |
---|---|---|
committer | uHOOCCOOHu <[email protected]> | 2019-09-25 23:02:04 +0100 |
commit | 5205c84ec7d6284b258e66a06c3e330c3f9fdd88 (patch) | |
tree | 0f91cb3081f435dd547f9183b145ce1c58164ab1 /crates/ra_hir/src/ty/infer.rs | |
parent | 870ce4b1a50a07e3a536ab26215804acdfc9ba8a (diff) |
Support auto-deref in argument position
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 76b4b6faa..746b07a05 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -806,6 +806,47 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
806 | } | 806 | } |
807 | } | 807 | } |
808 | 808 | ||
809 | fn unify_with_autoderef(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { | ||
810 | macro_rules! ty_app { | ||
811 | ($ctor:pat, $param:pat) => { | ||
812 | Ty::Apply(ApplicationTy { ctor: $ctor, parameters: $param }) | ||
813 | }; | ||
814 | } | ||
815 | |||
816 | // If given type and expected type are compatible reference, | ||
817 | // trigger auto-deref. | ||
818 | let (_to_mut, from_ty, to_ty) = | ||
819 | match (&*self.resolve_ty_shallow(&from_ty), &*self.resolve_ty_shallow(&to_ty)) { | ||
820 | ( | ||
821 | ty_app!(TypeCtor::Ref(from_mut), from_param), | ||
822 | ty_app!(TypeCtor::Ref(to_mut), to_param), | ||
823 | ) if *from_mut == Mutability::Mut || from_mut == to_mut => { | ||
824 | (to_mut, from_param[0].clone(), to_param[0].clone()) | ||
825 | } | ||
826 | _ => { | ||
827 | // Otherwise, just unify | ||
828 | return self.unify(&from_ty, &to_ty); | ||
829 | } | ||
830 | }; | ||
831 | |||
832 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty); | ||
833 | // FIXME: Auto DerefMut | ||
834 | for derefed_ty in | ||
835 | autoderef::autoderef(self.db, &self.resolver.clone(), canonicalized.value.clone()) | ||
836 | { | ||
837 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | ||
838 | match (&*self.resolve_ty_shallow(&derefed_ty), &*self.resolve_ty_shallow(&to_ty)) { | ||
839 | // Unify when constructor matches. | ||
840 | (ty_app!(from_ctor, _), ty_app!(to_ctor, _)) if from_ctor == to_ctor => { | ||
841 | return self.unify(&derefed_ty, &to_ty); | ||
842 | } | ||
843 | _ => {} | ||
844 | } | ||
845 | } | ||
846 | |||
847 | false | ||
848 | } | ||
849 | |||
809 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { | 850 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { |
810 | let ty = self.infer_expr_inner(tgt_expr, expected); | 851 | let ty = self.infer_expr_inner(tgt_expr, expected); |
811 | let could_unify = self.unify(&ty, &expected.ty); | 852 | let could_unify = self.unify(&ty, &expected.ty); |
@@ -1285,7 +1326,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1285 | } | 1326 | } |
1286 | 1327 | ||
1287 | let param_ty = self.normalize_associated_types_in(param_ty); | 1328 | let param_ty = self.normalize_associated_types_in(param_ty); |
1288 | self.infer_expr(arg, &Expectation::has_type(param_ty)); | 1329 | let arg_ty = self.infer_expr_inner(arg, &Expectation::has_type(param_ty.clone())); |
1330 | self.unify_with_autoderef(&arg_ty, ¶m_ty); | ||
1289 | } | 1331 | } |
1290 | } | 1332 | } |
1291 | } | 1333 | } |