about summary refs log tree commit diff
path: root/tests/ui/fn
diff options
context:
space:
mode:
authorMatthew J Perez <matt@mperez.io>2022-12-11 02:49:07 -0500
committerMatthew J Perez <matt@mperez.io>2023-01-24 14:02:56 -0500
commit1e22280f231e02b9ec8624e16b473b4082d7dfad (patch)
treed8cd1c05e065926b604fcbb4f7290d06a68d09f2 /tests/ui/fn
parentc8e6a9e8b6251bbc8276cb78cabe1998deecbed7 (diff)
downloadrust-1e22280f231e02b9ec8624e16b473b4082d7dfad.tar.gz
rust-1e22280f231e02b9ec8624e16b473b4082d7dfad.zip
Add suggestions for function pointers
- On compiler-error's suggestion of moving this lower down the stack,
along the path of `report_mismatched_types()`, which is used
by `rustc_hir_analysis` and `rustc_hir_typeck`.
- update ui tests, add test
- add suggestions for references to fn pointers
- modify `TypeErrCtxt::same_type_modulo_infer` to take `T: relate::Relate` instead of `Ty`
Diffstat (limited to 'tests/ui/fn')
-rw-r--r--tests/ui/fn/fn-compare-mismatch.stderr1
-rw-r--r--tests/ui/fn/fn-item-type.rs37
-rw-r--r--tests/ui/fn/fn-item-type.stderr49
-rw-r--r--tests/ui/fn/fn-pointer-mismatch.rs56
-rw-r--r--tests/ui/fn/fn-pointer-mismatch.stderr81
5 files changed, 176 insertions, 48 deletions
diff --git a/tests/ui/fn/fn-compare-mismatch.stderr b/tests/ui/fn/fn-compare-mismatch.stderr
index df838cb1181..f247ff6cf3f 100644
--- a/tests/ui/fn/fn-compare-mismatch.stderr
+++ b/tests/ui/fn/fn-compare-mismatch.stderr
@@ -19,6 +19,7 @@ LL |     let x = f == g;
    |
    = note: expected fn item `fn() {f}`
               found fn item `fn() {g}`
+   = note: different fn items have unique types, even if their signatures are the same
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/fn/fn-item-type.rs b/tests/ui/fn/fn-item-type.rs
index 1831e6cbf10..b6ebc867d28 100644
--- a/tests/ui/fn/fn-item-type.rs
+++ b/tests/ui/fn/fn-item-type.rs
@@ -1,13 +1,22 @@
 // Test that the types of distinct fn items are not compatible by
 // default. See also `run-pass/fn-item-type-*.rs`.
 
-fn foo<T>(x: isize) -> isize { x * 2 }
-fn bar<T>(x: isize) -> isize { x * 4 }
+fn foo<T>(x: isize) -> isize {
+    x * 2
+}
+fn bar<T>(x: isize) -> isize {
+    x * 4
+}
 
-fn eq<T>(x: T, y: T) { }
+fn eq<T>(x: T, y: T) {}
 
