rust/library/core/src
Matthias Krüger 8c6cf3c934
Rollup merge of #119305 - compiler-errors:async-fn-traits, r=oli-obk
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).
2024-01-25 08:39:41 +01:00
..
alloc libs: use assert_unchecked instead of intrinsic 2024-01-13 20:10:00 +01:00
array Rollup merge of #117561 - tgross35:split-array, r=scottmcm 2024-01-19 19:26:59 +01:00
ascii fix Debug impl for AsciiChar 2023-09-01 12:29:40 +01:00
async_iter Rollup merge of #119222 - eholk:into-async-iterator, r=compiler-errors,dtolnay 2023-12-22 21:41:04 -05:00
cell Add some optimizations 2023-10-13 14:54:33 +02:00
char Use assert_unsafe_precondition for char::from_u32_unchecked 2023-12-15 15:15:24 +00:00
cmp Merge two different equality specialization traits in core 2023-03-01 14:42:06 -08:00
convert Add #[track_caller] to the "From implies Into" impl 2024-01-10 10:30:54 +01:00
ffi Update c_str.rs 2023-12-14 19:05:03 -05:00
fmt Remove dead codes in core 2023-12-12 07:03:37 +00:00
future Replace some usage of #[rustc_on_unimplemented] with 2024-01-05 15:23:09 +01:00
hash Add insta-stable std:#️⃣:{DefaultHasher, RandomState} exports 2023-11-02 20:35:20 -04:00
intrinsics Add Assume custom MIR. 2024-01-22 23:55:10 +00:00
io Move BorrowedBuf and BorrowedCursor from std:io to core::io 2023-11-09 07:10:11 +09:00
iter Auto merge of #120196 - matthiaskrgr:rollup-id2zocf, r=matthiaskrgr 2024-01-22 08:56:22 +00:00
macros Add #[coverage(off)] to closures introduced by #[test]/#[bench] 2024-01-21 23:17:00 +11:00
mem Auto merge of #111803 - scottmcm:simple-swap-alternative, r=Mark-Simulacrum 2024-01-20 21:54:44 +00:00
net Rollup merge of #119081 - jstasiak:is-ipv4-mapped, r=dtolnay 2024-01-21 06:38:35 +01:00
num Auto merge of #119911 - NCGThompson:is-statically-known, r=oli-obk 2024-01-25 05:16:53 +00:00
ops Rollup merge of #119305 - compiler-errors:async-fn-traits, r=oli-obk 2024-01-25 08:39:41 +01:00
panic Replace some usage of #[rustc_on_unimplemented] with 2024-01-05 15:23:09 +01:00
prelude Revert "Remove #[alloc_error_handler] from the compiler and library" 2023-04-25 00:08:35 +02:00
ptr update cfg(bootstrap)s 2023-12-22 11:14:11 +01:00
slice Auto merge of #119892 - joboet:libs_use_assert_unchecked, r=Nilstrieb,cuviper 2024-01-23 06:45:58 +00:00
str review 2024-01-21 20:12:00 +01:00
sync Docs: Use non-SeqCst in module example of atomics 2023-12-19 22:19:03 +01:00
task Change return type of unstable Waker::noop() from Waker to &Waker. 2024-01-17 11:53:16 -08:00
unicode Apply changes to fix python linting errors 2023-06-16 20:56:01 -04:00
any.rs update version placeholders 2023-12-22 11:01:42 +01:00
arch.rs use visibility to check unused imports and delete some stmts 2023-10-22 21:27:46 +08:00
ascii.rs optimize Cstr/EscapeAscii display 2023-06-29 01:55:03 +02:00
asserting.rs [RFC 2011] Library code 2022-05-22 07:18:32 -03:00
bool.rs core is now compilable 2023-04-16 07:20:26 +00:00
borrow.rs doc: replace wrong punctuation mark 2023-07-28 14:46:17 +02:00
cell.rs Use OnceCell in cell module documentation 2023-11-29 17:42:44 +01:00
clone.rs remove redundant imports 2023-12-10 10:56:22 +08:00
cmp.rs Rollup merge of #118714 - The-Ludwig:explain_ord_derive_enum_field, r=Nilstrieb 2024-01-22 07:56:41 +01:00
default.rs Add more diagnostic items for clippy 2023-10-05 18:21:47 -04:00
error.md Fix minor grammar typo 2023-09-06 09:47:22 -07:00
error.rs Spelling fix 2024-01-20 18:27:55 +00:00
escape.rs Re-format code with new rustfmt 2023-11-15 21:45:48 -05:00
hint.rs Fixed ambiguity in hint.rs 2024-01-04 15:48:22 -08:00
internal_macros.rs add track_caller for arith ops 2023-11-24 00:54:06 +08:00
intrinsics.rs Auto merge of #119911 - NCGThompson:is-statically-known, r=oli-obk 2024-01-25 05:16:53 +00:00
lib.rs Auto merge of #119911 - NCGThompson:is-statically-known, r=oli-obk 2024-01-25 05:16:53 +00:00
marker.rs Rephrase unpin docs in terms of pinning-agnosticness 2024-01-07 08:56:24 -08:00
option.rs chore: suggest wrapping in an assert!() instead 2024-01-21 18:39:09 +08:00
panic.rs merge core_panic feature into panic_internals 2023-12-09 14:49:00 +01:00
panicking.rs merge core_panic feature into panic_internals 2023-12-09 14:49:00 +01:00
pin.rs link 2024-01-07 08:57:23 -08:00
primitive.rs
primitive_docs.rs Rollup merge of #119907 - asquared31415:fn_trait_docs, r=Nilstrieb 2024-01-19 08:15:04 +01:00
result.rs Tune the inlinability of Result::unwrap 2024-01-12 10:57:58 -08:00
time.rs Add Duration::abs_diff 2023-11-05 19:45:17 +01:00
tuple.rs update cfg(bootstrap)s 2023-12-22 11:14:11 +01:00
unit.rs Use implicit capture syntax in format_args 2022-03-10 10:23:40 -05:00