aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authoruHOOCCOOHu <[email protected]>2019-09-12 19:59:21 +0100
committeruHOOCCOOHu <[email protected]>2019-09-25 23:04:39 +0100
commit4bb66df6de6a832f53f09128ea038fc1c0068515 (patch)
treedc0509537b1f1cb0c61e0719d4d6f3317e09cc9f /crates/ra_hir/src
parent5205c84ec7d6284b258e66a06c3e330c3f9fdd88 (diff)
Support basic implicit type coerce
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/ty/infer.rs254
-rw-r--r--crates/ra_hir/src/ty/tests.rs271
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
193macro_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
193impl<'a, D: HirDatabase> InferenceContext<'a, D> { 202impl<'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, &param_ty);
1331 } 1447 }
1332 } 1448 }
1333 } 1449 }
@@ -1517,37 +1633,3 @@ mod diagnostics {
1517 } 1633 }
1518 } 1634 }
1519} 1635}
1520
1521fn is_never(ty: &Ty) -> bool {
1522 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) = ty {
1523 true
1524 } else {
1525 false
1526 }
1527}
1528
1529fn 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"]
808pub trait Deref { 808pub 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
813struct A<T>(T); 813struct A<T>(T);
814 814
815impl<T: Copy> A<T> { 815impl<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
830fn test() { 830fn 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"]
866pub trait Deref { 867pub 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
871struct A<T>(*mut T); 872struct A<T>(*mut T);
872 873
873impl<T: Copy> A<T> { 874impl<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
888fn test(a: A<i32>) { 889fn 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]
927fn infer_if_coerce() {
928 assert_snapshot!(
929 infer(r#"
930fn foo<T>(x: &[T]) -> &[T] { loop {} }
931fn 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]
963fn infer_if_else_coerce() {
964 assert_snapshot!(
965 infer(r#"
966fn foo<T>(x: &[T]) -> &[T] { loop {} }
967fn 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]
999fn infer_match_first_coerce() {
1000 assert_snapshot!(
1001 infer(r#"
1002fn foo<T>(x: &[T]) -> &[T] { loop {} }
1003fn 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]
1040fn infer_match_second_coerce() {
1041 assert_snapshot!(
1042 infer(r#"
1043fn foo<T>(x: &[T]) -> &[T] { loop {} }
1044fn 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]
922fn bug_484() { 1081fn bug_484() {
923 assert_snapshot!( 1082 assert_snapshot!(
924 infer(r#" 1083 infer(r#"
@@ -3474,7 +3633,7 @@ trait Deref {
3474} 3633}
3475 3634
3476struct Arc<T>; 3635struct Arc<T>;
3477impl<T: ?Sized> Deref for Arc<T> { 3636impl<T> Deref for Arc<T> {
3478 type Target = T; 3637 type Target = T;
3479} 3638}
3480 3639