-trait Foo { fn foo() { /* this is a default fn */ } }
-impl<T> Foo for T { /* `foo` is still default here */ }
+trait Foo {
+    fn foo() { /* this is a default fn */
+    }
+}
+impl<T> Foo for T {
+    /* `foo` is still default here */
+}
 
 fn main() {
     eq(foo::<u8>, bar::<u8>);
@@ -15,39 +24,29 @@ fn main() {
     //~| expected fn item `fn(_) -> _ {foo::<u8>}`
     //~| found fn item `fn(_) -> _ {bar::<u8>}`
     //~| expected fn item, found a different fn item
-    //~| different `fn` items always have unique types, even if their signatures are the same
-    //~| change the expected type to be function pointer
-    //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
+    //~| different fn items have unique types, even if their signatures are the same
 
     eq(foo::<u8>, foo::<i8>);
     //~^ ERROR mismatched types
     //~| expected `u8`, found `i8`
-    //~| different `fn` items always have unique types, even if their signatures are the same
-    //~| change the expected type to be function pointer
-    //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
+    //~| different fn items have unique types, even if their signatures are the same
 
     eq(bar::<String>, bar::<Vec<u8>>);
     //~^ ERROR mismatched types
     //~| found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
     //~| expected struct `String`, found struct `Vec`
-    //~| different `fn` items always have unique types, even if their signatures are the same
-    //~| change the expected type to be function pointer
-    //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
+    //~| different fn items have unique types, even if their signatures are the same
 
     // Make sure we distinguish between trait methods correctly.
     eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
     //~^ ERROR mismatched types
     //~| expected `u8`, found `u16`
-    //~| different `fn` items always have unique types, even if their signatures are the same
-    //~| change the expected type to be function pointer
-    //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
+    //~| different fn items have unique types, even if their signatures are the same
 
     eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
     //~^ ERROR mismatched types
     //~| found fn pointer `fn(_) -> _`
     //~| expected fn item, found fn pointer
-    //~| change the expected type to be function pointer
-    //~| if the expected type is due to type inference, cast the expected `fn` to a function pointer
 
     eq(foo::<u8> as fn(isize) -> isize, bar::<u8>); // ok!
 }
diff --git a/tests/ui/fn/fn-item-type.stderr b/tests/ui/fn/fn-item-type.stderr
index f03a47d5c2c..cb1b88c7ab8 100644
--- a/tests/ui/fn/fn-item-type.stderr
+++ b/tests/ui/fn/fn-item-type.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/fn-item-type.rs:13:19
+  --> $DIR/fn-item-type.rs:22:19
    |
 LL |     eq(foo::<u8>, bar::<u8>);
    |     --            ^^^^^^^^^ expected fn item, found a different fn item
@@ -8,17 +8,15 @@ LL |     eq(foo::<u8>, bar::<u8>);
    |
    = note: expected fn item `fn(_) -> _ {foo::<u8>}`
               found fn item `fn(_) -> _ {bar::<u8>}`
-   = note: different `fn` items always have unique types, even if their signatures are the same
-   = help: change the expected type to be function pointer `fn(isize) -> isize`
-   = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+   = note: different fn items have unique types, even if their signatures are the same
 note: function defined here
-  --> $DIR/fn-item-type.rs:7:4
+  --> $DIR/fn-item-type.rs:11:4
    |
-LL | fn eq<T>(x: T, y: T) { }
+LL | fn eq<T>(x: T, y: T) {}
    |    ^^          ----
 
 error[E0308]: mismatched types
-  --> $DIR/fn-item-type.rs:22:19
+  --> $DIR/fn-item-type.rs:29:19
    |
 LL |     eq(foo::<u8>, foo::<i8>);
    |     --            ^^^^^^^^^ expected `u8`, found `i8`
@@ -27,17 +25,15 @@ LL |     eq(foo::<u8>, foo::<i8>);
    |
    = note: expected fn item `fn(_) -> _ {foo::<u8>}`
               found fn item `fn(_) -> _ {foo::<i8>}`
-   = note: different `fn` items always have unique types, even if their signatures are the same
-   = help: change the expected type to be function pointer `fn(isize) -> isize`
-   = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+   = note: different fn items have unique types, even if their signatures are the same
 note: function defined here
-  --> $DIR/fn-item-type.rs:7:4
+  --> $DIR/fn-item-type.rs:11:4
    |
-LL | fn eq<T>(x: T, y: T) { }
+LL | fn eq<T>(x: T, y: T) {}
    |    ^^          ----
 
 error[E0308]: mismatched types
-  --> $DIR/fn-item-type.rs:29:23
+  --> $DIR/fn-item-type.rs:34:23
    |
 LL |     eq(bar::<String>, bar::<Vec<u8>>);
    |     --                ^^^^^^^^^^^^^^ expected struct `String`, found struct `Vec`
@@ -46,17 +42,15 @@ LL |     eq(bar::<String>, bar::<Vec<u8>>);
    |
    = note: expected fn item `fn(_) -> _ {bar::<String>}`
               found fn item `fn(_) -> _ {bar::<Vec<u8>>}`
-   = note: different `fn` items always have unique types, even if their signatures are the same
-   = help: change the expected type to be function pointer `fn(isize) -> isize`
-   = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `bar::<String> as fn(isize) -> isize`
+   = note: different fn items have unique types, even if their signatures are the same
 note: function defined here
-  --> $DIR/fn-item-type.rs:7:4
+  --> $DIR/fn-item-type.rs:11:4
    |
-LL | fn eq<T>(x: T, y: T) { }
+LL | fn eq<T>(x: T, y: T) {}
    |    ^^          ----
 
 error[E0308]: mismatched types
-  --> $DIR/fn-item-type.rs:38:26
+  --> $DIR/fn-item-type.rs:41:26
    |
 LL |     eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
    |     --                   ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
@@ -65,17 +59,15 @@ LL |     eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
    |
    = note: expected fn item `fn() {<u8 as Foo>::foo}`
               found fn item `fn() {<u16 as Foo>::foo}`
-   = note: different `fn` items always have unique types, even if their signatures are the same
-   = help: change the expected type to be function pointer `fn()`
-   = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `<u8 as Foo>::foo as fn()`
+   = note: different fn items have unique types, even if their signatures are the same
 note: function defined here
-  --> $DIR/fn-item-type.rs:7:4
+  --> $DIR/fn-item-type.rs:11:4
    |
-LL | fn eq<T>(x: T, y: T) { }
+LL | fn eq<T>(x: T, y: T) {}
    |    ^^          ----
 
 error[E0308]: mismatched types
-  --> $DIR/fn-item-type.rs:45:19
+  --> $DIR/fn-item-type.rs:46:19
    |
 LL |     eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
    |     --            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer
@@ -84,12 +76,11 @@ LL |     eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
    |
    = note: expected fn item `fn(_) -> _ {foo::<u8>}`
            found fn pointer `fn(_) -> _`
-   = help: change the expected type to be function pointer `fn(isize) -> isize`
-   = help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `foo::<u8> as fn(isize) -> isize`
+   = note: fn items are distinct from fn pointers
 note: function defined here
-  --> $DIR/fn-item-type.rs:7:4
+  --> $DIR/fn-item-type.rs:11:4
    |
-LL | fn eq<T>(x: T, y: T) { }
+LL | fn eq<T>(x: T, y: T) {}
    |    ^^          ----
 
 error: aborting due to 5 previous errors
diff --git a/tests/ui/fn/fn-pointer-mismatch.rs b/tests/ui/fn/fn-pointer-mismatch.rs
new file mode 100644
index 00000000000..0597478cb42
--- /dev/null
+++ b/tests/ui/fn/fn-pointer-mismatch.rs
@@ -0,0 +1,56 @@
+fn foo(x: u32) -> u32 {
+    x * 2
+}
+
+fn bar(x: u32) -> u32 {
+    x * 3
+}
+
+// original example from Issue #102608
+fn foobar(n: u32) -> u32 {
+    let g = if n % 2 == 0 { &foo } else { &bar };
+    //~^ ERROR `if` and `else` have incompatible types
+    //~| different fn items have unique types, even if their signatures are the same
+    g(n)
+}
+
+fn main() {
+    assert_eq!(foobar(7), 21);
+    assert_eq!(foobar(8), 16);
+
+    // general mismatch of fn item types
+    let mut a = foo;
+    a = bar;
+    //~^ ERROR mismatched types
+    //~| expected fn item `fn(_) -> _ {foo}`
+    //~| found fn item `fn(_) -> _ {bar}`
+    //~| different fn items have unique types, even if their signatures are the same
+
+    // display note even when boxed
+    let mut b = Box::new(foo);
+    b = Box::new(bar);
+    //~^ ERROR mismatched types
+    //~| different fn items have unique types, even if their signatures are the same
+
+    // suggest removing reference
+    let c: fn(u32) -> u32 = &foo;
+    //~^ ERROR mismatched types
+    //~| expected fn pointer `fn(u32) -> u32`
+    //~| found reference `&fn(u32) -> u32 {foo}`
+
+    // suggest using reference
+    let d: &fn(u32) -> u32 = foo;
+    //~^ ERROR mismatched types
+    //~| expected reference `&fn(u32) -> u32`
+    //~| found fn item `fn(u32) -> u32 {foo}`
+
+    // suggest casting with reference
+    let e: &fn(u32) -> u32 = &foo;
+    //~^ ERROR mismatched types
+    //~| expected reference `&fn(u32) -> u32`
+    //~| found reference `&fn(u32) -> u32 {foo}`
+
+    // OK
+    let mut z: fn(u32) -> u32 = foo as fn(u32) -> u32;
+    z = bar;
+}
diff --git a/tests/ui/fn/fn-pointer-mismatch.stderr b/tests/ui/fn/fn-pointer-mismatch.stderr
new file mode 100644
index 00000000000..2dc0710e27e
--- /dev/null
+++ b/tests/ui/fn/fn-pointer-mismatch.stderr
@@ -0,0 +1,81 @@
+error[E0308]: `if` and `else` have incompatible types
+  --> $DIR/fn-pointer-mismatch.rs:11:43
+   |
+LL |     let g = if n % 2 == 0 { &foo } else { &bar };
+   |                             ----          ^^^^ expected fn item, found a different fn item
+   |                             |
+   |                             expected because of this
+   |
+   = note: expected reference `&fn(u32) -> u32 {foo}`
+              found reference `&fn(u32) -> u32 {bar}`
+   = note: different fn items have unique types, even if their signatures are the same
+
+error[E0308]: mismatched types
+  --> $DIR/fn-pointer-mismatch.rs:23:9
+   |
+LL |     let mut a = foo;
+   |                 --- expected due to this value
+LL |     a = bar;
+   |         ^^^ expected fn item, found a different fn item
+   |
+   = note: expected fn item `fn(_) -> _ {foo}`
+              found fn item `fn(_) -> _ {bar}`
+   = note: different fn items have unique types, even if their signatures are the same
+
+error[E0308]: mismatched types
+  --> $DIR/fn-pointer-mismatch.rs:31:18
+   |
+LL |     b = Box::new(bar);
+   |         -------- ^^^ expected fn item, found a different fn item
+   |         |
+   |         arguments to this function are incorrect
+   |
+   = note: expected fn item `fn(_) -> _ {foo}`
+              found fn item `fn(_) -> _ {bar}`
+   = note: different fn items have unique types, even if their signatures are the same
+note: associated function defined here
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+
+error[E0308]: mismatched types
+  --> $DIR/fn-pointer-mismatch.rs:36:29
+   |
+LL |     let c: fn(u32) -> u32 = &foo;
+   |            --------------   ^^^^
+   |            |                |
+   |            |                expected fn pointer, found reference
+   |            |                help: consider removing the reference: `foo`
+   |            expected due to this
+   |
+   = note: expected fn pointer `fn(u32) -> u32`
+               found reference `&fn(u32) -> u32 {foo}`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-pointer-mismatch.rs:42:30
+   |
+LL |     let d: &fn(u32) -> u32 = foo;
+   |            ---------------   ^^^
+   |            |                 |
+   |            |                 expected `&fn(u32) -> u32`, found fn item
+   |            |                 help: consider using a reference: `&foo`
+   |            expected due to this
+   |
+   = note: expected reference `&fn(u32) -> u32`
+                found fn item `fn(u32) -> u32 {foo}`
+
+error[E0308]: mismatched types
+  --> $DIR/fn-pointer-mismatch.rs:48:30
+   |
+LL |     let e: &fn(u32) -> u32 = &foo;
+   |            ---------------   ^^^^
+   |            |                 |
+   |            |                 expected fn pointer, found fn item
+   |            |                 help: consider casting to a fn pointer: `&(foo as fn(u32) -> u32)`
+   |            expected due to this
+   |
+   = note: expected reference `&fn(u32) -> u32`
+              found reference `&fn(u32) -> u32 {foo}`
+   = note: fn items are distinct from fn pointers
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.