diff options
Diffstat (limited to 'tests/ui/closure-expected-type')
10 files changed, 276 insertions, 0 deletions
diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs b/tests/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs new file mode 100644 index 000000000..5f02e642d --- /dev/null +++ b/tests/ui/closure-expected-type/expect-fn-supply-fn-multiple.rs @@ -0,0 +1,38 @@ +// build-pass (FIXME(62277): could be check-pass?) + +#![allow(warnings)] + +type Different<'a, 'b> = &'a mut (&'a (), &'b ()); +type Same<'a> = Different<'a, 'a>; + +fn with_closure_expecting_different<F>(_: F) + where F: for<'a, 'b> FnOnce(Different<'a, 'b>) +{ +} + +fn with_closure_expecting_different_anon<F>(_: F) + where F: FnOnce(Different<'_, '_>) +{ +} + +fn supplying_nothing_expecting_anon() { + with_closure_expecting_different_anon(|x: Different| { + }) +} + +fn supplying_nothing_expecting_named() { + with_closure_expecting_different(|x: Different| { + }) +} + +fn supplying_underscore_expecting_anon() { + with_closure_expecting_different_anon(|x: Different<'_, '_>| { + }) +} + +fn supplying_underscore_expecting_named() { + with_closure_expecting_different(|x: Different<'_, '_>| { + }) +} + +fn main() { } diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn.rs b/tests/ui/closure-expected-type/expect-fn-supply-fn.rs new file mode 100644 index 000000000..7f1c14027 --- /dev/null +++ b/tests/ui/closure-expected-type/expect-fn-supply-fn.rs @@ -0,0 +1,60 @@ +fn with_closure_expecting_fn_with_free_region<F>(_: F) +where + F: for<'a> FnOnce(fn(&'a u32), &i32), +{ +} + +fn with_closure_expecting_fn_with_bound_region<F>(_: F) +where + F: FnOnce(fn(&u32), &i32), +{ +} + +fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + // Here, the type given for `'x` "obscures" a region from the + // expected signature that is bound at closure level. + with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough +} + +fn expect_free_supply_free_from_closure() { + // A variant on the previous test. Here, the region `'a` will be + // bound at the closure level, just as is expected, so no error + // results. + type Foo<'a> = fn(&'a u32); + with_closure_expecting_fn_with_free_region(|_x: Foo<'_>, y| {}); +} + +fn expect_free_supply_bound() { + // Here, we are given a function whose region is bound at closure level, + // but we expect one bound in the argument. Error results. + with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); + //~^ ERROR mismatched types +} + +fn expect_bound_supply_free_from_fn<'x>(x: &'x u32) { + // Here, we are given a `fn(&u32)` but we expect a `fn(&'x + // u32)`. In principle, this could be ok, but we demand equality. + with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); + //~^ ERROR mismatched types +} + +fn expect_bound_supply_free_from_closure() { + // A variant on the previous test. Here, the region `'a` will be + // bound at the closure level, but we expect something bound at + // the argument level. + type Foo<'a> = fn(&'a u32); + with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + //~^ ERROR mismatched types + }); +} + +fn expect_bound_supply_bound<'x>(x: &'x u32) { + // No error in this case. The supplied type supplies the bound + // regions, and hence we are able to figure out the type of `y` + // from the expected type + with_closure_expecting_fn_with_bound_region(|x: for<'z> fn(&'z u32), y| {}); +} + +fn main() {} diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr new file mode 100644 index 000000000..e6ddc6068 --- /dev/null +++ b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -0,0 +1,51 @@ +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:16:49 + | +LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + | -- lifetime `'x` defined here +... +LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + | ^ + | | + | has type `fn(&'1 u32)` + | requires that `'1` must outlive `'x` + +error: lifetime may not live long enough + --> $DIR/expect-fn-supply-fn.rs:16:49 + | +LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { + | -- lifetime `'x` defined here +... +LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); + | ^ requires that `'x` must outlive `'static` + +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:32:49 + | +LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); + | ^ one type is more general than the other + | + = note: expected fn pointer `fn(&u32)` + found fn pointer `for<'a> fn(&'a u32)` + +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:39:50 + | +LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'a> fn(&'a u32)` + found fn pointer `fn(&u32)` + +error[E0308]: mismatched types + --> $DIR/expect-fn-supply-fn.rs:48:50 + | +LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { + | ^ one type is more general than the other + | + = note: expected fn pointer `for<'a> fn(&'a u32)` + found fn pointer `fn(&u32)` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.rs b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.rs new file mode 100644 index 000000000..e5ec6b271 --- /dev/null +++ b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.rs @@ -0,0 +1,25 @@ +fn with_closure<F, A>(_: F) + where F: FnOnce(A, A) +{ +} + +fn a() { + with_closure(|x: u32, y| { + // We deduce type of `y` from `x`. + }); +} + +fn b() { + // Here we take the supplied types, resulting in an error later on. + with_closure(|x: u32, y: i32| { + //~^ ERROR type mismatch in closure arguments + }); +} + +fn c() { + with_closure(|x, y: i32| { + // We deduce type of `x` from `y`. + }); +} + +fn main() { } diff --git a/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr new file mode 100644 index 000000000..8dccf929b --- /dev/null +++ b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr @@ -0,0 +1,21 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/expect-infer-var-appearing-twice.rs:14:5 + | +LL | with_closure(|x: u32, y: i32| { + | ^^^^^^^^^^^^ ---------------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `fn(_, _) -> _` + found closure signature `fn(u32, i32) -> _` +note: required by a bound in `with_closure` + --> $DIR/expect-infer-var-appearing-twice.rs:2:14 + | +LL | fn with_closure<F, A>(_: F) + | ------------ required by a bound in this +LL | where F: FnOnce(A, A) + | ^^^^^^^^^^^^ required by this bound in `with_closure` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0631`. diff --git a/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs b/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs new file mode 100644 index 000000000..0ee738c2c --- /dev/null +++ b/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-bound-region.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) + +fn with_closure<F, A>(_: F) + where F: FnOnce(A, &u32) +{ +} + +fn foo() { + // This version works; we infer `A` to be `u32`, and take the type + // of `y` to be `&u32`. + with_closure(|x: u32, y| {}); +} + +fn bar() { + // This version also works. + with_closure(|x: &u32, y| {}); +} + +fn main() { } diff --git a/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs b/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs new file mode 100644 index 000000000..15711da4b --- /dev/null +++ b/tests/ui/closure-expected-type/expect-infer-var-supply-ty-with-free-region.rs @@ -0,0 +1,19 @@ +// build-pass (FIXME(62277): could be check-pass?) + +fn with_closure<F, A>(_: F) + where F: FnOnce(A, &u32) +{ +} + +fn foo() { + // This version works; we infer `A` to be `u32`, and take the type + // of `y` to be `&u32`. + with_closure(|x: u32, y| {}); +} + +fn bar<'x>(x: &'x u32) { + // Same. + with_closure(|x: &'x u32, y| {}); +} + +fn main() { } diff --git a/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs b/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs new file mode 100644 index 000000000..97d7a51a7 --- /dev/null +++ b/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.rs @@ -0,0 +1,19 @@ +fn with_closure<F, A, B>(_: F) + where F: FnOnce(A, B) +{ +} + +fn a() { + // Type of `y` is unconstrained. + with_closure(|x: u32, y| {}); //~ ERROR E0282 +} + +fn b() { + with_closure(|x: u32, y: u32| {}); // OK +} + +fn c() { + with_closure(|x: u32, y: u32| {}); // OK +} + +fn main() { } diff --git a/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr b/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr new file mode 100644 index 000000000..7a04ed738 --- /dev/null +++ b/tests/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed + --> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:27 + | +LL | with_closure(|x: u32, y| {}); + | ^ + | +help: consider giving this closure parameter an explicit type + | +LL | with_closure(|x: u32, y: /* Type */| {}); + | ++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/closure-expected-type/issue-24421.rs b/tests/ui/closure-expected-type/issue-24421.rs new file mode 100644 index 000000000..2e104b599 --- /dev/null +++ b/tests/ui/closure-expected-type/issue-24421.rs @@ -0,0 +1,10 @@ +// check-pass + +fn test<F: Fn(&u64, &u64)>(f: F) {} + +fn main() { + test(|x, y | {}); + test(|x:&u64, y:&u64| {}); + test(|x:&u64, y | {}); + test(|x, y:&u64| {}); +} |