]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_ty/src/tests/coercion.rs
Merge #11842
[rust.git] / crates / hir_ty / src / tests / coercion.rs
index 6c57bf697d81de3d77140b2535e5dd419fae5b11..268faf8cb3a0643a7fb842f604af28213673393b 100644 (file)
@@ -2,12 +2,10 @@
 
 #[test]
 fn block_expr_type_mismatch() {
-    // FIXME fix double type mismatch
     check(
         r"
 fn test() {
     let a: i32 = { 1i64 };
-              // ^^^^^^^^ expected i32, got i64
                 // ^^^^ expected i32, got i64
 }
         ",
@@ -46,12 +44,14 @@ fn test2() {
 
 #[test]
 fn let_stmt_coerce() {
-    check_no_mismatches(
+    check(
         r"
 //- minicore: coerce_unsized
 fn test() {
     let x: &[isize] = &[1];
+                   // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
     let x: *const [isize] = &[1];
+                         // ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
 }
 ",
     );
@@ -96,6 +96,7 @@ fn foo<T>(x: &[T]) -> &[T] { x }
 fn test() {
     let x = if true {
         foo(&[1])
+         // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
     } else {
         &[1]
     };
@@ -130,6 +131,7 @@ fn foo<T>(x: &[T]) -> &[T] { x }
 fn test(i: i32) {
     let x = match i {
         2 => foo(&[2]),
+              // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
         1 => &[1],
         _ => &[3],
     };
@@ -144,6 +146,7 @@ fn match_second_coerce() {
         r#"
 //- minicore: coerce_unsized
 fn foo<T>(x: &[T]) -> &[T] { loop {} }
+                          // ^^^^^^^ adjustments: NeverToAny
 fn test(i: i32) {
     let x = match i {
         1 => &[1],
@@ -168,9 +171,12 @@ fn test() {
         2 => t as &i32,
            //^^^^^^^^^ expected *mut i32, got &i32
         _ => t as *const i32,
+          // ^^^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer)
+
     };
     x;
   //^ type: *const i32
+
 }
         ",
     );
@@ -228,11 +234,51 @@ fn takes_ref_str(x: &str) {}
 fn returns_string() -> String { loop {} }
 fn test() {
     takes_ref_str(&{ returns_string() });
+               // ^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(None), Deref(Some(OverloadedDeref(Not))), Borrow(Ref(Not))
 }
 "#,
     );
 }
 
+#[test]
+fn coerce_autoderef_implication_1() {
+    check_no_mismatches(
+        r"
+//- minicore: deref
+struct Foo<T>;
+impl core::ops::Deref for Foo<u32> { type Target = (); }
+
+fn takes_ref_foo<T>(x: &Foo<T>) {}
+fn test() {
+    let foo = Foo;
+      //^^^ type: Foo<{unknown}>
+    takes_ref_foo(&foo);
+
+    let foo = Foo;
+      //^^^ type: Foo<u32>
+    let _: &() = &foo;
+}",
+    );
+}
+
+#[test]
+fn coerce_autoderef_implication_2() {
+    check(
+        r"
+//- minicore: deref
+struct Foo<T>;
+impl core::ops::Deref for Foo<u32> { type Target = (); }
+
+fn takes_ref_foo<T>(x: &Foo<T>) {}
+fn test() {
+    let foo = Foo;
+      //^^^ type: Foo<{unknown}>
+    let _: &u32 = &Foo;
+                //^^^^ expected &u32, got &Foo<{unknown}>
+}",
+    );
+}
+
 #[test]
 fn closure_return_coerce() {
     check_no_mismatches(
@@ -248,6 +294,24 @@ fn foo() {
     );
 }
 
+#[test]
+fn assign_coerce() {
+    check_no_mismatches(
+        r"
+//- minicore: deref
+struct String;
+impl core::ops::Deref for String { type Target = str; }
+fn g(_text: &str) {}
+fn f(text: &str) {
+    let mut text = text;
+    let tmp = String;
+    text = &tmp;
+    g(text);
+}
+",
+    );
+}
+
 #[test]
 fn coerce_fn_item_to_fn_ptr() {
     check_no_mismatches(
@@ -255,6 +319,9 @@ fn coerce_fn_item_to_fn_ptr() {
 fn foo(x: u32) -> isize { 1 }
 fn test() {
     let f: fn(u32) -> isize = foo;
+                           // ^^^ adjustments: Pointer(ReifyFnPointer)
+    let f: unsafe fn(u32) -> isize = foo;
+                                  // ^^^ adjustments: Pointer(ReifyFnPointer)
 }",
     );
 }
@@ -378,7 +445,7 @@ fn test() {
     let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
                                    //^^^^^^^^^ expected [usize], got [usize; 3]
     let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
-                         //^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &Bar<[usize]>, got &Bar<[i32; 3]>
+                                       //^^^^^^^^^ expected [usize], got [usize; 3]
 }
 "#,
     );
@@ -386,15 +453,15 @@ fn test() {
 
 #[test]
 fn coerce_unsize_apit() {
-    // FIXME: #8984
     check(
         r#"
 //- minicore: coerce_unsized
 trait Foo {}
 
-fn test(f: impl Foo) {
+fn test(f: impl Foo, g: &(impl Foo + ?Sized)) {
     let _: &dyn Foo = &f;
-                    //^^ expected &dyn Foo, got &impl Foo
+    let _: &dyn Foo = g;
+                    //^ expected &dyn Foo, got &impl Foo + ?Sized
 }
         "#,
     );
@@ -488,7 +555,7 @@ fn main() {
 }
 
 #[test]
-fn coerce_unsize_expected_type() {
+fn coerce_unsize_expected_type_1() {
     check_no_mismatches(
         r#"
 //- minicore: coerce_unsized
@@ -508,6 +575,72 @@ fn main() {
     );
 }
 
+#[test]
+fn coerce_unsize_expected_type_2() {
+    check_no_mismatches(
+        r#"
+//- minicore: coerce_unsized
+struct InFile<T>;
+impl<T> InFile<T> {
+    fn with_value<U>(self, value: U) -> InFile<U> { InFile }
+}
+struct RecordField;
+trait AstNode {}
+impl AstNode for RecordField {}
+
+fn takes_dyn(it: InFile<&dyn AstNode>) {}
+
+fn test() {
+    let x: InFile<()> = InFile;
+    let n = &RecordField;
+    takes_dyn(x.with_value(n));
+}
+        "#,
+    );
+}
+
+#[test]
+fn coerce_unsize_expected_type_3() {
+    check_no_mismatches(
+        r#"
+//- minicore: coerce_unsized
+enum Option<T> { Some(T), None }
+struct RecordField;
+trait AstNode {}
+impl AstNode for RecordField {}
+
+fn takes_dyn(it: Option<&dyn AstNode>) {}
+
+fn test() {
+    let x: InFile<()> = InFile;
+    let n = &RecordField;
+    takes_dyn(Option::Some(n));
+}
+        "#,
+    );
+}
+
+#[test]
+fn coerce_unsize_expected_type_4() {
+    check_no_mismatches(
+        r#"
+//- minicore: coerce_unsized
+use core::{marker::Unsize, ops::CoerceUnsized};
+
+struct B<T: ?Sized>(*const T);
+impl<T: ?Sized> B<T> {
+    fn new(t: T) -> Self { B(&t) }
+}
+
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
+
+fn test() {
+    let _: B<[isize]> = B::new({ [1, 2, 3] });
+}
+        "#,
+    );
+}
+
 #[test]
 fn coerce_array_elems_lub() {
     check_no_mismatches(
@@ -521,3 +654,40 @@ fn test() {
         "#,
     );
 }
+
+#[test]
+fn coerce_type_var() {
+    check_types(
+        r#"
+//- minicore: from, coerce_unsized
+fn test() {
+    let x = ();
+    let _: &() = &x.into();
+}               //^^^^^^^^ ()
+"#,
+    )
+}
+
+#[test]
+fn coerce_overloaded_binary_op_rhs() {
+    check_types(
+        r#"
+//- minicore: deref, add
+
+struct String {}
+impl core::ops::Deref for String { type Target = str; }
+
+impl core::ops::Add<&str> for String {
+    type Output = String;
+}
+
+fn test() {
+    let s1 = String {};
+    let s2 = String {};
+    s1 + &s2;
+  //^^^^^^^^ String
+}
+
+        "#,
+    );
+}