diff options
author | uHOOCCOOHu <[email protected]> | 2019-09-12 19:59:21 +0100 |
---|---|---|
committer | uHOOCCOOHu <[email protected]> | 2019-09-25 23:04:39 +0100 |
commit | 4bb66df6de6a832f53f09128ea038fc1c0068515 (patch) | |
tree | dc0509537b1f1cb0c61e0719d4d6f3317e09cc9f /crates/ra_hir/src | |
parent | 5205c84ec7d6284b258e66a06c3e330c3f9fdd88 (diff) |
Support basic implicit type coerce
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 254 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 271 |
2 files changed, 383 insertions, 142 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 746b07a05..def787fb1 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -190,6 +190,15 @@ struct InferenceContext<'a, D: HirDatabase> { | |||
190 | return_ty: Ty, | 190 | return_ty: Ty, |
191 | } | 191 | } |
192 | 192 | ||
193 | macro_rules! ty_app { | ||
194 | ($ctor:pat, $param:pat) => { | ||
195 | Ty::Apply(ApplicationTy { ctor: $ctor, parameters: $param }) | ||
196 | }; | ||
197 | ($ctor:pat) => { | ||
198 | ty_app!($ctor, _) | ||
199 | }; | ||
200 | } | ||
201 | |||
193 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 202 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
194 | fn new(db: &'a D, body: Arc<Body>, resolver: Resolver) -> Self { | 203 | fn new(db: &'a D, body: Arc<Body>, resolver: Resolver) -> Self { |
195 | InferenceContext { | 204 | InferenceContext { |
@@ -278,10 +287,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
278 | let ty1 = self.resolve_ty_shallow(ty1); | 287 | let ty1 = self.resolve_ty_shallow(ty1); |
279 | let ty2 = self.resolve_ty_shallow(ty2); | 288 | let ty2 = self.resolve_ty_shallow(ty2); |
280 | match (&*ty1, &*ty2) { | 289 | match (&*ty1, &*ty2) { |
281 | (Ty::Unknown, _) | (_, Ty::Unknown) => true, | ||
282 | (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { | 290 | (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { |
283 | self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) | 291 | self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) |
284 | } | 292 | } |
293 | _ => self.unify_inner_trivial(&ty1, &ty2), | ||
294 | } | ||
295 | } | ||
296 | |||
297 | fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | ||
298 | match (ty1, ty2) { | ||
299 | (Ty::Unknown, _) | (_, Ty::Unknown) => true, | ||
285 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) | 300 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) |
286 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) | 301 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) |
287 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => { | 302 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => { |
@@ -795,50 +810,146 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
795 | ret_ty | 810 | ret_ty |
796 | } | 811 | } |
797 | 812 | ||
798 | /// This is similar to unify, but it makes the first type coerce to the | 813 | /// Infer type of expression with possibly implicit coerce to the expected type. |
799 | /// second one. | 814 | fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty { |
815 | let ty = self.infer_expr_inner(expr, &expected); | ||
816 | self.coerce(&ty, &expected.ty); | ||
817 | ty | ||
818 | } | ||
819 | |||
820 | /// Unify two types, but may coerce the first one to the second one | ||
821 | /// using "implicit coercion rules" if needed. | ||
822 | /// | ||
823 | /// See: https://doc.rust-lang.org/nomicon/coercions.html | ||
800 | fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { | 824 | fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { |
801 | if is_never(from_ty) { | 825 | let from_ty = self.resolve_ty_shallow(from_ty).into_owned(); |
802 | // ! coerces to any type | 826 | let to_ty = self.resolve_ty_shallow(to_ty); |
803 | true | 827 | self.coerce_inner(from_ty, &to_ty) |
804 | } else { | 828 | } |
805 | self.unify(from_ty, to_ty) | 829 | |
830 | fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { | ||
831 | match (&mut from_ty, &*to_ty) { | ||
832 | // Top and bottom type | ||
833 | (ty_app!(TypeCtor::Never), _) => return true, | ||
834 | |||
835 | // FIXME: Solve `FromTy: CoerceUnsized<ToTy>` instead of listing common impls here. | ||
836 | |||
837 | // `*mut T`, `&mut T, `&T`` -> `*const T` | ||
838 | // `&mut T` -> `&T` | ||
839 | // `&mut T` -> `*mut T` | ||
840 | (ty_app!(c1@TypeCtor::RawPtr(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) | ||
841 | | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::RawPtr(Mutability::Shared))) | ||
842 | | (ty_app!(c1@TypeCtor::Ref(_)), ty_app!(c2@TypeCtor::Ref(Mutability::Shared))) | ||
843 | | (ty_app!(c1@TypeCtor::Ref(Mutability::Mut)), ty_app!(c2@TypeCtor::RawPtr(_))) => { | ||
844 | *c1 = *c2; | ||
845 | } | ||
846 | |||
847 | // Illegal mutablity conversion | ||
848 | ( | ||
849 | ty_app!(TypeCtor::RawPtr(Mutability::Shared)), | ||
850 | ty_app!(TypeCtor::RawPtr(Mutability::Mut)), | ||
851 | ) | ||
852 | | ( | ||
853 | ty_app!(TypeCtor::Ref(Mutability::Shared)), | ||
854 | ty_app!(TypeCtor::Ref(Mutability::Mut)), | ||
855 | ) => return false, | ||
856 | |||
857 | // `{function_type}` -> `fn()` | ||
858 | (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnPtr { .. })) => { | ||
859 | match from_ty.callable_sig(self.db) { | ||
860 | None => return false, | ||
861 | Some(sig) => { | ||
862 | let num_args = sig.params_and_return.len() as u16 - 1; | ||
863 | from_ty = | ||
864 | Ty::apply(TypeCtor::FnPtr { num_args }, Substs(sig.params_and_return)); | ||
865 | } | ||
866 | } | ||
867 | } | ||
868 | |||
869 | // Trivial cases, this should go after `never` check to | ||
870 | // avoid infer result type to be never | ||
871 | _ => { | ||
872 | if self.unify_inner_trivial(&from_ty, &to_ty) { | ||
873 | return true; | ||
874 | } | ||
875 | } | ||
876 | } | ||
877 | |||
878 | // Try coerce or unify | ||
879 | match (&from_ty, &to_ty) { | ||
880 | // FIXME: Solve `FromTy: CoerceUnsized<ToTy>` instead of listing common impls here. | ||
881 | (ty_app!(TypeCtor::Ref(_), st1), ty_app!(TypeCtor::Ref(_), st2)) | ||
882 | | (ty_app!(TypeCtor::RawPtr(_), st1), ty_app!(TypeCtor::RawPtr(_), st2)) => { | ||
883 | match self.try_coerce_unsized(&st1[0], &st2[0], 0) { | ||
884 | Some(ret) => return ret, | ||
885 | None => {} | ||
886 | } | ||
887 | } | ||
888 | _ => {} | ||
889 | } | ||
890 | |||
891 | // Auto Deref if cannot coerce | ||
892 | match (&from_ty, &to_ty) { | ||
893 | (ty_app!(TypeCtor::Ref(_), st1), ty_app!(TypeCtor::Ref(_), st2)) => { | ||
894 | self.unify_autoderef_behind_ref(&st1[0], &st2[0]) | ||
895 | } | ||
896 | |||
897 | // Normal unify | ||
898 | _ => self.unify(&from_ty, &to_ty), | ||
806 | } | 899 | } |
807 | } | 900 | } |
808 | 901 | ||
809 | fn unify_with_autoderef(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { | 902 | /// Coerce a type to a DST if `FromTy: Unsize<ToTy>` |
810 | macro_rules! ty_app { | 903 | /// |
811 | ($ctor:pat, $param:pat) => { | 904 | /// See: `https://doc.rust-lang.org/nightly/std/marker/trait.Unsize.html` |
812 | Ty::Apply(ApplicationTy { ctor: $ctor, parameters: $param }) | 905 | fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty, depth: usize) -> Option<bool> { |
813 | }; | 906 | if depth > 1000 { |
907 | panic!("Infinite recursion in coercion"); | ||
814 | } | 908 | } |
815 | 909 | ||
816 | // If given type and expected type are compatible reference, | 910 | // FIXME: Correctly handle |
817 | // trigger auto-deref. | 911 | match (&from_ty, &to_ty) { |
818 | let (_to_mut, from_ty, to_ty) = | 912 | // `[T; N]` -> `[T]` |
819 | match (&*self.resolve_ty_shallow(&from_ty), &*self.resolve_ty_shallow(&to_ty)) { | 913 | (ty_app!(TypeCtor::Array, st1), ty_app!(TypeCtor::Slice, st2)) => { |
820 | ( | 914 | Some(self.unify(&st1[0], &st2[0])) |
821 | ty_app!(TypeCtor::Ref(from_mut), from_param), | 915 | } |
822 | ty_app!(TypeCtor::Ref(to_mut), to_param), | 916 | |
823 | ) if *from_mut == Mutability::Mut || from_mut == to_mut => { | 917 | // `T` -> `dyn Trait` when `T: Trait` |
824 | (to_mut, from_param[0].clone(), to_param[0].clone()) | 918 | (_, Ty::Dyn(_)) => { |
825 | } | 919 | // FIXME: Check predicates |
826 | _ => { | 920 | Some(true) |
827 | // Otherwise, just unify | 921 | } |
828 | return self.unify(&from_ty, &to_ty); | 922 | |
923 | (ty_app!(ctor1, st1), ty_app!(ctor2, st2)) if ctor1 == ctor2 => { | ||
924 | for (ty1, ty2) in st1.iter().zip(st2.iter()) { | ||
925 | match self.try_coerce_unsized(ty1, ty2, depth + 1) { | ||
926 | Some(true) => {} | ||
927 | ret => return ret, | ||
928 | } | ||
829 | } | 929 | } |
830 | }; | 930 | Some(true) |
931 | } | ||
932 | |||
933 | _ => None, | ||
934 | } | ||
935 | } | ||
831 | 936 | ||
832 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty); | 937 | /// Unify `from_ty` to `to_ty` with optional auto Deref |
938 | /// | ||
939 | /// Note that the parameters are already stripped the outer reference. | ||
940 | fn unify_autoderef_behind_ref(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { | ||
941 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); | ||
942 | let to_ty = self.resolve_ty_shallow(&to_ty); | ||
833 | // FIXME: Auto DerefMut | 943 | // FIXME: Auto DerefMut |
834 | for derefed_ty in | 944 | for derefed_ty in |
835 | autoderef::autoderef(self.db, &self.resolver.clone(), canonicalized.value.clone()) | 945 | autoderef::autoderef(self.db, &self.resolver.clone(), canonicalized.value.clone()) |
836 | { | 946 | { |
837 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 947 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
838 | match (&*self.resolve_ty_shallow(&derefed_ty), &*self.resolve_ty_shallow(&to_ty)) { | 948 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { |
839 | // Unify when constructor matches. | 949 | // Stop when constructor matches. |
840 | (ty_app!(from_ctor, _), ty_app!(to_ctor, _)) if from_ctor == to_ctor => { | 950 | (ty_app!(from_ctor, st1), ty_app!(to_ctor, st2)) if from_ctor == to_ctor => { |
841 | return self.unify(&derefed_ty, &to_ty); | 951 | // It will not recurse to `coerce`. |
952 | return self.unify_substs(st1, st2, 0); | ||
842 | } | 953 | } |
843 | _ => {} | 954 | _ => {} |
844 | } | 955 | } |
@@ -875,9 +986,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
875 | Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), | 986 | Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), |
876 | None => Ty::unit(), | 987 | None => Ty::unit(), |
877 | }; | 988 | }; |
878 | self.coerce(&else_ty, &expected.ty); | 989 | if !self.coerce(&else_ty, &expected.ty) { |
879 | 990 | self.coerce(&expected.ty, &else_ty); | |
880 | expected.ty.clone() | 991 | else_ty.clone() |
992 | } else { | ||
993 | expected.ty.clone() | ||
994 | } | ||
881 | } | 995 | } |
882 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), | 996 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), |
883 | Expr::TryBlock { body } => { | 997 | Expr::TryBlock { body } => { |
@@ -973,13 +1087,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
973 | .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), | 1087 | .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), |
974 | Expr::Match { expr, arms } => { | 1088 | Expr::Match { expr, arms } => { |
975 | let input_ty = self.infer_expr(*expr, &Expectation::none()); | 1089 | let input_ty = self.infer_expr(*expr, &Expectation::none()); |
976 | let expected = if expected.ty == Ty::Unknown { | 1090 | let mut expected = match expected.ty { |
977 | Expectation::has_type(self.new_type_var()) | 1091 | Ty::Unknown => Expectation::has_type(Ty::simple(TypeCtor::Never)), |
978 | } else { | 1092 | _ => expected.clone(), |
979 | expected.clone() | ||
980 | }; | 1093 | }; |
981 | 1094 | let mut all_never = true; | |
982 | let mut arm_tys = Vec::with_capacity(arms.len()); | ||
983 | 1095 | ||
984 | for arm in arms { | 1096 | for arm in arms { |
985 | for &pat in &arm.pats { | 1097 | for &pat in &arm.pats { |
@@ -991,16 +1103,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
991 | &Expectation::has_type(Ty::simple(TypeCtor::Bool)), | 1103 | &Expectation::has_type(Ty::simple(TypeCtor::Bool)), |
992 | ); | 1104 | ); |
993 | } | 1105 | } |
994 | arm_tys.push(self.infer_expr_inner(arm.expr, &expected)); | 1106 | let arm_ty = self.infer_expr_inner(arm.expr, &expected); |
1107 | match &arm_ty { | ||
1108 | ty_app!(TypeCtor::Never) => (), | ||
1109 | _ => all_never = false, | ||
1110 | } | ||
1111 | if !self.coerce(&arm_ty, &expected.ty) { | ||
1112 | self.coerce(&expected.ty, &arm_ty); | ||
1113 | expected = Expectation::has_type(arm_ty); | ||
1114 | } | ||
995 | } | 1115 | } |
996 | 1116 | ||
997 | let lub_ty = calculate_least_upper_bound(expected.ty, &arm_tys); | 1117 | if all_never { |
998 | 1118 | Ty::simple(TypeCtor::Never) | |
999 | for arm_ty in &arm_tys { | 1119 | } else { |
1000 | self.coerce(arm_ty, &lub_ty); | 1120 | expected.ty |
1001 | } | 1121 | } |
1002 | |||
1003 | lub_ty | ||
1004 | } | 1122 | } |
1005 | Expr::Path(p) => { | 1123 | Expr::Path(p) => { |
1006 | // FIXME this could be more efficient... | 1124 | // FIXME this could be more efficient... |
@@ -1289,8 +1407,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1289 | type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown); | 1407 | type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown); |
1290 | let decl_ty = self.insert_type_vars(decl_ty); | 1408 | let decl_ty = self.insert_type_vars(decl_ty); |
1291 | let ty = if let Some(expr) = initializer { | 1409 | let ty = if let Some(expr) = initializer { |
1292 | let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty)); | 1410 | self.infer_expr_coerce(*expr, &Expectation::has_type(decl_ty)) |
1293 | expr_ty | ||
1294 | } else { | 1411 | } else { |
1295 | decl_ty | 1412 | decl_ty |
1296 | }; | 1413 | }; |
@@ -1326,8 +1443,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1326 | } | 1443 | } |
1327 | 1444 | ||
1328 | let param_ty = self.normalize_associated_types_in(param_ty); | 1445 | let param_ty = self.normalize_associated_types_in(param_ty); |
1329 | let arg_ty = self.infer_expr_inner(arg, &Expectation::has_type(param_ty.clone())); | 1446 | self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); |
1330 | self.unify_with_autoderef(&arg_ty, ¶m_ty); | ||
1331 | } | 1447 | } |
1332 | } | 1448 | } |
1333 | } | 1449 | } |
@@ -1517,37 +1633,3 @@ mod diagnostics { | |||
1517 | } | 1633 | } |
1518 | } | 1634 | } |
1519 | } | 1635 | } |
1520 | |||
1521 | fn is_never(ty: &Ty) -> bool { | ||
1522 | if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) = ty { | ||
1523 | true | ||
1524 | } else { | ||
1525 | false | ||
1526 | } | ||
1527 | } | ||
1528 | |||
1529 | fn calculate_least_upper_bound(expected_ty: Ty, actual_tys: &[Ty]) -> Ty { | ||
1530 | let mut all_never = true; | ||
1531 | let mut last_never_ty = None; | ||
1532 | let mut least_upper_bound = expected_ty; | ||
1533 | |||
1534 | for actual_ty in actual_tys { | ||
1535 | if is_never(actual_ty) { | ||
1536 | last_never_ty = Some(actual_ty.clone()); | ||
1537 | } else { | ||
1538 | all_never = false; | ||
1539 | least_upper_bound = match (actual_ty, &least_upper_bound) { | ||
1540 | (_, Ty::Unknown) | ||
1541 | | (Ty::Infer(_), Ty::Infer(InferTy::TypeVar(_))) | ||
1542 | | (Ty::Apply(_), _) => actual_ty.clone(), | ||
1543 | _ => least_upper_bound, | ||
1544 | } | ||
1545 | } | ||
1546 | } | ||
1547 | |||
1548 | if all_never && last_never_ty.is_some() { | ||
1549 | last_never_ty.unwrap() | ||
1550 | } else { | ||
1551 | least_upper_bound | ||
1552 | } | ||
1553 | } | ||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 6076e4025..2ce0039b1 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -806,14 +806,14 @@ fn infer_argument_autoderef() { | |||
806 | infer(r#" | 806 | infer(r#" |
807 | #[lang = "deref"] | 807 | #[lang = "deref"] |
808 | pub trait Deref { | 808 | pub trait Deref { |
809 | type Target: ?Sized; | 809 | type Target; |
810 | fn deref(&self) -> &Self::Target; | 810 | fn deref(&self) -> &Self::Target; |
811 | } | 811 | } |
812 | 812 | ||
813 | struct A<T>(T); | 813 | struct A<T>(T); |
814 | 814 | ||
815 | impl<T: Copy> A<T> { | 815 | impl<T> A<T> { |
816 | fn foo(&self) -> T { | 816 | fn foo(&self) -> &T { |
817 | self.0 | 817 | self.0 |
818 | } | 818 | } |
819 | } | 819 | } |
@@ -828,32 +828,33 @@ impl<T> Deref for B<T> { | |||
828 | } | 828 | } |
829 | 829 | ||
830 | fn test() { | 830 | fn test() { |
831 | A::foo(&&B(B(A(42)))); | 831 | let t = A::foo(&&B(B(A(42)))); |
832 | } | 832 | } |
833 | "#), | 833 | "#), |
834 | @r###" | 834 | @r###" |
835 | [76; 80) 'self': &Self | 835 | [68; 72) 'self': &Self |
836 | [153; 157) 'self': &A<T> | 836 | [139; 143) 'self': &A<T> |
837 | [164; 186) '{ ... }': T | 837 | [151; 173) '{ ... }': T |
838 | [174; 178) 'self': &A<T> | 838 | [161; 165) 'self': &A<T> |
839 | [174; 180) 'self.0': T | 839 | [161; 167) 'self.0': T |
840 | [267; 271) 'self': &B<T> | 840 | [254; 258) 'self': &B<T> |
841 | [290; 313) '{ ... }': &T | 841 | [277; 300) '{ ... }': &T |
842 | [300; 307) '&self.0': &T | 842 | [287; 294) '&self.0': &T |
843 | [301; 305) 'self': &B<T> | 843 | [288; 292) 'self': &B<T> |
844 | [301; 307) 'self.0': T | 844 | [288; 294) 'self.0': T |
845 | [327; 357) '{ ...))); }': () | 845 | [314; 352) '{ ...))); }': () |
846 | [333; 339) 'A::foo': fn foo<i32>(&A<T>) -> T | 846 | [324; 325) 't': &i32 |
847 | [333; 354) 'A::foo...42))))': i32 | 847 | [328; 334) 'A::foo': fn foo<i32>(&A<T>) -> &T |
848 | [340; 353) '&&B(B(A(42)))': &&B<B<A<i32>>> | 848 | [328; 349) 'A::foo...42))))': &i32 |
849 | [341; 353) '&B(B(A(42)))': &B<B<A<i32>>> | 849 | [335; 348) '&&B(B(A(42)))': &&B<B<A<i32>>> |
850 | [342; 343) 'B': B<B<A<i32>>>(T) -> B<T> | 850 | [336; 348) '&B(B(A(42)))': &B<B<A<i32>>> |
851 | [342; 353) 'B(B(A(42)))': B<B<A<i32>>> | 851 | [337; 338) 'B': B<B<A<i32>>>(T) -> B<T> |
852 | [344; 345) 'B': B<A<i32>>(T) -> B<T> | 852 | [337; 348) 'B(B(A(42)))': B<B<A<i32>>> |
853 | [344; 352) 'B(A(42))': B<A<i32>> | 853 | [339; 340) 'B': B<A<i32>>(T) -> B<T> |
854 | [346; 347) 'A': A<i32>(T) -> A<T> | 854 | [339; 347) 'B(A(42))': B<A<i32>> |
855 | [346; 351) 'A(42)': A<i32> | 855 | [341; 342) 'A': A<i32>(T) -> A<T> |
856 | [348; 350) '42': i32 | 856 | [341; 346) 'A(42)': A<i32> |
857 | [343; 345) '42': i32 | ||
857 | "### | 858 | "### |
858 | ); | 859 | ); |
859 | } | 860 | } |
@@ -864,15 +865,15 @@ fn infer_method_argument_autoderef() { | |||
864 | infer(r#" | 865 | infer(r#" |
865 | #[lang = "deref"] | 866 | #[lang = "deref"] |
866 | pub trait Deref { | 867 | pub trait Deref { |
867 | type Target: ?Sized; | 868 | type Target; |
868 | fn deref(&self) -> &Self::Target; | 869 | fn deref(&self) -> &Self::Target; |
869 | } | 870 | } |
870 | 871 | ||
871 | struct A<T>(*mut T); | 872 | struct A<T>(*mut T); |
872 | 873 | ||
873 | impl<T: Copy> A<T> { | 874 | impl<T> A<T> { |
874 | fn foo(&self, x: &A<T>) -> T { | 875 | fn foo(&self, x: &A<T>) -> &T { |
875 | x | 876 | &*x.0 |
876 | } | 877 | } |
877 | } | 878 | } |
878 | 879 | ||
@@ -886,39 +887,197 @@ impl<T> Deref for B<T> { | |||
886 | } | 887 | } |
887 | 888 | ||
888 | fn test(a: A<i32>) { | 889 | fn test(a: A<i32>) { |
889 | A(0 as *mut _).foo(&&B(B(a))); | 890 | let t = A(0 as *mut _).foo(&&B(B(a))); |
891 | } | ||
892 | "#), | ||
893 | @r###" | ||
894 | [68; 72) 'self': &Self | ||
895 | [144; 148) 'self': &A<T> | ||
896 | [150; 151) 'x': &A<T> | ||
897 | [166; 187) '{ ... }': &T | ||
898 | [176; 181) '&*x.0': &T | ||
899 | [177; 181) '*x.0': T | ||
900 | [178; 179) 'x': &A<T> | ||
901 | [178; 181) 'x.0': *mut T | ||
902 | [268; 272) 'self': &B<T> | ||
903 | [291; 314) '{ ... }': &T | ||
904 | [301; 308) '&self.0': &T | ||
905 | [302; 306) 'self': &B<T> | ||
906 | [302; 308) 'self.0': T | ||
907 | [326; 327) 'a': A<i32> | ||
908 | [337; 383) '{ ...))); }': () | ||
909 | [347; 348) 't': &i32 | ||
910 | [351; 352) 'A': A<i32>(*mut T) -> A<T> | ||
911 | [351; 365) 'A(0 as *mut _)': A<i32> | ||
912 | [351; 380) 'A(0 as...B(a)))': &i32 | ||
913 | [353; 354) '0': i32 | ||
914 | [353; 364) '0 as *mut _': *mut i32 | ||
915 | [370; 379) '&&B(B(a))': &&B<B<A<i32>>> | ||
916 | [371; 379) '&B(B(a))': &B<B<A<i32>>> | ||
917 | [372; 373) 'B': B<B<A<i32>>>(T) -> B<T> | ||
918 | [372; 379) 'B(B(a))': B<B<A<i32>>> | ||
919 | [374; 375) 'B': B<A<i32>>(T) -> B<T> | ||
920 | [374; 378) 'B(a)': B<A<i32>> | ||
921 | [376; 377) 'a': A<i32> | ||
922 | "### | ||
923 | ); | ||
924 | } | ||
925 | |||
926 | #[test] | ||
927 | fn infer_if_coerce() { | ||
928 | assert_snapshot!( | ||
929 | infer(r#" | ||
930 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
931 | fn test() { | ||
932 | let x = if true { | ||
933 | foo(&[1]) | ||
934 | } else { | ||
935 | &[1] | ||
936 | }; | ||
890 | } | 937 | } |
891 | "#), | 938 | "#), |
892 | @r###" | 939 | @r###" |
893 | [76; 80) 'self': &Self | 940 | [11; 12) 'x': &[T] |
894 | [158; 162) 'self': &A<T> | 941 | [28; 39) '{ loop {} }': ! |
895 | [164; 165) 'x': &A<T> | 942 | [30; 37) 'loop {}': ! |
896 | [179; 196) '{ ... }': &A<T> | 943 | [35; 37) '{}': () |
897 | [189; 190) 'x': &A<T> | 944 | [50; 126) '{ ... }; }': () |
898 | [277; 281) 'self': &B<T> | 945 | [60; 61) 'x': &[i32] |
899 | [300; 323) '{ ... }': &T | 946 | [64; 123) 'if tru... }': &[i32] |
900 | [310; 317) '&self.0': &T | 947 | [67; 71) 'true': bool |
901 | [311; 315) 'self': &B<T> | 948 | [72; 97) '{ ... }': &[i32] |
902 | [311; 317) 'self.0': T | 949 | [82; 85) 'foo': fn foo<i32>(&[T]) -> &[T] |
903 | [335; 336) 'a': A<i32> | 950 | [82; 91) 'foo(&[1])': &[i32] |
904 | [346; 384) '{ ...))); }': () | 951 | [86; 90) '&[1]': &[i32;_] |
905 | [352; 353) 'A': A<i32>(*mut T) -> A<T> | 952 | [87; 90) '[1]': [i32;_] |
906 | [352; 366) 'A(0 as *mut _)': A<i32> | 953 | [88; 89) '1': i32 |
907 | [352; 381) 'A(0 as...B(a)))': i32 | 954 | [103; 123) '{ ... }': &[i32;_] |
908 | [354; 355) '0': i32 | 955 | [113; 117) '&[1]': &[i32;_] |
909 | [354; 365) '0 as *mut _': *mut i32 | 956 | [114; 117) '[1]': [i32;_] |
910 | [371; 380) '&&B(B(a))': &&B<B<A<i32>>> | 957 | [115; 116) '1': i32 |
911 | [372; 380) '&B(B(a))': &B<B<A<i32>>> | ||
912 | [373; 374) 'B': B<B<A<i32>>>(T) -> B<T> | ||
913 | [373; 380) 'B(B(a))': B<B<A<i32>>> | ||
914 | [375; 376) 'B': B<A<i32>>(T) -> B<T> | ||
915 | [375; 379) 'B(a)': B<A<i32>> | ||
916 | [377; 378) 'a': A<i32> | ||
917 | "### | 958 | "### |
918 | ); | 959 | ); |
919 | } | 960 | } |
920 | 961 | ||
921 | #[test] | 962 | #[test] |
963 | fn infer_if_else_coerce() { | ||
964 | assert_snapshot!( | ||
965 | infer(r#" | ||
966 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
967 | fn test() { | ||
968 | let x = if true { | ||
969 | &[1] | ||
970 | } else { | ||
971 | foo(&[1]) | ||
972 | }; | ||
973 | } | ||
974 | "#), | ||
975 | @r###" | ||
976 | [11; 12) 'x': &[T] | ||
977 | [28; 39) '{ loop {} }': ! | ||
978 | [30; 37) 'loop {}': ! | ||
979 | [35; 37) '{}': () | ||
980 | [50; 126) '{ ... }; }': () | ||
981 | [60; 61) 'x': &[i32] | ||
982 | [64; 123) 'if tru... }': &[i32] | ||
983 | [67; 71) 'true': bool | ||
984 | [72; 92) '{ ... }': &[i32;_] | ||
985 | [82; 86) '&[1]': &[i32;_] | ||
986 | [83; 86) '[1]': [i32;_] | ||
987 | [84; 85) '1': i32 | ||
988 | [98; 123) '{ ... }': &[i32] | ||
989 | [108; 111) 'foo': fn foo<i32>(&[T]) -> &[T] | ||
990 | [108; 117) 'foo(&[1])': &[i32] | ||
991 | [112; 116) '&[1]': &[i32;_] | ||
992 | [113; 116) '[1]': [i32;_] | ||
993 | [114; 115) '1': i32 | ||
994 | "### | ||
995 | ); | ||
996 | } | ||
997 | |||
998 | #[test] | ||
999 | fn infer_match_first_coerce() { | ||
1000 | assert_snapshot!( | ||
1001 | infer(r#" | ||
1002 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
1003 | fn test(i: i32) { | ||
1004 | let x = match i { | ||
1005 | 2 => foo(&[2]), | ||
1006 | 1 => &[1], | ||
1007 | _ => &[3], | ||
1008 | }; | ||
1009 | } | ||
1010 | "#), | ||
1011 | @r###" | ||
1012 | [11; 12) 'x': &[T] | ||
1013 | [28; 39) '{ loop {} }': ! | ||
1014 | [30; 37) 'loop {}': ! | ||
1015 | [35; 37) '{}': () | ||
1016 | [48; 49) 'i': i32 | ||
1017 | [56; 150) '{ ... }; }': () | ||
1018 | [66; 67) 'x': &[i32] | ||
1019 | [70; 147) 'match ... }': &[i32] | ||
1020 | [76; 77) 'i': i32 | ||
1021 | [88; 89) '2': i32 | ||
1022 | [93; 96) 'foo': fn foo<i32>(&[T]) -> &[T] | ||
1023 | [93; 102) 'foo(&[2])': &[i32] | ||
1024 | [97; 101) '&[2]': &[i32;_] | ||
1025 | [98; 101) '[2]': [i32;_] | ||
1026 | [99; 100) '2': i32 | ||
1027 | [112; 113) '1': i32 | ||
1028 | [117; 121) '&[1]': &[i32;_] | ||
1029 | [118; 121) '[1]': [i32;_] | ||
1030 | [119; 120) '1': i32 | ||
1031 | [131; 132) '_': i32 | ||
1032 | [136; 140) '&[3]': &[i32;_] | ||
1033 | [137; 140) '[3]': [i32;_] | ||
1034 | [138; 139) '3': i32 | ||
1035 | "### | ||
1036 | ); | ||
1037 | } | ||
1038 | |||
1039 | #[test] | ||
1040 | fn infer_match_second_coerce() { | ||
1041 | assert_snapshot!( | ||
1042 | infer(r#" | ||
1043 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | ||
1044 | fn test(i: i32) { | ||
1045 | let x = match i { | ||
1046 | 1 => &[1], | ||
1047 | 2 => foo(&[2]), | ||
1048 | _ => &[3], | ||
1049 | }; | ||
1050 | } | ||
1051 | "#), | ||
1052 | @r###" | ||
1053 | [11; 12) 'x': &[T] | ||
1054 | [28; 39) '{ loop {} }': ! | ||
1055 | [30; 37) 'loop {}': ! | ||
1056 | [35; 37) '{}': () | ||
1057 | [48; 49) 'i': i32 | ||
1058 | [56; 150) '{ ... }; }': () | ||
1059 | [66; 67) 'x': &[i32] | ||
1060 | [70; 147) 'match ... }': &[i32] | ||
1061 | [76; 77) 'i': i32 | ||
1062 | [88; 89) '1': i32 | ||
1063 | [93; 97) '&[1]': &[i32;_] | ||
1064 | [94; 97) '[1]': [i32;_] | ||
1065 | [95; 96) '1': i32 | ||
1066 | [107; 108) '2': i32 | ||
1067 | [112; 115) 'foo': fn foo<i32>(&[T]) -> &[T] | ||
1068 | [112; 121) 'foo(&[2])': &[i32] | ||
1069 | [116; 120) '&[2]': &[i32;_] | ||
1070 | [117; 120) '[2]': [i32;_] | ||
1071 | [118; 119) '2': i32 | ||
1072 | [131; 132) '_': i32 | ||
1073 | [136; 140) '&[3]': &[i32;_] | ||
1074 | [137; 140) '[3]': [i32;_] | ||
1075 | [138; 139) '3': i32 | ||
1076 | "### | ||
1077 | ); | ||
1078 | } | ||
1079 | |||
1080 | #[test] | ||
922 | fn bug_484() { | 1081 | fn bug_484() { |
923 | assert_snapshot!( | 1082 | assert_snapshot!( |
924 | infer(r#" | 1083 | infer(r#" |
@@ -3474,7 +3633,7 @@ trait Deref { | |||
3474 | } | 3633 | } |
3475 | 3634 | ||
3476 | struct Arc<T>; | 3635 | struct Arc<T>; |
3477 | impl<T: ?Sized> Deref for Arc<T> { | 3636 | impl<T> Deref for Arc<T> { |
3478 | type Target = T; | 3637 | type Target = T; |
3479 | } | 3638 | } |
3480 | 3639 | ||