diff options
| author | Matthew J Perez <matt@mperez.io> | 2022-12-11 02:49:07 -0500 |
|---|---|---|
| committer | Matthew J Perez <matt@mperez.io> | 2023-01-24 14:02:56 -0500 |
| commit | 1e22280f231e02b9ec8624e16b473b4082d7dfad (patch) | |
| tree | d8cd1c05e065926b604fcbb4f7290d06a68d09f2 /tests/ui/fn | |
| parent | c8e6a9e8b6251bbc8276cb78cabe1998deecbed7 (diff) | |
| download | rust-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.stderr | 1 | ||||
| -rw-r--r-- | tests/ui/fn/fn-item-type.rs | 37 | ||||
| -rw-r--r-- | tests/ui/fn/fn-item-type.stderr | 49 | ||||
| -rw-r--r-- | tests/ui/fn/fn-pointer-mismatch.rs | 56 | ||||
| -rw-r--r-- | tests/ui/fn/fn-pointer-mismatch.stderr | 81 |
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`. |
