summaryrefslogtreecommitdiffstats
path: root/tests/ui/fn
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/fn')
-rw-r--r--tests/ui/fn/bad-main.rs1
-rw-r--r--tests/ui/fn/bad-main.stderr12
-rw-r--r--tests/ui/fn/dyn-fn-alignment.rs23
-rw-r--r--tests/ui/fn/expr-fn-panic.rs11
-rw-r--r--tests/ui/fn/expr-fn.rs62
-rw-r--r--tests/ui/fn/fn-bad-block-type.rs5
-rw-r--r--tests/ui/fn/fn-bad-block-type.stderr11
-rw-r--r--tests/ui/fn/fn-closure-mutable-capture.rs12
-rw-r--r--tests/ui/fn/fn-closure-mutable-capture.stderr15
-rw-r--r--tests/ui/fn/fn-compare-mismatch.rs7
-rw-r--r--tests/ui/fn/fn-compare-mismatch.stderr26
-rw-r--r--tests/ui/fn/fn-item-type.rs53
-rw-r--r--tests/ui/fn/fn-item-type.stderr97
-rw-r--r--tests/ui/fn/fn-recover-return-sign.fixed28
-rw-r--r--tests/ui/fn/fn-recover-return-sign.rs28
-rw-r--r--tests/ui/fn/fn-recover-return-sign.stderr26
-rw-r--r--tests/ui/fn/fn-recover-return-sign2.rs8
-rw-r--r--tests/ui/fn/fn-recover-return-sign2.stderr14
-rw-r--r--tests/ui/fn/fn-trait-formatting.rs21
-rw-r--r--tests/ui/fn/fn-trait-formatting.stderr60
-rw-r--r--tests/ui/fn/fun-call-variants.rs12
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type-2.rs23
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr17
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type-3.rs22
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type-4.rs24
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr14
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs23
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr19
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type.rs23
-rw-r--r--tests/ui/fn/implied-bounds-unnorm-associated-type.stderr14
-rw-r--r--tests/ui/fn/issue-3044.rs6
-rw-r--r--tests/ui/fn/issue-3044.stderr21
-rw-r--r--tests/ui/fn/issue-3904.rs25
-rw-r--r--tests/ui/fn/issue-80179.rs27
-rw-r--r--tests/ui/fn/issue-80179.stderr23
-rw-r--r--tests/ui/fn/keyword-order.rs6
-rw-r--r--tests/ui/fn/keyword-order.stderr16
-rw-r--r--tests/ui/fn/nested-function-names-issue-8587.rs42
-rw-r--r--tests/ui/fn/signature-error-reporting-under-verbose.rs15
-rw-r--r--tests/ui/fn/signature-error-reporting-under-verbose.stderr19
-rw-r--r--tests/ui/fn/suggest-return-closure.rs34
-rw-r--r--tests/ui/fn/suggest-return-closure.stderr36
-rw-r--r--tests/ui/fn/suggest-return-future.rs23
-rw-r--r--tests/ui/fn/suggest-return-future.stderr21
44 files changed, 1025 insertions, 0 deletions
diff --git a/tests/ui/fn/bad-main.rs b/tests/ui/fn/bad-main.rs
new file mode 100644
index 000000000..751159961
--- /dev/null
+++ b/tests/ui/fn/bad-main.rs
@@ -0,0 +1 @@
+fn main(x: isize) { } //~ ERROR: `main` function has wrong type [E0580]
diff --git a/tests/ui/fn/bad-main.stderr b/tests/ui/fn/bad-main.stderr
new file mode 100644
index 000000000..675b66d05
--- /dev/null
+++ b/tests/ui/fn/bad-main.stderr
@@ -0,0 +1,12 @@
+error[E0580]: `main` function has wrong type
+ --> $DIR/bad-main.rs:1:1
+ |
+LL | fn main(x: isize) { }
+ | ^^^^^^^^^^^^^^^^^ incorrect number of function parameters
+ |
+ = note: expected fn pointer `fn()`
+ found fn pointer `fn(isize)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0580`.
diff --git a/tests/ui/fn/dyn-fn-alignment.rs b/tests/ui/fn/dyn-fn-alignment.rs
new file mode 100644
index 000000000..cedfd1cf2
--- /dev/null
+++ b/tests/ui/fn/dyn-fn-alignment.rs
@@ -0,0 +1,23 @@
+// run-pass
+
+#![allow(dead_code)]
+#[repr(align(256))]
+struct A {
+ v: u8,
+}
+
+impl A {
+ fn f(&self) -> *const A {
+ self
+ }
+}
+
+fn f2(v: u8) -> Box<dyn FnOnce() -> *const A> {
+ let a = A { v };
+ Box::new(move || a.f())
+}
+
+fn main() {
+ let addr = f2(0)();
+ assert_eq!(addr as usize % 256, 0, "addr: {:?}", addr);
+}
diff --git a/tests/ui/fn/expr-fn-panic.rs b/tests/ui/fn/expr-fn-panic.rs
new file mode 100644
index 000000000..123b57f97
--- /dev/null
+++ b/tests/ui/fn/expr-fn-panic.rs
@@ -0,0 +1,11 @@
+// run-fail
+// error-pattern:explicit panic
+// ignore-emscripten no processes
+
+fn f() -> ! {
+ panic!()
+}
+
+fn main() {
+ f();
+}
diff --git a/tests/ui/fn/expr-fn.rs b/tests/ui/fn/expr-fn.rs
new file mode 100644
index 000000000..253cbfd5d
--- /dev/null
+++ b/tests/ui/fn/expr-fn.rs
@@ -0,0 +1,62 @@
+// run-pass
+#![allow(unused_braces)]
+
+fn test_int() {
+ fn f() -> isize { 10 }
+ assert_eq!(f(), 10);
+}
+
+fn test_vec() {
+ fn f() -> Vec<isize> { vec![10, 11] }
+ let vect = f();
+ assert_eq!(vect[1], 11);
+}
+
+fn test_generic() {
+ fn f<T>(t: T) -> T { t }
+ assert_eq!(f(10), 10);
+}
+
+fn test_alt() {
+ fn f() -> isize { match true { false => { 10 } true => { 20 } } }
+ assert_eq!(f(), 20);
+}
+
+fn test_if() {
+ fn f() -> isize { if true { 10 } else { 20 } }
+ assert_eq!(f(), 10);
+}
+
+fn test_block() {
+ fn f() -> isize { { 10 } }
+ assert_eq!(f(), 10);
+}
+
+fn test_ret() {
+ fn f() -> isize {
+ return 10 // no semi
+
+ }
+ assert_eq!(f(), 10);
+}
+
+
+// From issue #372
+fn test_372() {
+ fn f() -> isize { let x = { 3 }; x }
+ assert_eq!(f(), 3);
+}
+
+fn test_nil() { () }
+
+pub fn main() {
+ test_int();
+ test_vec();
+ test_generic();
+ test_alt();
+ test_if();
+ test_block();
+ test_ret();
+ test_372();
+ test_nil();
+}
diff --git a/tests/ui/fn/fn-bad-block-type.rs b/tests/ui/fn/fn-bad-block-type.rs
new file mode 100644
index 000000000..01dcff058
--- /dev/null
+++ b/tests/ui/fn/fn-bad-block-type.rs
@@ -0,0 +1,5 @@
+// error-pattern:mismatched types
+
+fn f() -> isize { true }
+
+fn main() { }
diff --git a/tests/ui/fn/fn-bad-block-type.stderr b/tests/ui/fn/fn-bad-block-type.stderr
new file mode 100644
index 000000000..13ebfd1e2
--- /dev/null
+++ b/tests/ui/fn/fn-bad-block-type.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+ --> $DIR/fn-bad-block-type.rs:3:19
+ |
+LL | fn f() -> isize { true }
+ | ----- ^^^^ expected `isize`, found `bool`
+ | |
+ | expected `isize` because of return type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/fn/fn-closure-mutable-capture.rs b/tests/ui/fn/fn-closure-mutable-capture.rs
new file mode 100644
index 000000000..97141886f
--- /dev/null
+++ b/tests/ui/fn/fn-closure-mutable-capture.rs
@@ -0,0 +1,12 @@
+pub fn bar<F: Fn()>(_f: F) {} //~ NOTE change this to accept `FnMut` instead of `Fn`
+
+pub fn foo() {
+ let mut x = 0;
+ bar(move || x = 1);
+ //~^ ERROR cannot assign to `x`, as it is a captured variable in a `Fn` closure
+ //~| NOTE cannot assign
+ //~| NOTE expects `Fn` instead of `FnMut`
+ //~| NOTE in this closure
+}
+
+fn main() {}
diff --git a/tests/ui/fn/fn-closure-mutable-capture.stderr b/tests/ui/fn/fn-closure-mutable-capture.stderr
new file mode 100644
index 000000000..03e3d545a
--- /dev/null
+++ b/tests/ui/fn/fn-closure-mutable-capture.stderr
@@ -0,0 +1,15 @@
+error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
+ --> $DIR/fn-closure-mutable-capture.rs:5:17
+ |
+LL | pub fn bar<F: Fn()>(_f: F) {}
+ | - change this to accept `FnMut` instead of `Fn`
+...
+LL | bar(move || x = 1);
+ | --- ------- ^^^^^ cannot assign
+ | | |
+ | | in this closure
+ | expects `Fn` instead of `FnMut`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/tests/ui/fn/fn-compare-mismatch.rs b/tests/ui/fn/fn-compare-mismatch.rs
new file mode 100644
index 000000000..d734d54e8
--- /dev/null
+++ b/tests/ui/fn/fn-compare-mismatch.rs
@@ -0,0 +1,7 @@
+fn main() {
+ fn f() { }
+ fn g() { }
+ let x = f == g;
+ //~^ ERROR binary operation `==` cannot be applied
+ //~| ERROR mismatched types
+}
diff --git a/tests/ui/fn/fn-compare-mismatch.stderr b/tests/ui/fn/fn-compare-mismatch.stderr
new file mode 100644
index 000000000..df838cb11
--- /dev/null
+++ b/tests/ui/fn/fn-compare-mismatch.stderr
@@ -0,0 +1,26 @@
+error[E0369]: binary operation `==` cannot be applied to type `fn() {f}`
+ --> $DIR/fn-compare-mismatch.rs:4:15
+ |
+LL | let x = f == g;
+ | - ^^ - fn() {g}
+ | |
+ | fn() {f}
+ |
+help: use parentheses to call these
+ |
+LL | let x = f() == g();
+ | ++ ++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-compare-mismatch.rs:4:18
+ |
+LL | let x = f == g;
+ | ^ expected fn item, found a different fn item
+ |
+ = note: expected fn item `fn() {f}`
+ found fn item `fn() {g}`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0369.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/fn/fn-item-type.rs b/tests/ui/fn/fn-item-type.rs
new file mode 100644
index 000000000..1831e6cbf
--- /dev/null
+++ b/tests/ui/fn/fn-item-type.rs
@@ -0,0 +1,53 @@
+// 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 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 */ }
+
+fn main() {
+ eq(foo::<u8>, bar::<u8>);
+ //~^ ERROR mismatched types
+ //~| 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
+
+ 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
+
+ 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
+
+ // 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
+
+ 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
new file mode 100644
index 000000000..f03a47d5c
--- /dev/null
+++ b/tests/ui/fn/fn-item-type.stderr
@@ -0,0 +1,97 @@
+error[E0308]: mismatched types
+ --> $DIR/fn-item-type.rs:13:19
+ |
+LL | eq(foo::<u8>, bar::<u8>);
+ | -- ^^^^^^^^^ expected fn item, found a different fn item
+ | |
+ | arguments to this function are incorrect
+ |
+ = 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: function defined here
+ --> $DIR/fn-item-type.rs:7:4
+ |
+LL | fn eq<T>(x: T, y: T) { }
+ | ^^ ----
+
+error[E0308]: mismatched types
+ --> $DIR/fn-item-type.rs:22:19
+ |
+LL | eq(foo::<u8>, foo::<i8>);
+ | -- ^^^^^^^^^ expected `u8`, found `i8`
+ | |
+ | arguments to this function are incorrect
+ |
+ = 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: function defined here
+ --> $DIR/fn-item-type.rs:7:4
+ |
+LL | fn eq<T>(x: T, y: T) { }
+ | ^^ ----
+
+error[E0308]: mismatched types
+ --> $DIR/fn-item-type.rs:29:23
+ |
+LL | eq(bar::<String>, bar::<Vec<u8>>);
+ | -- ^^^^^^^^^^^^^^ expected struct `String`, found struct `Vec`
+ | |
+ | arguments to this function are incorrect
+ |
+ = 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: function defined here
+ --> $DIR/fn-item-type.rs:7:4
+ |
+LL | fn eq<T>(x: T, y: T) { }
+ | ^^ ----
+
+error[E0308]: mismatched types
+ --> $DIR/fn-item-type.rs:38:26
+ |
+LL | eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
+ | -- ^^^^^^^^^^^^^^^^^ expected `u8`, found `u16`
+ | |
+ | arguments to this function are incorrect
+ |
+ = 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: function defined here
+ --> $DIR/fn-item-type.rs:7:4
+ |
+LL | fn eq<T>(x: T, y: T) { }
+ | ^^ ----
+
+error[E0308]: mismatched types
+ --> $DIR/fn-item-type.rs:45:19
+ |
+LL | eq(foo::<u8>, bar::<u8> as fn(isize) -> isize);
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn item, found fn pointer
+ | |
+ | arguments to this function are incorrect
+ |
+ = 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: function defined here
+ --> $DIR/fn-item-type.rs:7:4
+ |
+LL | fn eq<T>(x: T, y: T) { }
+ | ^^ ----
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/fn/fn-recover-return-sign.fixed b/tests/ui/fn/fn-recover-return-sign.fixed
new file mode 100644
index 000000000..076be6a35
--- /dev/null
+++ b/tests/ui/fn/fn-recover-return-sign.fixed
@@ -0,0 +1,28 @@
+// run-rustfix
+#![allow(unused)]
+fn a() -> usize { 0 }
+//~^ ERROR return types are denoted using `->`
+
+fn b()-> usize { 0 }
+//~^ ERROR return types are denoted using `->`
+
+fn bar(_: u32) {}
+
+fn baz() -> *const dyn Fn(u32) { unimplemented!() }
+
+fn foo() {
+ match () {
+ _ if baz() == &bar as &dyn Fn(u32) => (),
+ () => (),
+ }
+}
+
+fn main() {
+ let foo = |a: bool| -> bool { a };
+ //~^ ERROR return types are denoted using `->`
+ dbg!(foo(false));
+
+ let bar = |a: bool|-> bool { a };
+ //~^ ERROR return types are denoted using `->`
+ dbg!(bar(false));
+}
diff --git a/tests/ui/fn/fn-recover-return-sign.rs b/tests/ui/fn/fn-recover-return-sign.rs
new file mode 100644
index 000000000..0656023c0
--- /dev/null
+++ b/tests/ui/fn/fn-recover-return-sign.rs
@@ -0,0 +1,28 @@
+// run-rustfix
+#![allow(unused)]
+fn a() => usize { 0 }
+//~^ ERROR return types are denoted using `->`
+
+fn b(): usize { 0 }
+//~^ ERROR return types are denoted using `->`
+
+fn bar(_: u32) {}
+
+fn baz() -> *const dyn Fn(u32) { unimplemented!() }
+
+fn foo() {
+ match () {
+ _ if baz() == &bar as &dyn Fn(u32) => (),
+ () => (),
+ }
+}
+
+fn main() {
+ let foo = |a: bool| => bool { a };
+ //~^ ERROR return types are denoted using `->`
+ dbg!(foo(false));
+
+ let bar = |a: bool|: bool { a };
+ //~^ ERROR return types are denoted using `->`
+ dbg!(bar(false));
+}
diff --git a/tests/ui/fn/fn-recover-return-sign.stderr b/tests/ui/fn/fn-recover-return-sign.stderr
new file mode 100644
index 000000000..983109730
--- /dev/null
+++ b/tests/ui/fn/fn-recover-return-sign.stderr
@@ -0,0 +1,26 @@
+error: return types are denoted using `->`
+ --> $DIR/fn-recover-return-sign.rs:3:8
+ |
+LL | fn a() => usize { 0 }
+ | ^^ help: use `->` instead
+
+error: return types are denoted using `->`
+ --> $DIR/fn-recover-return-sign.rs:6:7
+ |
+LL | fn b(): usize { 0 }
+ | ^ help: use `->` instead
+
+error: return types are denoted using `->`
+ --> $DIR/fn-recover-return-sign.rs:21:25
+ |
+LL | let foo = |a: bool| => bool { a };
+ | ^^ help: use `->` instead
+
+error: return types are denoted using `->`
+ --> $DIR/fn-recover-return-sign.rs:25:24
+ |
+LL | let bar = |a: bool|: bool { a };
+ | ^ help: use `->` instead
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/fn/fn-recover-return-sign2.rs b/tests/ui/fn/fn-recover-return-sign2.rs
new file mode 100644
index 000000000..31f56565c
--- /dev/null
+++ b/tests/ui/fn/fn-recover-return-sign2.rs
@@ -0,0 +1,8 @@
+// Separate test file because `Fn() => bool` isn't getting fixed and rustfix complained that
+// even though a fix was applied the code was still incorrect
+
+fn foo() => impl Fn() => bool {
+ //~^ ERROR return types are denoted using `->`
+ //~| ERROR expected one of `+`, `->`, `::`, `where`, or `{`, found `=>`
+ unimplemented!()
+}
diff --git a/tests/ui/fn/fn-recover-return-sign2.stderr b/tests/ui/fn/fn-recover-return-sign2.stderr
new file mode 100644
index 000000000..25ee8dd0c
--- /dev/null
+++ b/tests/ui/fn/fn-recover-return-sign2.stderr
@@ -0,0 +1,14 @@
+error: return types are denoted using `->`
+ --> $DIR/fn-recover-return-sign2.rs:4:10
+ |
+LL | fn foo() => impl Fn() => bool {
+ | ^^ help: use `->` instead
+
+error: expected one of `+`, `->`, `::`, `where`, or `{`, found `=>`
+ --> $DIR/fn-recover-return-sign2.rs:4:23
+ |
+LL | fn foo() => impl Fn() => bool {
+ | ^^ expected one of `+`, `->`, `::`, `where`, or `{`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/fn/fn-trait-formatting.rs b/tests/ui/fn/fn-trait-formatting.rs
new file mode 100644
index 000000000..636ac7107
--- /dev/null
+++ b/tests/ui/fn/fn-trait-formatting.rs
@@ -0,0 +1,21 @@
+fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
+
+
+
+fn main() {
+ let _: () = Box::new(|_: isize| {}) as Box<dyn FnOnce(isize)>;
+ //~^ ERROR mismatched types
+ //~| expected unit type `()`
+ //~| found struct `Box<dyn FnOnce(isize)>`
+ let _: () = Box::new(|_: isize, isize| {}) as Box<dyn Fn(isize, isize)>;
+ //~^ ERROR mismatched types
+ //~| expected unit type `()`
+ //~| found struct `Box<dyn Fn(isize, isize)>`
+ let _: () = Box::new(|| -> isize { unimplemented!() }) as Box<dyn FnMut() -> isize>;
+ //~^ ERROR mismatched types
+ //~| expected unit type `()`
+ //~| found struct `Box<dyn FnMut() -> isize>`
+
+ needs_fn(1);
+ //~^ ERROR expected a `Fn<(isize,)>` closure, found `{integer}`
+}
diff --git a/tests/ui/fn/fn-trait-formatting.stderr b/tests/ui/fn/fn-trait-formatting.stderr
new file mode 100644
index 000000000..2a674d3c1
--- /dev/null
+++ b/tests/ui/fn/fn-trait-formatting.stderr
@@ -0,0 +1,60 @@
+error[E0308]: mismatched types
+ --> $DIR/fn-trait-formatting.rs:6:17
+ |
+LL | let _: () = Box::new(|_: isize| {}) as Box<dyn FnOnce(isize)>;
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+ | |
+ | expected due to this
+ |
+ = note: expected unit type `()`
+ found struct `Box<dyn FnOnce(isize)>`
+help: use parentheses to call this trait object
+ |
+LL | let _: () = (Box::new(|_: isize| {}) as Box<dyn FnOnce(isize)>)(/* isize */);
+ | + ++++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-trait-formatting.rs:10:17
+ |
+LL | let _: () = Box::new(|_: isize, isize| {}) as Box<dyn Fn(isize, isize)>;
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+ | |
+ | expected due to this
+ |
+ = note: expected unit type `()`
+ found struct `Box<dyn Fn(isize, isize)>`
+help: use parentheses to call this trait object
+ |
+LL | let _: () = (Box::new(|_: isize, isize| {}) as Box<dyn Fn(isize, isize)>)(/* isize */, /* isize */);
+ | + +++++++++++++++++++++++++++
+
+error[E0308]: mismatched types
+ --> $DIR/fn-trait-formatting.rs:14:17
+ |
+LL | let _: () = Box::new(|| -> isize { unimplemented!() }) as Box<dyn FnMut() -> isize>;
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+ | |
+ | expected due to this
+ |
+ = note: expected unit type `()`
+ found struct `Box<dyn FnMut() -> isize>`
+
+error[E0277]: expected a `Fn<(isize,)>` closure, found `{integer}`
+ --> $DIR/fn-trait-formatting.rs:19:14
+ |
+LL | needs_fn(1);
+ | -------- ^ expected an `Fn<(isize,)>` closure, found `{integer}`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Fn<(isize,)>` is not implemented for `{integer}`
+note: required by a bound in `needs_fn`
+ --> $DIR/fn-trait-formatting.rs:1:31
+ |
+LL | fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
+ | ^^^^^^^^^^^^^^^^^^ required by this bound in `needs_fn`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/fn/fun-call-variants.rs b/tests/ui/fn/fun-call-variants.rs
new file mode 100644
index 000000000..5b83e2620
--- /dev/null
+++ b/tests/ui/fn/fun-call-variants.rs
@@ -0,0 +1,12 @@
+// run-pass
+
+fn ho<F>(f: F) -> isize where F: FnOnce(isize) -> isize { let n: isize = f(3); return n; }
+
+fn direct(x: isize) -> isize { return x + 1; }
+
+pub fn main() {
+ let a: isize = direct(3); // direct
+ let b: isize = ho(direct); // indirect unbound
+
+ assert_eq!(a, b);
+}
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-2.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.rs
new file mode 100644
index 000000000..5d9245556
--- /dev/null
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.rs
@@ -0,0 +1,23 @@
+// check-fail
+
+trait Trait {
+ type Type;
+}
+
+impl<T> Trait for T {
+ type Type = ();
+}
+
+fn f<'a, 'b>(_: <&'a &'b () as Trait>::Type)
+where
+ 'a: 'a,
+ 'b: 'b,
+{
+}
+
+fn g<'a, 'b>() {
+ f::<'a, 'b>(());
+ //~^ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr
new file mode 100644
index 000000000..0c3df04ea
--- /dev/null
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr
@@ -0,0 +1,17 @@
+error: lifetime may not live long enough
+ --> $DIR/implied-bounds-unnorm-associated-type-2.rs:19:5
+ |
+LL | fn g<'a, 'b>() {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | f::<'a, 'b>(());
+ | ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
+ |
+ = help: consider adding the following bound: `'b: 'a`
+ = note: requirement occurs because of a function pointer to `f`
+ = note: the function `f` is invariant over the parameter `'a`
+ = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to previous error
+
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-3.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type-3.rs
new file mode 100644
index 000000000..888f74cf6
--- /dev/null
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-3.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+pub trait Yokeable<'a>: 'static {
+ type Output: 'a;
+}
+
+impl<'a, T: 'static + ?Sized> Yokeable<'a> for &'static T {
+ type Output = &'a T;
+}
+
+pub trait ZeroCopyFrom<C: ?Sized>: for<'a> Yokeable<'a> {
+ /// Clone the cart `C` into a [`Yokeable`] struct, which may retain references into `C`.
+ fn zero_copy_from<'b>(cart: &'b C) -> <Self as Yokeable<'b>>::Output;
+}
+
+impl<T> ZeroCopyFrom<[T]> for &'static [T] {
+ fn zero_copy_from<'b>(cart: &'b [T]) -> &'b [T] {
+ cart
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.rs
new file mode 100644
index 000000000..12859252c
--- /dev/null
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.rs
@@ -0,0 +1,24 @@
+// A regression test for #98543
+
+trait Trait {
+ type Type;
+}
+
+impl<T> Trait for T {
+ type Type = ();
+}
+
+fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str
+where
+ &'a &'b (): Trait, // <- adding this bound is the change from #91068
+{
+ s
+}
+
+fn main() {
+ let x = String::from("Hello World!");
+ let y = f(&x, ());
+ drop(x);
+ //~^ ERROR cannot move out of `x` because it is borrowed
+ println!("{}", y);
+}
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr
new file mode 100644
index 000000000..fcbaa91d1
--- /dev/null
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr
@@ -0,0 +1,14 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+ --> $DIR/implied-bounds-unnorm-associated-type-4.rs:21:10
+ |
+LL | let y = f(&x, ());
+ | -- borrow of `x` occurs here
+LL | drop(x);
+ | ^ move out of `x` occurs here
+LL |
+LL | println!("{}", y);
+ | - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs
new file mode 100644
index 000000000..2a9a6a8cc
--- /dev/null
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs
@@ -0,0 +1,23 @@
+trait Trait<'a>: 'a {
+ type Type;
+}
+
+// if the `T: 'a` bound gets implied we would probably get ub here again
+impl<'a, T> Trait<'a> for T {
+ //~^ ERROR the parameter type `T` may not live long enough
+ type Type = ();
+}
+
+fn f<'a, 'b>(s: &'b str, _: <&'b () as Trait<'a>>::Type) -> &'a str
+where
+ &'b (): Trait<'a>,
+{
+ s
+}
+
+fn main() {
+ let x = String::from("Hello World!");
+ let y = f(&x, ());
+ drop(x);
+ println!("{}", y);
+}
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr
new file mode 100644
index 000000000..458756a3d
--- /dev/null
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr
@@ -0,0 +1,19 @@
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/implied-bounds-unnorm-associated-type-5.rs:6:13
+ |
+LL | impl<'a, T> Trait<'a> for T {
+ | ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
+ |
+note: ...that is required by this bound
+ --> $DIR/implied-bounds-unnorm-associated-type-5.rs:1:18
+ |
+LL | trait Trait<'a>: 'a {
+ | ^^
+help: consider adding an explicit lifetime bound...
+ |
+LL | impl<'a, T: 'a> Trait<'a> for T {
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type.rs
new file mode 100644
index 000000000..d58d25036
--- /dev/null
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type.rs
@@ -0,0 +1,23 @@
+// check-fail
+// See issue #91068. We check that the unnormalized associated types in
+// function signatures are implied
+
+trait Trait {
+ type Type;
+}
+
+impl<T> Trait for T {
+ type Type = ();
+}
+
+fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str {
+ s
+}
+
+fn main() {
+ let x = String::from("Hello World!");
+ let y = f(&x, ());
+ drop(x);
+ //~^ ERROR cannot move out of `x` because it is borrowed
+ println!("{}", y);
+}
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr
new file mode 100644
index 000000000..e35f46e44
--- /dev/null
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr
@@ -0,0 +1,14 @@
+error[E0505]: cannot move out of `x` because it is borrowed
+ --> $DIR/implied-bounds-unnorm-associated-type.rs:20:10
+ |
+LL | let y = f(&x, ());
+ | -- borrow of `x` occurs here
+LL | drop(x);
+ | ^ move out of `x` occurs here
+LL |
+LL | println!("{}", y);
+ | - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/tests/ui/fn/issue-3044.rs b/tests/ui/fn/issue-3044.rs
new file mode 100644
index 000000000..19bee733e
--- /dev/null
+++ b/tests/ui/fn/issue-3044.rs
@@ -0,0 +1,6 @@
+fn main() {
+ let needlesArr: Vec<char> = vec!['a', 'f'];
+ needlesArr.iter().fold(|x, y| {
+ //~^ ERROR this method takes 2 arguments but 1 argument was supplied
+ });
+}
diff --git a/tests/ui/fn/issue-3044.stderr b/tests/ui/fn/issue-3044.stderr
new file mode 100644
index 000000000..2690ad711
--- /dev/null
+++ b/tests/ui/fn/issue-3044.stderr
@@ -0,0 +1,21 @@
+error[E0061]: this method takes 2 arguments but 1 argument was supplied
+ --> $DIR/issue-3044.rs:3:23
+ |
+LL | needlesArr.iter().fold(|x, y| {
+ | _______________________^^^^-
+LL | |
+LL | | });
+ | |______- an argument is missing
+ |
+note: associated function defined here
+ --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+help: provide the argument
+ |
+LL ~ needlesArr.iter().fold(|x, y| {
+LL +
+LL ~ }, /* f */);
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/fn/issue-3904.rs b/tests/ui/fn/issue-3904.rs
new file mode 100644
index 000000000..7beb91a28
--- /dev/null
+++ b/tests/ui/fn/issue-3904.rs
@@ -0,0 +1,25 @@
+// run-pass
+fn example_err(prog: &str, arg: &str) {
+ println!("{}: {}", prog, arg)
+}
+
+fn exit<F>(print: F, prog: &str, arg: &str) where F: FnOnce(&str, &str) {
+ print(prog, arg);
+}
+
+struct X<F> where F: FnOnce(&str, &str) {
+ err: F,
+}
+
+impl<F> X<F> where F: FnOnce(&str, &str) {
+ pub fn boom(self) {
+ exit(self.err, "prog", "arg");
+ }
+}
+
+pub fn main(){
+ let val = X {
+ err: example_err,
+ };
+ val.boom();
+}
diff --git a/tests/ui/fn/issue-80179.rs b/tests/ui/fn/issue-80179.rs
new file mode 100644
index 000000000..35e39bebb
--- /dev/null
+++ b/tests/ui/fn/issue-80179.rs
@@ -0,0 +1,27 @@
+// Functions with a type placeholder `_` as the return type should
+// show a function pointer suggestion when given a function item
+// and suggest how to return closures correctly from a function.
+// This is a regression test of #80179
+
+fn returns_i32() -> i32 {
+ 0
+}
+
+fn returns_fn_ptr() -> _ {
+//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+//~| NOTE not allowed in type signatures
+//~| HELP replace with the correct return type
+//~| SUGGESTION fn() -> i32
+ returns_i32
+}
+
+fn returns_closure() -> _ {
+//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+//~| NOTE not allowed in type signatures
+//~| HELP replace with an appropriate return type
+//~| SUGGESTION impl Fn() -> i32
+//~| NOTE for more information on `Fn` traits and closure types
+ || 0
+}
+
+fn main() {}
diff --git a/tests/ui/fn/issue-80179.stderr b/tests/ui/fn/issue-80179.stderr
new file mode 100644
index 000000000..f5d6c44db
--- /dev/null
+++ b/tests/ui/fn/issue-80179.stderr
@@ -0,0 +1,23 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/issue-80179.rs:10:24
+ |
+LL | fn returns_fn_ptr() -> _ {
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with the correct return type: `fn() -> i32`
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/issue-80179.rs:18:25
+ |
+LL | fn returns_closure() -> _ {
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with an appropriate return type: `impl Fn() -> i32`
+ |
+ = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/fn/keyword-order.rs b/tests/ui/fn/keyword-order.rs
new file mode 100644
index 000000000..8a21db673
--- /dev/null
+++ b/tests/ui/fn/keyword-order.rs
@@ -0,0 +1,6 @@
+// edition:2018
+
+default pub const async unsafe extern fn err() {} //~ ERROR `default` is not followed by an item
+//~^ ERROR expected item, found keyword `pub`
+
+pub default const async unsafe extern fn ok() {}
diff --git a/tests/ui/fn/keyword-order.stderr b/tests/ui/fn/keyword-order.stderr
new file mode 100644
index 000000000..d3b140c85
--- /dev/null
+++ b/tests/ui/fn/keyword-order.stderr
@@ -0,0 +1,16 @@
+error: `default` is not followed by an item
+ --> $DIR/keyword-order.rs:3:1
+ |
+LL | default pub const async unsafe extern fn err() {}
+ | ^^^^^^^ the `default` qualifier
+ |
+ = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
+
+error: expected item, found keyword `pub`
+ --> $DIR/keyword-order.rs:3:9
+ |
+LL | default pub const async unsafe extern fn err() {}
+ | ^^^ expected item
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/fn/nested-function-names-issue-8587.rs b/tests/ui/fn/nested-function-names-issue-8587.rs
new file mode 100644
index 000000000..8fafd41d9
--- /dev/null
+++ b/tests/ui/fn/nested-function-names-issue-8587.rs
@@ -0,0 +1,42 @@
+// run-pass
+// Make sure nested functions are separate, even if they have
+// equal name.
+//
+// Issue #8587
+
+
+pub struct X;
+
+impl X {
+ fn f(&self) -> isize {
+ #[inline(never)]
+ fn inner() -> isize {
+ 0
+ }
+ inner()
+ }
+
+ fn g(&self) -> isize {
+ #[inline(never)]
+ fn inner_2() -> isize {
+ 1
+ }
+ inner_2()
+ }
+
+ fn h(&self) -> isize {
+ #[inline(never)]
+ fn inner() -> isize {
+ 2
+ }
+ inner()
+ }
+}
+
+pub fn main() {
+ let n = X;
+ assert_eq!(n.f(), 0);
+ assert_eq!(n.g(), 1);
+ // This test `h` used to fail.
+ assert_eq!(n.h(), 2);
+}
diff --git a/tests/ui/fn/signature-error-reporting-under-verbose.rs b/tests/ui/fn/signature-error-reporting-under-verbose.rs
new file mode 100644
index 000000000..d7a8c95e8
--- /dev/null
+++ b/tests/ui/fn/signature-error-reporting-under-verbose.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Zverbose
+
+fn foo(_: i32, _: i32) {}
+
+fn needs_ptr(_: fn(i32, u32)) {}
+//~^ NOTE function defined here
+//~| NOTE
+
+fn main() {
+ needs_ptr(foo);
+ //~^ ERROR mismatched types
+ //~| NOTE expected `u32`, found `i32`
+ //~| NOTE expected fn pointer `fn(i32, u32)`
+ //~| NOTE arguments to this function are incorrect
+}
diff --git a/tests/ui/fn/signature-error-reporting-under-verbose.stderr b/tests/ui/fn/signature-error-reporting-under-verbose.stderr
new file mode 100644
index 000000000..6260fc8dc
--- /dev/null
+++ b/tests/ui/fn/signature-error-reporting-under-verbose.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+ --> $DIR/signature-error-reporting-under-verbose.rs:10:15
+ |
+LL | needs_ptr(foo);
+ | --------- ^^^ expected `u32`, found `i32`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected fn pointer `fn(i32, u32)`
+ found fn item `fn(i32, i32) {foo}`
+note: function defined here
+ --> $DIR/signature-error-reporting-under-verbose.rs:5:4
+ |
+LL | fn needs_ptr(_: fn(i32, u32)) {}
+ | ^^^^^^^^^ ---------------
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/fn/suggest-return-closure.rs b/tests/ui/fn/suggest-return-closure.rs
new file mode 100644
index 000000000..33daa1ea0
--- /dev/null
+++ b/tests/ui/fn/suggest-return-closure.rs
@@ -0,0 +1,34 @@
+fn fn_once() -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+ //~| NOTE not allowed in type signatures
+ //~| HELP replace with an appropriate return type
+ //~| SUGGESTION impl FnOnce()
+ //~| NOTE for more information on `Fn` traits and closure types
+ let x = String::new();
+ || {
+ drop(x);
+ }
+}
+
+fn fn_mut() -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+ //~| NOTE not allowed in type signatures
+ //~| HELP replace with an appropriate return type
+ //~| SUGGESTION impl FnMut(char)
+ //~| NOTE for more information on `Fn` traits and closure types
+ let x = String::new();
+ |c| {
+ x.push(c);
+ }
+}
+
+fn fun() -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+ //~| NOTE not allowed in type signatures
+ //~| HELP replace with an appropriate return type
+ //~| SUGGESTION impl Fn() -> i32
+ //~| NOTE for more information on `Fn` traits and closure types
+ || 1i32
+}
+
+fn main() {}
diff --git a/tests/ui/fn/suggest-return-closure.stderr b/tests/ui/fn/suggest-return-closure.stderr
new file mode 100644
index 000000000..341044469
--- /dev/null
+++ b/tests/ui/fn/suggest-return-closure.stderr
@@ -0,0 +1,36 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/suggest-return-closure.rs:1:17
+ |
+LL | fn fn_once() -> _ {
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with an appropriate return type: `impl FnOnce()`
+ |
+ = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/suggest-return-closure.rs:13:16
+ |
+LL | fn fn_mut() -> _ {
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with an appropriate return type: `impl FnMut(char)`
+ |
+ = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/suggest-return-closure.rs:25:13
+ |
+LL | fn fun() -> _ {
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with an appropriate return type: `impl Fn() -> i32`
+ |
+ = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/fn/suggest-return-future.rs b/tests/ui/fn/suggest-return-future.rs
new file mode 100644
index 000000000..750740d94
--- /dev/null
+++ b/tests/ui/fn/suggest-return-future.rs
@@ -0,0 +1,23 @@
+// edition: 2021
+
+async fn a() -> i32 {
+ 0
+}
+
+fn foo() -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+ //~| NOTE not allowed in type signatures
+ //~| HELP replace with an appropriate return type
+ //~| SUGGESTION impl Future<Output = i32>
+ a()
+}
+
+fn bar() -> _ {
+ //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121]
+ //~| NOTE not allowed in type signatures
+ //~| HELP replace with an appropriate return type
+ //~| SUGGESTION impl Future<Output = i32>
+ async { a().await }
+}
+
+fn main() {}
diff --git a/tests/ui/fn/suggest-return-future.stderr b/tests/ui/fn/suggest-return-future.stderr
new file mode 100644
index 000000000..a4c8b5d8c
--- /dev/null
+++ b/tests/ui/fn/suggest-return-future.stderr
@@ -0,0 +1,21 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/suggest-return-future.rs:7:13
+ |
+LL | fn foo() -> _ {
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with an appropriate return type: `impl Future<Output = i32>`
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+ --> $DIR/suggest-return-future.rs:15:13
+ |
+LL | fn bar() -> _ {
+ | ^
+ | |
+ | not allowed in type signatures
+ | help: replace with an appropriate return type: `impl Future<Output = i32>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.