Add `AsyncFn` family of traits I'm proposing to add a new family of `async`hronous `Fn`-like traits to the standard library for experimentation purposes. ## Why do we need new traits? On the user side, it is useful to be able to express `AsyncFn` trait bounds natively via the parenthesized sugar syntax, i.e. `x: impl AsyncFn(&str) -> String` when experimenting with async-closure code. This also does not preclude `AsyncFn` becoming something else like a trait alias if a more fundamental desugaring (which can take many[^1] different[^2] forms) comes around. I think we should be able to play around with `AsyncFn` well before that, though. I'm also not proposing stabilization of these trait names any time soon (we may even want to instead express them via new syntax, like `async Fn() -> ..`), but I also don't think we need to introduce an obtuse bikeshedding name, since `AsyncFn` just makes sense. ## The lending problem: why not add a more fundamental primitive of `LendingFn`/`LendingFnMut`? Firstly, for `async` closures to be as flexible as possible, they must be allowed to return futures which borrow from the async closure's captures. This can be done by introducing `LendingFn`/`LendingFnMut` traits, or (equivalently) by adding a new generic associated type to `FnMut` which allows the return type to capture lifetimes from the `&mut self` argument of the trait. This was proposed in one of [Niko's blog posts](https://smallcultfollowing.com/babysteps/blog/2023/05/09/giving-lending-and-async-closures/). Upon further experimentation, for the purposes of closure type- and borrow-checking, I've come to the conclusion that it's significantly harder to teach the compiler how to handle *general* lending closures which may borrow from their captures. This is, because unlike `Fn`/`FnMut`, the `LendingFn`/`LendingFnMut` traits don't form a simple "inheritance" hierarchy whose top trait is `FnOnce`. ```mermaid flowchart LR Fn FnMut FnOnce LendingFn LendingFnMut Fn -- isa --> FnMut FnMut -- isa --> FnOnce LendingFn -- isa --> LendingFnMut Fn -- isa --> LendingFn FnMut -- isa --> LendingFnMut ``` For example: ``` fn main() { let s = String::from("hello, world"); let f = move || &s; let x = f(); // This borrows `f` for some lifetime `'1` and returns `&'1 String`. ``` That trait hierarchy means that in general for "lending" closures, like `f` above, there's not really a meaningful return type for `<typeof(f) as FnOnce>::Output` -- it can't return `&'static str`, for example. ### Special-casing this problem: By splitting out these traits manually, and making sure that each trait has its own associated future type, we side-step the issue of having to answer the questions of a general `LendingFn`/`LendingFnMut` implementation, since the compiler knows how to generate built-in implementations for first-class constructs like async closures, including the required future types for the (by-move) `AsyncFnOnce` and (by-ref) `AsyncFnMut`/`AsyncFn` trait implementations. [^1]: For example, with trait transformers, we may eventually be able to write: `trait AsyncFn = async Fn;` [^2]: For example, via the introduction of a more fundamental "`LendingFn`" trait, plus a [special desugaring with augmented trait aliases](https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Lending.20closures.20and.20Fn*.28.29.20-.3E.20impl.20Trait/near/408471480).
346 lines
11 KiB
Plaintext
346 lines
11 KiB
Plaintext
error: missing angle brackets in associated item path
|
|
--> $DIR/bad-assoc-ty.rs:1:10
|
|
|
|
|
LL | type A = [u8; 4]::AssocTy;
|
|
| ^^^^^^^
|
|
|
|
|
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
|
|
|
|
LL | type A = <[u8; 4]>::AssocTy;
|
|
| + +
|
|
|
|
error: missing angle brackets in associated item path
|
|
--> $DIR/bad-assoc-ty.rs:5:10
|
|
|
|
|
LL | type B = [u8]::AssocTy;
|
|
| ^^^^
|
|
|
|
|
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
|
|
|
|
LL | type B = <[u8]>::AssocTy;
|
|
| + +
|
|
|
|
error: missing angle brackets in associated item path
|
|
--> $DIR/bad-assoc-ty.rs:9:10
|
|
|
|
|
LL | type C = (u8)::AssocTy;
|
|
| ^^^^
|
|
|
|
|
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
|
|
|
|
LL | type C = <(u8)>::AssocTy;
|
|
| + +
|
|
|
|
error: missing angle brackets in associated item path
|
|
--> $DIR/bad-assoc-ty.rs:13:10
|
|
|
|
|
LL | type D = (u8, u8)::AssocTy;
|
|
| ^^^^^^^^
|
|
|
|
|
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
|
|
|
|
LL | type D = <(u8, u8)>::AssocTy;
|
|
| + +
|
|
|
|
error: missing angle brackets in associated item path
|
|
--> $DIR/bad-assoc-ty.rs:17:10
|
|
|
|
|
LL | type E = _::AssocTy;
|
|
| ^
|
|
|
|
|
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
|
|
|
|
LL | type E = <_>::AssocTy;
|
|
| + +
|
|
|
|
error: missing angle brackets in associated item path
|
|
--> $DIR/bad-assoc-ty.rs:21:19
|
|
|
|
|
LL | type F = &'static (u8)::AssocTy;
|
|
| ^^^^
|
|
|
|
|
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
|
|
|
|
LL | type F = &'static <(u8)>::AssocTy;
|
|
| + +
|
|
|
|
error: missing angle brackets in associated item path
|
|
--> $DIR/bad-assoc-ty.rs:27:10
|
|
|
|
|
LL | type G = dyn 'static + (Send)::AssocTy;
|
|
| ^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
|
|
|
|
LL | type G = <dyn 'static + (Send)>::AssocTy;
|
|
| + +
|
|
|
|
error: missing angle brackets in associated item path
|
|
--> $DIR/bad-assoc-ty.rs:46:10
|
|
|
|
|
LL | type I = ty!()::AssocTy;
|
|
| ^^^^^
|
|
|
|
|
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
|
|
|
|
LL | type I = <ty!()>::AssocTy;
|
|
| + +
|
|
|
|
error: missing angle brackets in associated item path
|
|
--> $DIR/bad-assoc-ty.rs:39:19
|
|
|
|
|
LL | ($ty: ty) => ($ty::AssocTy);
|
|
| ^^^
|
|
...
|
|
LL | type J = ty!(u8);
|
|
| ------- in this macro invocation
|
|
|
|
|
= note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
|
|
|
|
|
LL | ($ty: ty) => (<$ty>::AssocTy);
|
|
| + +
|
|
|
|
error[E0223]: ambiguous associated type
|
|
--> $DIR/bad-assoc-ty.rs:1:10
|
|
|
|
|
LL | type A = [u8; 4]::AssocTy;
|
|
| ^^^^^^^^^^^^^^^^
|
|
|
|
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8; 4]`, you could use the fully-qualified path
|
|
|
|
|
LL | type A = <[u8; 4] as Example>::AssocTy;
|
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
error[E0223]: ambiguous associated type
|
|
--> $DIR/bad-assoc-ty.rs:5:10
|
|
|
|
|
LL | type B = [u8]::AssocTy;
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8]`, you could use the fully-qualified path
|
|
|
|
|
LL | type B = <[u8] as Example>::AssocTy;
|
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
error[E0223]: ambiguous associated type
|
|
--> $DIR/bad-assoc-ty.rs:9:10
|
|
|
|
|
LL | type C = (u8)::AssocTy;
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
|
|
|
|
|
LL | type C = <u8 as Example>::AssocTy;
|
|
| ~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
error[E0223]: ambiguous associated type
|
|
--> $DIR/bad-assoc-ty.rs:13:10
|
|
|
|
|
LL | type D = (u8, u8)::AssocTy;
|
|
| ^^^^^^^^^^^^^^^^^
|
|
|
|
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(u8, u8)`, you could use the fully-qualified path
|
|
|
|
|
LL | type D = <(u8, u8) as Example>::AssocTy;
|
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
|
|
--> $DIR/bad-assoc-ty.rs:17:10
|
|
|
|
|
LL | type E = _::AssocTy;
|
|
| ^ not allowed in type signatures
|
|
|
|
error[E0223]: ambiguous associated type
|
|
--> $DIR/bad-assoc-ty.rs:21:19
|
|
|
|
|
LL | type F = &'static (u8)::AssocTy;
|
|
| ^^^^^^^^^^^^^
|
|
|
|
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
|
|
|
|
|
LL | type F = &'static <u8 as Example>::AssocTy;
|
|
| ~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
error[E0223]: ambiguous associated type
|
|
--> $DIR/bad-assoc-ty.rs:27:10
|
|
|
|
|
LL | type G = dyn 'static + (Send)::AssocTy;
|
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(dyn Send + 'static)`, you could use the fully-qualified path
|
|
|
|
|
LL | type G = <(dyn Send + 'static) as Example>::AssocTy;
|
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
warning: trait objects without an explicit `dyn` are deprecated
|
|
--> $DIR/bad-assoc-ty.rs:33:10
|
|
|
|
|
LL | type H = Fn(u8) -> (u8)::Output;
|
|
| ^^^^^^^^^^^^^^
|
|
|
|
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
|
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
|
|
= note: `#[warn(bare_trait_objects)]` on by default
|
|
help: use `dyn`
|
|
|
|
|
LL | type H = <dyn Fn(u8) -> (u8)>::Output;
|
|
| ++++ +
|
|
|
|
error[E0223]: ambiguous associated type
|
|
--> $DIR/bad-assoc-ty.rs:33:10
|
|
|
|
|
LL | type H = Fn(u8) -> (u8)::Output;
|
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
help: use fully-qualified syntax
|
|
|
|
|
LL | type H = <(dyn Fn(u8) -> u8 + 'static) as AsyncFnOnce>::Output;
|
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
LL | type H = <(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output;
|
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
error[E0223]: ambiguous associated type
|
|
--> $DIR/bad-assoc-ty.rs:39:19
|
|
|
|
|
LL | ($ty: ty) => ($ty::AssocTy);
|
|
| ^^^^^^^^^^^^
|
|
...
|
|
LL | type J = ty!(u8);
|
|
| ------- in this macro invocation
|
|
|
|
|
= note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
|
|
|
|
|
LL | ($ty: ty) => (<u8 as Example>::AssocTy);
|
|
| ~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
error[E0223]: ambiguous associated type
|
|
--> $DIR/bad-assoc-ty.rs:46:10
|
|
|
|
|
LL | type I = ty!()::AssocTy;
|
|
| ^^^^^^^^^^^^^^
|
|
|
|
|
help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
|
|
|
|
|
LL | type I = <u8 as Example>::AssocTy;
|
|
| ~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
|
--> $DIR/bad-assoc-ty.rs:51:13
|
|
|
|
|
LL | fn foo<X: K<_, _>>(x: X) {}
|
|
| ^ ^ not allowed in type signatures
|
|
| |
|
|
| not allowed in type signatures
|
|
|
|
|
help: use type parameters instead
|
|
|
|
|
LL | fn foo<X: K<T, T>, T>(x: X) {}
|
|
| ~ ~ +++
|
|
|
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
|
--> $DIR/bad-assoc-ty.rs:54:34
|
|
|
|
|
LL | fn bar<F>(_: F) where F: Fn() -> _ {}
|
|
| ^ not allowed in type signatures
|
|
|
|
|
help: use type parameters instead
|
|
|
|
|
LL | fn bar<F, T>(_: F) where F: Fn() -> T {}
|
|
| +++ ~
|
|
|
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
|
--> $DIR/bad-assoc-ty.rs:57:19
|
|
|
|
|
LL | fn baz<F: Fn() -> _>(_: F) {}
|
|
| ^ not allowed in type signatures
|
|
|
|
|
help: use type parameters instead
|
|
|
|
|
LL | fn baz<F: Fn() -> T, T>(_: F) {}
|
|
| ~+++
|
|
|
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
|
|
--> $DIR/bad-assoc-ty.rs:60:33
|
|
|
|
|
LL | struct L<F>(F) where F: Fn() -> _;
|
|
| ^ not allowed in type signatures
|
|
|
|
|
help: use type parameters instead
|
|
|
|
|
LL | struct L<F, T>(F) where F: Fn() -> T;
|
|
| +++ ~
|
|
|
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
|
|
--> $DIR/bad-assoc-ty.rs:62:30
|
|
|
|
|
LL | struct M<F> where F: Fn() -> _ {
|
|
| ^ not allowed in type signatures
|
|
|
|
|
help: use type parameters instead
|
|
|
|
|
LL | struct M<F, T> where F: Fn() -> T {
|
|
| +++ ~
|
|
|
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for enums
|
|
--> $DIR/bad-assoc-ty.rs:66:28
|
|
|
|
|
LL | enum N<F> where F: Fn() -> _ {
|
|
| ^ not allowed in type signatures
|
|
|
|
|
help: use type parameters instead
|
|
|
|
|
LL | enum N<F, T> where F: Fn() -> T {
|
|
| +++ ~
|
|
|
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for unions
|
|
--> $DIR/bad-assoc-ty.rs:71:29
|
|
|
|
|
LL | union O<F> where F: Fn() -> _ {
|
|
| ^ not allowed in type signatures
|
|
|
|
|
help: use type parameters instead
|
|
|
|
|
LL | union O<F, T> where F: Fn() -> T {
|
|
| +++ ~
|
|
|
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits
|
|
--> $DIR/bad-assoc-ty.rs:77:29
|
|
|
|
|
LL | trait P<F> where F: Fn() -> _ {
|
|
| ^ not allowed in type signatures
|
|
|
|
|
help: use type parameters instead
|
|
|
|
|
LL | trait P<F, T> where F: Fn() -> T {
|
|
| +++ ~
|
|
|
|
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
|
|
--> $DIR/bad-assoc-ty.rs:82:38
|
|
|
|
|
LL | fn foo<F>(_: F) where F: Fn() -> _ {}
|
|
| ^ not allowed in type signatures
|
|
|
|
|
help: use type parameters instead
|
|
|
|
|
LL | fn foo<F, T>(_: F) where F: Fn() -> T {}
|
|
| +++ ~
|
|
|
|
error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
|
|
--> $DIR/bad-assoc-ty.rs:73:5
|
|
|
|
|
LL | foo: F,
|
|
| ^^^^^^
|
|
|
|
|
= note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
|
|
help: wrap the field type in `ManuallyDrop<...>`
|
|
|
|
|
LL | foo: std::mem::ManuallyDrop<F>,
|
|
| +++++++++++++++++++++++ +
|
|
|
|
error: aborting due to 29 previous errors; 1 warning emitted
|
|
|
|
Some errors have detailed explanations: E0121, E0223, E0740.
|
|
For more information about an error, try `rustc --explain E0121`.
|