diff options
Diffstat (limited to 'tests/ui/fn')
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`. |