-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Allow impl Fn() -> impl Trait
in return position
#93582
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Conversation
impl Fn() -> impl Trait
in return possitionimpl Fn() -> impl Trait
in return position
☔ The latest upstream changes (presumably #92007) made this pull request unmergeable. Please resolve the merge conflicts. |
a819fec
to
711a422
Compare
☔ The latest upstream changes (presumably #93893) made this pull request unmergeable. Please resolve the merge conflicts. |
711a422
to
e478a1a
Compare
☔ The latest upstream changes (presumably #94134) made this pull request unmergeable. Please resolve the merge conflicts. |
e478a1a
to
64489b2
Compare
This comment has been minimized.
This comment has been minimized.
64489b2
to
15e2324
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @WaffleLapkin, sorry for the very slow review. Here are some tests that would be good!
Come to think of it, @WaffleLapkin, here are more tests related to '_
: ---
we should show that fn foo() -> impl Fn() -> (impl Debug + '_)
is an error
and that impl for<'a> Fn(&'a u8) -> (impl Debug + '_)
correctly matches the '_
to 'a
related: impl Fn(&'a u8) -> (impl Debug + '_)
correctly matches the '_
to some pre-existing 'a
|| () | ||
} | ||
|
||
fn ff_debug() -> impl Fn() -> impl Fn() -> impl Debug { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add some tests about +
bounds:
// This should error because the returned closure is capturing
// its argument, which was not declared as part of the signature.
fn f_debug() -> impl Fn(&u8) -> impl Debug {
|x| x
}
// This should (maybe) error because or parsing ambiguities
fn f_debug() -> impl Fn(&u8) -> impl Debug + '_ {
|x| x
}
// This should (maybe) error because or parsing ambiguities
fn f_debug() -> impl Fn() -> impl Debug + Send {
|| ()
}
// This should work
fn f_debug() -> impl Fn(&u8) -> (impl Debug + '_) {
|x| x
}
// This should work
fn f_debug() -> impl Fn() -> (impl Debug + Send) {
|| ()
}
Nominating for @rust-lang/lang meeting. We've discussed a predecessor of this PR before, and this is the follow-up. It extends fn foo() -> impl Fn() -> impl Debug { } There are a few interesting questions. On the prior PR, @cramertj pointed out that parsing has some syntactical ambiguities here: fn foo() -> impl Fn() -> impl Debug + Send { }
// Is this `-> impl Fn() -> (impl Debug) + Send` or `impl Fn() -> (impl Debug + Send)` ? The same above also implies the fn foo() -> impl Fn(&u8) -> (impl Debug + '_) |
@rustbot team |
☔ The latest upstream changes (presumably #94081) made this pull request unmergeable. Please resolve the merge conflicts. |
Hmm, we've been slow in getting to this! I won't be at the next triage meeting, but I'll try to ensure we discuss it soon! Apologies @WaffleLapkin |
@WaffleLapkin -- this is still blocked on you making some adjustments, right? We are going to remove the nomination in the meantime. |
@rustbot author |
@nikomatsakis the problem is not necessarily with this feature by itself, but more with the general HRTB+RPIT issues like #95647 which stop me from adding proposed tests (because they ICE). |
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.
92ebd2a
to
e93982a
Compare
@compiler-errors rebased ;) |
@bors r+ See my comment #93582 (comment) -- this may be something we want to revisit before stabilizing this, but it shouldn't block landing the feature gate IMO. |
…errors Allow `impl Fn() -> impl Trait` in return position _This was originally proposed as part of rust-lang#93082 which was [closed](rust-lang#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 } } ```
…errors Allow `impl Fn() -> impl Trait` in return position _This was originally proposed as part of rust-lang#93082 which was [closed](rust-lang#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 } } ```
Rollup of 5 pull requests Successful merges: - rust-lang#93582 (Allow `impl Fn() -> impl Trait` in return position) - rust-lang#103560 (Point only to the identifiers in the typo suggestions of shadowed names instead of the entire struct) - rust-lang#103588 (rustdoc: add missing URL redirect) - rust-lang#103689 (Do fewer passes and generally be more efficient when filtering tests) - rust-lang#103740 (rustdoc: remove unnecessary CSS `.search-results { padding-bottom }`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Yay! |
…errors Allow `impl Fn() -> impl Trait` in return position _This was originally proposed as part of rust-lang#93082 which was [closed](rust-lang#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 } } ```
Rollup of 5 pull requests Successful merges: - rust-lang#93582 (Allow `impl Fn() -> impl Trait` in return position) - rust-lang#103560 (Point only to the identifiers in the typo suggestions of shadowed names instead of the entire struct) - rust-lang#103588 (rustdoc: add missing URL redirect) - rust-lang#103689 (Do fewer passes and generally be more efficient when filtering tests) - rust-lang#103740 (rustdoc: remove unnecessary CSS `.search-results { padding-bottom }`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This was originally proposed as part of #93082 which was closed due to allowing
impl Fn() -> impl Trait
in argument position.This allows writing the following function signatures:
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 bothf0
andf3
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.There even is a test that
f0
compiles:rust/src/test/ui/impl-trait/nested_impl_trait.rs
Lines 25 to 28 in 2f004d2
But it was changed in PR 48084 (lines) to test the opposite, probably unintentionally given PR 48084 (lines).
r? @nikomatsakis
This limitation is especially annoying with async code, since it forces one to write this:
Instead of: