-
Notifications
You must be signed in to change notification settings - Fork 12.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of #93582 - WaffleLapkin:rpitirpit, r=compiler-errors
Allow `impl Fn() -> impl Trait` in return position _This was originally proposed as part of #93082 which was [closed](#93082 (comment)) due to allowing `impl Fn() -> impl Trait` in argument position._ This allows writing the following function signatures: ```rust fn f0() -> impl Fn() -> impl Trait; fn f3() -> &'static dyn Fn() -> impl Trait; ``` These signatures were already allowed for common traits and associated types, there is no reason why `Fn*` traits should be special in this regard. `impl Trait` in both `f0` and `f3` means "new existential type", just like with `-> impl Iterator<Item = impl Trait>` and such. Arrow in `impl Fn() ->` is right-associative and binds from right to left, it's tested by [this test](https://github.com/WaffleLapkin/rust/blob/a819fecb8dea438fc70488ddec30a61e52942672/src/test/ui/impl-trait/impl_fn_associativity.rs). There even is a test that `f0` compiles: https://github.com/rust-lang/rust/blob/2f004d2d401682e553af3984ebd9a3976885e752/src/test/ui/impl-trait/nested_impl_trait.rs#L25-L28 But it was changed in [PR 48084 (lines)](https://github.com/rust-lang/rust/pull/48084/files#diff-ccecca938872d65ffe8cd1c3ef1956e309fac83bcda547d8b16b89257e53a437R37) to test the opposite, probably unintentionally given [PR 48084 (lines)](https://github.com/rust-lang/rust/pull/48084/files#diff-5a02f1ed43debed1fd24f7aad72490064f795b9420f15d847bac822aa4621a1cR476-R477). r? `@nikomatsakis` ---- This limitation is especially annoying with async code, since it forces one to write this: ```rust trait AsyncFn3<A, B, C>: Fn(A, B, C) -> <Self as AsyncFn3<A, B, C>>::Future { type Future: Future<Output = Self::Out>; type Out; } impl<A, B, C, Fut, F> AsyncFn3<A, B, C> for F where F: Fn(A, B, C) -> Fut, Fut: Future, { type Future = Fut; type Out = Fut::Output; } fn async_closure() -> impl AsyncFn3<i32, i32, i32, Out = u32> { |a, b, c| async move { (a + b + c) as u32 } } ``` Instead of: ```rust fn async_closure() -> impl Fn(i32, i32, i32) -> impl Future<Output = u32> { |a, b, c| async move { (a + b + c) as u32 } } ```
- Loading branch information
Showing
18 changed files
with
295 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
fn f() -> impl Fn() -> impl Sized { || () } | ||
//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return | ||
fn g() -> &'static dyn Fn() -> impl Sized { &|| () } | ||
//~^ ERROR `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return | ||
|
||
fn main() {} |
15 changes: 15 additions & 0 deletions
15
src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return | ||
--> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:1:24 | ||
| | ||
LL | fn f() -> impl Fn() -> impl Sized { || () } | ||
| ^^^^^^^^^^ | ||
|
||
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return | ||
--> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32 | ||
| | ||
LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () } | ||
| ^^^^^^^^^^ | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0562`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#![feature(impl_trait_in_fn_trait_return)] | ||
use std::fmt::Debug; | ||
|
||
fn a() -> impl Fn(&u8) -> impl Debug { | ||
|x| x //~ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds | ||
--> $DIR/impl-fn-hrtb-bounds-2.rs:5:9 | ||
| | ||
LL | |x| x | ||
| --- ^ | ||
| | | ||
| hidden type `&u8` captures the anonymous lifetime #1 defined here | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0700`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#![feature(impl_trait_in_fn_trait_return)] | ||
use std::fmt::Debug; | ||
|
||
fn a() -> impl Fn(&u8) -> (impl Debug + '_) { | ||
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet | ||
|x| x | ||
} | ||
|
||
fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { | ||
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet | ||
|x| x | ||
} | ||
|
||
fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | ||
//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet | ||
|x| x | ||
} | ||
|
||
fn d() -> impl Fn() -> (impl Debug + '_) { | ||
//~^ ERROR missing lifetime specifier | ||
|| () | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
error[E0106]: missing lifetime specifier | ||
--> $DIR/impl-fn-hrtb-bounds.rs:19:38 | ||
| | ||
LL | fn d() -> impl Fn() -> (impl Debug + '_) { | ||
| ^^ expected named lifetime parameter | ||
| | ||
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from | ||
help: consider using the `'static` lifetime | ||
| | ||
LL | fn d() -> impl Fn() -> (impl Debug + 'static) { | ||
| ~~~~~~~ | ||
|
||
error: higher kinded lifetime bounds on nested opaque types are not supported yet | ||
--> $DIR/impl-fn-hrtb-bounds.rs:4:41 | ||
| | ||
LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { | ||
| ^^ | ||
| | ||
note: lifetime declared here | ||
--> $DIR/impl-fn-hrtb-bounds.rs:4:19 | ||
| | ||
LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) { | ||
| ^ | ||
|
||
error: higher kinded lifetime bounds on nested opaque types are not supported yet | ||
--> $DIR/impl-fn-hrtb-bounds.rs:9:52 | ||
| | ||
LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { | ||
| ^^ | ||
| | ||
note: lifetime declared here | ||
--> $DIR/impl-fn-hrtb-bounds.rs:9:20 | ||
| | ||
LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) { | ||
| ^^ | ||
|
||
error: higher kinded lifetime bounds on nested opaque types are not supported yet | ||
--> $DIR/impl-fn-hrtb-bounds.rs:14:52 | ||
| | ||
LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | ||
| ^^ | ||
| | ||
note: lifetime declared here | ||
--> $DIR/impl-fn-hrtb-bounds.rs:14:20 | ||
| | ||
LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) { | ||
| ^^ | ||
|
||
error: aborting due to 4 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0106`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#![feature(impl_trait_in_fn_trait_return)] | ||
use std::fmt::Debug; | ||
|
||
fn a() -> impl Fn(&u8) -> impl Debug + '_ { | ||
//~^ ERROR ambiguous `+` in a type | ||
//~^^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet | ||
|x| x | ||
} | ||
|
||
fn b() -> impl Fn() -> impl Debug + Send { | ||
//~^ ERROR ambiguous `+` in a type | ||
|| () | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
error: ambiguous `+` in a type | ||
--> $DIR/impl-fn-parsing-ambiguities.rs:4:27 | ||
| | ||
LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { | ||
| ^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + '_)` | ||
|
||
error: ambiguous `+` in a type | ||
--> $DIR/impl-fn-parsing-ambiguities.rs:10:24 | ||
| | ||
LL | fn b() -> impl Fn() -> impl Debug + Send { | ||
| ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)` | ||
|
||
error: higher kinded lifetime bounds on nested opaque types are not supported yet | ||
--> $DIR/impl-fn-parsing-ambiguities.rs:4:40 | ||
| | ||
LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { | ||
| ^^ | ||
| | ||
note: lifetime declared here | ||
--> $DIR/impl-fn-parsing-ambiguities.rs:4:19 | ||
| | ||
LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ { | ||
| ^ | ||
|
||
error: aborting due to 3 previous errors | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#![feature(impl_trait_in_fn_trait_return)] | ||
use std::fmt::Debug; | ||
|
||
fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | ||
//~^ ERROR cannot resolve opaque type | ||
|
||
|x| x | ||
//~^ ERROR concrete type differs from previous defining opaque type use | ||
} | ||
|
||
fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { | ||
a() | ||
} | ||
|
||
fn main() {} |
24 changes: 24 additions & 0 deletions
24
src/test/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
error: concrete type differs from previous defining opaque type use | ||
--> $DIR/impl-fn-predefined-lifetimes.rs:7:9 | ||
| | ||
LL | |x| x | ||
| ^ expected `impl Debug + '_`, got `&u8` | ||
| | ||
note: previous use here | ||
--> $DIR/impl-fn-predefined-lifetimes.rs:7:5 | ||
| | ||
LL | |x| x | ||
| ^^^^^ | ||
|
||
error[E0720]: cannot resolve opaque type | ||
--> $DIR/impl-fn-predefined-lifetimes.rs:4:35 | ||
| | ||
LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | ||
| ^^^^^^^^^^^^^^^ recursive opaque type | ||
... | ||
LL | |x| x | ||
| ----- returning here with type `[closure@$DIR/impl-fn-predefined-lifetimes.rs:7:5: 7:8]` | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0720`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// run-pass | ||
#![feature(impl_trait_in_fn_trait_return)] | ||
use std::fmt::Debug; | ||
|
||
fn f_debug() -> impl Fn() -> impl Debug { | ||
|| () | ||
} | ||
|
||
fn ff_debug() -> impl Fn() -> impl Fn() -> impl Debug { | ||
|| f_debug() | ||
} | ||
|
||
fn multi() -> impl Fn() -> (impl Debug + Send) { | ||
|| () | ||
} | ||
|
||
fn main() { | ||
// Check that `ff_debug` is `() -> (() -> Debug)` and not `(() -> ()) -> Debug` | ||
let debug = ff_debug()()(); | ||
assert_eq!(format!("{:?}", debug), "()"); | ||
|
||
let x = multi()(); | ||
assert_eq!(format!("{:?}", x), "()"); | ||
fn assert_send(_: &impl Send) {} | ||
assert_send(&x); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.