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.rs44
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, &param_ty);
1289 } 1331 }
1290 } 1332 }
1291 } 1333 }