-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow impl Fn() -> impl Trait
in return position
#93582
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: