Commit Graph

540 Commits

Author SHA1 Message Date
Oli Scherer
cb4751d4b8 Implement #[define_opaque] attribute for functions. 2025-03-11 12:05:02 +00:00
Moulins
b8a217081d Refactor coroutine layout logic to precompute all sublayouts
Also properly attaches spans on layouts of non-promoted coroutine
locals, which slightly improves the error messages for some coroutine tests.
2025-03-08 12:36:45 +01:00
Michael Goulet
1458b3560f
Rollup merge of #137910 - compiler-errors:async-fn-goal-error, r=oli-obk
Improve error message for `AsyncFn` trait failure for RPIT

Use a `WellFormedDerived` obligation cause to make sure we can turn an `AsyncFnKindHelper` trait goal into its parent `AsyncFn*` goal, then fix the logic for reporting `AsyncFn*` kind mismatches.

Best reviewed without whitespace.

Fixes #137905

r? oli-obk
2025-03-06 12:22:25 -05:00
Frank King
cb7d687e96 Implement &pin const self and &pin mut self sugars 2025-03-05 22:37:53 +08:00
Michael Goulet
0ad48b47e6 Do not recover missing lifetime with random in-scope lifetime 2025-03-03 05:57:55 +00:00
Michael Goulet
e213f4beea Improve error message for AsyncFn trait failure for RPIT 2025-03-03 04:09:43 +00:00
Michael Goulet
9313580e2a Don't suggest constraining unstable associated types 2025-02-25 20:02:01 +00:00
Esteban Küber
e565eeed78 Tweak E0277 when predicate comes indirectly from ?
When a `?` operation requires an `Into` conversion with additional bounds (like having a concrete error but wanting to convert to a trait object), we handle it speficically and provide the same kind of information we give other `?` related errors.

```
error[E0277]: `?` couldn't convert the error: `E: std::error::Error` is not satisfied
  --> $DIR/bad-question-mark-on-trait-object.rs:5:13
   |
LL | fn foo() -> Result<(), Box<dyn std::error::Error>> {
   |             -------------------------------------- required `E: std::error::Error` because of this
LL |     Ok(bar()?)
   |             ^ the trait `std::error::Error` is not implemented for `E`
   |
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = note: required for `Box<dyn std::error::Error>` to implement `From<E>`
```

Avoid talking about `FromResidual` when other more relevant information is being given, particularly from `rust_on_unimplemented`.
2025-02-20 18:15:39 +00:00
Jacob Pratt
575405161f
Rollup merge of #134090 - veluca93:stable-tf11, r=oli-obk
Stabilize target_feature_11

# Stabilization report

This is an updated version of https://github.com/rust-lang/rust/pull/116114, which is itself a redo of https://github.com/rust-lang/rust/pull/99767. Most of this commit and report were copied from those PRs. Thanks ```@LeSeulArtichaut``` and ```@calebzulawski!```

## Summary
Allows for safe functions to be marked with `#[target_feature]` attributes.

Functions marked with `#[target_feature]` are generally considered as unsafe functions: they are unsafe to call, cannot *generally* be assigned to safe function pointers, and don't implement the `Fn*` traits.

However, calling them from other `#[target_feature]` functions with a superset of features is safe.

```rust
// Demonstration function
#[target_feature(enable = "avx2")]
fn avx2() {}

fn foo() {
    // Calling `avx2` here is unsafe, as we must ensure
    // that AVX is available first.
    unsafe {
        avx2();
    }
}

#[target_feature(enable = "avx2")]
fn bar() {
    // Calling `avx2` here is safe.
    avx2();
}
```

Moreover, once https://github.com/rust-lang/rust/pull/135504 is merged, they can be converted to safe function pointers in a context in which calling them is safe:

```rust
// Demonstration function
#[target_feature(enable = "avx2")]
fn avx2() {}

fn foo() -> fn() {
    // Converting `avx2` to fn() is a compilation error here.
    avx2
}

#[target_feature(enable = "avx2")]
fn bar() -> fn() {
    // `avx2` coerces to fn() here
    avx2
}
```

See the section "Closures" below for justification of this behaviour.

## Test cases
Tests for this feature can be found in [`tests/ui/target_feature/`](f6cb952dc1/tests/ui/target-feature).

## Edge cases
### Closures
 * [target-feature 1.1: should closures inherit target-feature annotations? #73631](https://github.com/rust-lang/rust/issues/73631)

Closures defined inside functions marked with #[target_feature] inherit the target features of their parent function. They can still be assigned to safe function pointers and implement the appropriate `Fn*` traits.

```rust
#[target_feature(enable = "avx2")]
fn qux() {
    let my_closure = || avx2(); // this call to `avx2` is safe
    let f: fn() = my_closure;
}
```
This means that in order to call a function with #[target_feature], you must guarantee that the target-feature is available while the function, any closures defined inside it, as well as any safe function pointers obtained from target-feature functions inside it, execute.

This is usually ensured because target features are assumed to never disappear, and:
- on any unsafe call to a `#[target_feature]` function, presence of the target feature is guaranteed by the programmer through the safety requirements of the unsafe call.
- on any safe call, this is guaranteed recursively by the caller.

If you work in an environment where target features can be disabled, it is your responsibility to ensure that no code inside a target feature function (including inside a closure) runs after this (until the feature is enabled again).

**Note:** this has an effect on existing code, as nowadays closures do not inherit features from the enclosing function, and thus this strengthens a safety requirement. It was originally proposed in #73631 to solve this by adding a new type of UB: “taking a target feature away from your process after having run code that uses that target feature is UB” .
This was motivated by userspace code already assuming in a few places that CPU features never disappear from a program during execution (see i.e. 2e29bdf908/crates/std_detect/src/detect/arch/x86.rs); however, concerns were raised in the context of the Linux kernel; thus, we propose to relax that requirement to "causing the set of usable features to be reduced is unsafe; when doing so, the programmer is required to ensure that no closures or safe fn pointers that use removed features are still in scope".

* [Fix #[inline(always)] on closures with target feature 1.1 #111836](https://github.com/rust-lang/rust/pull/111836)

Closures accept `#[inline(always)]`, even within functions marked with `#[target_feature]`. Since these attributes conflict, `#[inline(always)]` wins out to maintain compatibility.

### ABI concerns
* [The extern "C" ABI of SIMD vector types depends on target features #116558](https://github.com/rust-lang/rust/issues/116558)

The ABI of some types can change when compiling a function with different target features. This could have introduced unsoundness with target_feature_11, but recent fixes (#133102, #132173) either make those situations invalid or make the ABI no longer dependent on features. Thus, those issues should no longer occur.

### Special functions
The `#[target_feature]` attribute is forbidden from a variety of special functions, such as main, current and future lang items (e.g. `#[start]`, `#[panic_handler]`), safe default trait implementations and safe trait methods.

This was not disallowed at the time of the first stabilization PR for target_features_11, and resulted in the following issues/PRs:
* [`#[target_feature]` is allowed on `main` #108645](https://github.com/rust-lang/rust/issues/108645)
* [`#[target_feature]` is allowed on default implementations #108646](https://github.com/rust-lang/rust/issues/108646)
* [#[target_feature] is allowed on #[panic_handler] with target_feature 1.1 #109411](https://github.com/rust-lang/rust/issues/109411)
* [Prevent using `#[target_feature]` on lang item functions #115910](https://github.com/rust-lang/rust/pull/115910)

## Documentation
 * Reference: [Document the `target_feature_11` feature reference#1181](https://github.com/rust-lang/reference/pull/1181)
---

cc tracking issue https://github.com/rust-lang/rust/issues/69098
cc ```@workingjubilee```
cc ```@RalfJung```
r? ```@rust-lang/lang```
2025-02-12 20:09:56 -05:00
Michael Goulet
6ffe6dd826 Check sig for errors before checking for unconstrained anonymous lifetime 2025-02-11 22:59:57 +00:00
Esteban Küber
f0845adb0c Show diff suggestion format on verbose replacement
```
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
  --> $DIR/attempted-access-non-fatal.rs:7:15
   |
LL |     let _ = 2.l;
   |               ^
   |
help: if intended to be a floating point literal, consider adding a `0` after the period and a `f64` suffix
   |
LL -     let _ = 2.l;
LL +     let _ = 2.0f64;
   |
```
2025-02-10 20:21:39 +00:00
Michael Goulet
d0b0b028a6 Eagerly detect coroutine recursion pre-mono when possible 2025-02-05 18:36:17 +00:00
Matthias Krüger
dc4d38740e
Rollup merge of #136414 - estebank:expected-return-type, r=oli-obk
Shorten error message for callable with wrong return type

```
error: expected `{closure@...}` to return `Ret`, but it returns `Other`
```
instead of
```
error: expected `{closure@...}` to be a closure that returns `Ret`, but it returns `Other`
```
2025-02-02 23:06:55 +01:00
Esteban Küber
9ebbba4ad9 Shorten error message for callable with wrong return type
```
error: expected `{closure@...}` to return `Ret`, but it returns `Other`
```
instead of
```
error: expected `{closure@...}` to be a closure that returns `Ret`, but it returns `Other`
```
2025-02-02 01:00:33 +00:00
bors
854f22563c Auto merge of #136350 - matthiaskrgr:rollup-6eqfyvh, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #134531 ([rustdoc] Add `--extract-doctests` command-line flag)
 - #135860 (Compiler: Finalize dyn compatibility renaming)
 - #135992 (Improve documentation when adding a new target)
 - #136194 (Support clobber_abi in BPF inline assembly)
 - #136325 (Delay a bug when indexing unsized slices)
 - #136326 (Replace our `LLVMRustDIBuilderRef` with LLVM-C's `LLVMDIBuilderRef`)
 - #136330 (Remove unnecessary hooks)
 - #136336 (Overhaul `rustc_middle::util`)
 - #136341 (Remove myself from vacation)

r? `@ghost`
`@rustbot` modify labels: rollup
2025-01-31 20:16:46 +00:00
Matthias Krüger
308ea7120b
Rollup merge of #135860 - fmease:compiler-mv-obj-save-dyn-compat-ii, r=jieyouxu
Compiler: Finalize dyn compatibility renaming

Update the Reference link to use the new URL fragment from https://github.com/rust-lang/reference/pull/1666 (this change has finally hit stable). Fixes a FIXME.

Follow-up to #130826.
Part of #130852.

~~Blocking it on #133372.~~ (merged)

r? ghost
2025-01-31 12:28:15 +01:00
Esteban Küber
87d323c81e Add closure labels 2025-01-30 18:38:42 +00:00
Esteban Küber
d3a148fe07 When encountering unexpected closure return type, point at return type/expression
```
error[E0271]: expected `{closure@fallback-closure-wrap.rs:18:40}` to be a closure that returns `()`, but it returns `!`
  --> $DIR/fallback-closure-wrap.rs:19:9
   |
LL |     let error = Closure::wrap(Box::new(move || {
   |                                        -------
LL |         panic!("Can't connect to server.");
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `!`
   |
   = note: expected unit type `()`
                   found type `!`
   = note: required for the cast from `Box<{closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47}>` to `Box<dyn FnMut()>`
```

```
error[E0271]: expected `{closure@dont-ice-for-type-mismatch-in-closure-in-async.rs:6:10}` to be a closure that returns `bool`, but it returns `Option<()>`
  --> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:6:16
   |
LL |     call(|| -> Option<()> {
   |     ---- ------^^^^^^^^^^
   |     |          |
   |     |          expected `bool`, found `Option<()>`
   |     required by a bound introduced by this call
   |
   = note: expected type `bool`
              found enum `Option<()>`
note: required by a bound in `call`
  --> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:3:25
   |
LL | fn call(_: impl Fn() -> bool) {}
   |                         ^^^^ required by this bound in `call`
```

```
error[E0271]: expected `{closure@f670.rs:28:13}` to be a closure that returns `Result<(), _>`, but it returns `!`
    --> f670.rs:28:20
     |
28   |     let c = |e| -> ! {
     |             -------^
     |                    |
     |                    expected `Result<(), _>`, found `!`
...
32   |     f().or_else(c);
     |         ------- required by a bound introduced by this call
-Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs:1433:28
     |
     = note: expected enum `Result<(), _>`
                found type `!`
note: required by a bound in `Result::<T, E>::or_else`
    --> /home/gh-estebank/rust/library/core/src/result.rs:1406:39
     |
1406 |     pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> {
     |                                       ^^^^^^^^^^^^ required by this bound in `Result::<T, E>::or_else`
```
2025-01-30 18:38:37 +00:00
Caleb Zulawski
44b2e6c07d Stabilize target_feature_11 2025-01-27 23:44:47 +01:00
Guillaume Gomez
f4a5cbd0d8
Rollup merge of #136112 - fmease:clean-up-all-dead-files-in-ui-tests, r=compiler-errors
Clean up all dead files inside `tests/ui/`

While rebasing #135860 I noticed that there are several dead `*.stderr` files inside `tests/ui/`.

When I checked thoroughly, I found 69 dead `*.$revision.stderr` files, 3 other dead `*.stderr` files and one dead `*.rs` file.

Prior to #134808, compiletest's `--bless` didn't remove dead `*.stderr` files when the set of revisions changed in any way (renamings, removals, additions, …) which explains their existence.

Regarding the dead `*.rs` file, that one was located inside an `auxiliary/` directory (together with a `*.stderr` file) despite not being meant to be an auxiliary file (it's not referenced by any `//@ aux-*`, it has an accompanying `*.stderr` file and it's obvious from looking at #111056 which added it). Ideally compiletest or tidy would forbid `*.std{out,err}` files inside `auxiliary/` dirs, that would've caught it. I moved it, updated it and turned it into a proper UI test.

---

How to reproduce:

1. Run `rm tests/ui/**/*.stderr`
2. Run `./x test tests/ui --bless` (or similar)
3. Manually / semi-automatically go through all tests that were ignored (likely due to your OS etc. not matching) and restore any stderr files that were overzealously removed

---

r? compiler
2025-01-27 15:38:29 +01:00
León Orell Valerian Liehr
0b18b4fbbc
Remove all dead files inside tests/ui/ 2025-01-27 02:28:04 +01:00
León Orell Valerian Liehr
57b5d3af62
Compiler: Finalize dyn compatibility renaming 2025-01-26 21:20:31 +01:00
Michael Goulet
d7a6fdc71f Add cache to FoldEscapingRegions 2025-01-26 18:27:58 +00:00
Matthias Krüger
4496f23ca9
Rollup merge of #135492 - metamuffin:bug-invalid-await-suggest, r=compiler-errors
Add missing check for async body when suggesting await on futures.

Currently the compiler suggests adding `.await` to resolve some type conflicts without checking if the conflict happens in an async context. This can lead to the compiler suggesting `.await` in function signatures where it is invalid. Example:

```rs
trait A {
    fn a() -> impl Future<Output = ()>;
}
struct B;
impl A for B {
    fn a() -> impl Future<Output = impl Future<Output = ()>> {
        async { async { () } }
    }
}
```
```
error[E0271]: expected `impl Future<Output = impl Future<Output = ()>>` to be a future that resolves to `()`, but it resolves to `impl Future<Output = ()>`
 --> bug.rs:6:15
  |
6 |     fn a() -> impl Future<Output = impl Future<Output = ()>> {
  |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found future
  |
note: calling an async function returns a future
 --> bug.rs:6:15
  |
6 |     fn a() -> impl Future<Output = impl Future<Output = ()>> {
  |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `A::{synthetic#0}`
 --> bug.rs:2:27
  |
2 |     fn a() -> impl Future<Output = ()>;
  |                           ^^^^^^^^^^^ required by this bound in `A::{synthetic#0}`
help: consider `await`ing on the `Future`
  |
6 |     fn a() -> impl Future<Output = impl Future<Output = ()>>.await {
  |                                                             ++++++
```

The documentation of suggest_await_on_expect_found (`compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs:156`) even mentions such a check but does not actually implement it.

This PR adds that check to ensure `.await` is only suggested within async blocks.

There were 3 unit tests whose expected output needed to be changed because they had the suggestion outside of async. One of them (`tests/ui/async-await/dont-suggest-missing-await.rs`) actually tests that exact problem but expects it to be present.

Thanks to `@llenck` for initially noticing the bug and helping with fixing it
2025-01-23 19:54:24 +01:00
Matthias Krüger
ef0e6863c6
Rollup merge of #135816 - BoxyUwU:root_normalizes_to_goal_ice, r=lcnr
Use `structurally_normalize` instead of manual `normalizes-to` goals in alias relate errors

r? `@lcnr`

I added `structurally_normalize_term` so that code that is generic over ty or const can use the structurally normalize helpers. See `tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.rs` for a description of the reason for the (now fixed) ICEs
2025-01-22 19:29:39 +01:00
Taylor Cramer
d00d4dfe0d Refactor dyn-compatibility error and suggestions
This CL makes a number of small changes to dyn compatibility errors:
- "object safety" has been renamed to "dyn-compatibility" throughout
- "Convert to enum" suggestions are no longer generated when there
  exists a type-generic impl of the trait or an impl for `dyn OtherTrait`
- Several error messages are reorganized for user readability

Additionally, the dyn compatibility error creation code has been
split out into functions.

cc #132713
cc #133267
2025-01-22 09:20:57 -08:00
Boxy
513bfaa8bc Use structurally_normalize instead of manual normalizes-to goals 2025-01-22 07:04:53 +00:00
Ralf Jung
56c90dc31e remove support for the #[start] attribute 2025-01-21 06:59:15 -07:00
metamuffin
ab2c8ffda9
Add missing check for async body when suggesting await on futures. 2025-01-16 21:34:40 +01:00
Oli Scherer
50654e5384 Render fn defs with target_features attrs with the attribute 2025-01-15 08:58:17 +00:00
Oli Scherer
56178ddc90 Treat safe target_feature functions as unsafe by default 2025-01-15 08:58:17 +00:00
dianne
31e4d8175a best_blame_constraint: avoid blaming constraints from MIR generated by desugaring 2025-01-06 16:12:11 -08:00
dianne
ac922245f0 best_blame_constraint: don't filter constraints by sup SCC
The SCCs of the region graph are not a reliable heuristic to use for blaming an interesting
constraint for diagnostics. For region errors, if the outlived region is `'static`, or the involved
types are invariant in their lifetiems, there will be cycles in the constraint graph containing both
the target region and the most interesting constraints to blame. To get better diagnostics in these
cases, this commit removes that heuristic.
2025-01-06 16:08:29 -08:00
Michael Goulet
8e344ae127 Suppress type param suggestion if encountering invalid const infer 2025-01-02 23:39:16 +00:00
Michael Goulet
6885ff4a7b Unconditionally lower generic_arg_infer 2025-01-02 23:39:16 +00:00
Michael Goulet
ed9a4cfdeb Make sure we check the future type is Sized in AsyncFn* 2024-12-31 00:46:46 +00:00
Michael Goulet
9bcd1dee95 Actually print all the relevant parts of a coroutine in verbose mode 2024-12-25 01:08:59 +00:00
bors
ed14192604 Auto merge of #134294 - matthiaskrgr:rollup-anh6io8, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #134252 (Fix `Path::is_absolute` on Hermit)
 - #134254 (Fix building `std` for Hermit after `c_char` change)
 - #134255 (Update includes in `/library/core/src/error.rs`.)
 - #134261 (Document the symbol Visibility enum)
 - #134262 (Arbitrary self types v2: adjust diagnostic.)
 - #134265 (Rename `ty_def_id` so people will stop using it by accident)
 - #134271 (Arbitrary self types v2: better feature gate test)
 - #134274 (Add check-pass test for `&raw`)

r? `@ghost`
`@rustbot` modify labels: rollup
2024-12-14 06:44:05 +00:00
Matthias Krüger
2846699366
Rollup merge of #134181 - estebank:trim-render, r=oli-obk
Tweak multispan rendering to reduce output length

Consider comments and bare delimiters the same as an "empty line" for purposes of hiding rendered code output of long multispans. This results in more aggressive shortening of rendered output without losing too much context, specially in `*.stderr` tests that have "hidden" comments. We do that check not only on the first 4 lines of the multispan, but now also on the previous to last line as well.
2024-12-14 03:54:31 +01:00
Adrian Taylor
174dae607c Arbitrary self types v2: adjust diagnostic.
The recently landed PR to adjust arbitrary self types was a bit
overenthusiastic, advising folks to use the new Receiver trait even
before it's been stabilized. Revert to the older wording of the lint in
such cases.
2024-12-13 15:40:37 +00:00
bors
f4f0fafd0c Auto merge of #132706 - compiler-errors:async-closures, r=oli-obk
Stabilize async closures (RFC 3668)

# Async Closures Stabilization Report

This report proposes the stabilization of `#![feature(async_closure)]` ([RFC 3668](https://rust-lang.github.io/rfcs/3668-async-closures.html)). This is a long-awaited feature that increases the expressiveness of the Rust language and fills a pressing gap in the async ecosystem.

## Stabilization summary

* You can write async closures like `async || {}` which return futures that can borrow from their captures and can be higher-ranked in their argument lifetimes.
* You can express trait bounds for these async closures using the `AsyncFn` family of traits, analogous to the `Fn` family.

```rust
async fn takes_an_async_fn(f: impl AsyncFn(&str)) {
    futures::join(f("hello"), f("world")).await;
}

takes_an_async_fn(async |s| { other_fn(s).await }).await;
```

## Motivation

Without this feature, users hit two major obstacles when writing async code that uses closures and `Fn` trait bounds:

- The inability to express higher-ranked async function signatures.
- That closures cannot return futures that borrow from the closure captures.

That is, for the first, we cannot write:

```rust
// We cannot express higher-ranked async function signatures.
async fn f<Fut>(_: impl for<'a> Fn(&'a u8) -> Fut)
where
    Fut: Future<Output = ()>,
{ todo!() }

async fn main() {
    async fn g(_: &u8) { todo!() }
    f(g).await;
    //~^ ERROR mismatched types
    //~| ERROR one type is more general than the other
}
```

And for the second, we cannot write:

```rust
// Closures cannot return futures that borrow closure captures.
async fn f<Fut: Future<Output = ()>>(_: impl FnMut() -> Fut)
{ todo!() }

async fn main() {
    let mut xs = vec![];
    f(|| async {
        async fn g() -> u8 { todo!() }
        xs.push(g().await);
    });
    //~^ ERROR captured variable cannot escape `FnMut` closure body
}
```

Async closures provide a first-class solution to these problems.

For further background, please refer to the [motivation section](https://rust-lang.github.io/rfcs/3668-async-closures.html#motivation) of the RFC.

## Major design decisions since RFC

The RFC had left open the question of whether we would spell the bounds syntax for async closures...

```rust
// ...as this...
fn f() -> impl AsyncFn() -> u8 { todo!() }
// ...or as this:
fn f() -> impl async Fn() -> u8 { todo!() }
```

We've decided to spell this as `AsyncFn{,Mut,Once}`.

The `Fn` family of traits is special in many ways.  We had originally argued that, due to this specialness, that perhaps the `async Fn` syntax could be adopted without having to decide whether a general `async Trait` mechanism would ever be adopted.  However, concerns have been raised that we may not want to use `async Fn` syntax unless we would pursue more general trait modifiers.  Since there remain substantial open questions on those -- and we don't want to rush any design work there -- it makes sense to ship this needed feature using the `AsyncFn`-style bounds syntax.

Since we would, in no case, be shipping a generalized trait modifier system anytime soon, we'll be continuing to see `AsyncFoo` traits appear across the ecosystem regardless.  If we were to ever later ship some general mechanism, we could at that time manage the migration from `AsyncFn` to `async Fn`, just as we'd be enabling and managing the migration of many other traits.

Note that, as specified in RFC 3668, the details of the `AsyncFn*` traits are not exposed and they can only be named via the "parentheses sugar".  That is, we can write `T: AsyncFn() -> u8` but not `T: AsyncFn<Output = u8>`.

Unlike the `Fn` traits, we cannot project to the `Output` associated type of the `AsyncFn` traits.  That is, while we can write...

```rust
fn f<F: Fn() -> u8>(_: F::Output) {}
```

...we cannot write:

```rust
fn f<F: AsyncFn() -> u8>(_: F::Output) {}
//~^ ERROR
```

The choice of `AsyncFn{,Mut,Once}` bounds syntax obviates, for our purposes here, another question decided after that RFC, which was how to order bound modifiers such as `for<'a> async Fn()`.

Other than answering the open question in the RFC on syntax, nothing has changed about the design of this feature between RFC 3668 and this stabilization.

## What is stabilized

For those interested in the technical details, please see [the dev guide section](https://rustc-dev-guide.rust-lang.org/coroutine-closures.html) I authored.

#### Async closures

Other than in how they solve the problems described above, async closures act similarly to closures that return async blocks, and can have parts of their signatures specified:

```rust
// They can have arguments annotated with types:
let _ = async |_: u8| { todo!() };

// They can have their return types annotated:
let _ = async || -> u8 { todo!() };

// They can be higher-ranked:
let _ = async |_: &str| { todo!() };

// They can capture values by move:
let x = String::from("hello, world");
let _ = async move || do_something(&x).await };
```

When called, they return an anonymous future type corresponding to the (not-yet-executed) body of the closure. These can be awaited like any other future.

What distinguishes async closures is that, unlike closures that return async blocks, the futures returned from the async closure can capture state from the async closure. For example:

```rust
let vec: Vec<String> = vec![];

let closure = async || {
    vec.push(ready(String::from("")).await);
};
```

The async closure captures `vec` with some `&'closure mut Vec<String>` which lives until the closure is dropped. Every call to `closure()` returns a future which reborrows that mutable reference `&'call mut Vec<String>` which lives until the future is dropped (e.g. it is `await`ed).

As another example:

```rust
let string: String = "Hello, world".into();

let closure = async move || {
    ready(&string).await;
};
```

The closure is marked with `move`, which means it takes ownership of the string by *value*. The future that is returned by calling `closure()` returns a future which borrows a reference `&'call String` which lives until the future is dropped (e.g. it is `await`ed).

#### Async fn trait family

To support the lending capability of async closures, and to provide a first-class way to express higher-ranked async closures, we introduce the `AsyncFn*` family of traits. See the [corresponding section](https://rust-lang.github.io/rfcs/3668-async-closures.html#asyncfn) of the RFC.

We stabilize naming `AsyncFn*` via the "parenthesized sugar" syntax that normal `Fn*` traits can be named. The `AsyncFn*` trait can be used anywhere a `Fn*` trait bound is allowed, such as:

```rust
/// In return-position impl trait:
fn closure() -> impl AsyncFn() { async || {} }

/// In trait bounds:
trait Foo<F>: Sized
where
    F: AsyncFn()
{
    fn new(f: F) -> Self;
}

/// in GATs:
trait Gat {
    type AsyncHasher<T>: AsyncFn(T) -> i32;
}
```

Other than using them in trait bounds, the definitions of these traits are not directly observable, but certain aspects of their behavior can be indirectly observed such as the fact that:

* `AsyncFn::async_call` and `AsyncFnMut::async_call_mut` return a future which is *lending*, and therefore borrows the `&self` lifetime of the callee.

```rust
fn by_ref_call(c: impl AsyncFn()) {
    let fut = c();
    drop(c);
    //   ^ Cannot drop `c` since it is borrowed by `fut`.
}
```

* `AsyncFnOnce::async_call_once` returns a future that takes ownership of the callee.

```rust
fn by_ref_call(c: impl AsyncFnOnce()) {
    let fut = c();
    let _ = c();
    //      ^ Cannot call `c` since calling it takes ownership the callee.
}
```

* All currently-stable callable types (i.e., closures, function items, function pointers, and `dyn Fn*` trait objects) automatically implement `AsyncFn*() -> T` if they implement `Fn*() -> Fut` for some output type `Fut`, and `Fut` implements `Future<Output = T>`.
    * This is to make sure that `AsyncFn*()` trait bounds have maximum compatibility with existing callable types which return futures, such as async function items and closures which return boxed futures.
    * For now, this only works currently for *concrete* callable types -- for example, a argument-position impl trait like `impl Fn() -> impl Future<Output = ()>` does not implement `AsyncFn()`, due to the fact that a `AsyncFn`-if-`Fn` blanket impl does not exist in reality. This may be relaxed in the future. Users can work around this by wrapping their type in an async closure and calling it. I expect this to not matter much in practice, as users are encouraged to write `AsyncFn` bounds directly.

```rust
fn is_async_fn(_: impl AsyncFn(&str)) {}

async fn async_fn_item(s: &str) { todo!() }
is_async_fn(s);
// ^^^ This works.

fn generic(f: impl Fn() -> impl Future<Output = ()>) {
    is_async_fn(f);
    // ^^^ This does not work (yet).
}
```

#### The by-move future

When async closures are called with `AsyncFn`/`AsyncFnMut`, they return a coroutine that borrows from the closure. However, when they are called via `AsyncFnOnce`, we consume that closure, and cannot return a coroutine that borrows from data that is now dropped.

To work around around this limitation, we synthesize a separate future type for calling the async closure via `AsyncFnOnce`.

This future executes identically to the by-ref future returned from calling the async closure, except for the fact that it has a different set of captures, since we must *move* the captures from the parent async into the child future.

#### Interactions between async closures and the `Fn*` family of traits

Async closures always implement `FnOnce`, since they always can be called once. They may also implement `Fn` or `FnMut` if their body is compatible with the calling mode (i.e. if they do not mutate their captures, or they do not capture their captures, respectively) and if the future returned by the async closure is not *lending*.

```rust
let id = String::new();

let mapped: Vec</* impl Future */> =
    [/* elements */]
    .into_iter()
    // `Iterator::map` takes an `impl FnMut`
    .map(async |element| {
        do_something(&id, element).await;
    })
    .collect();
```

See [the dev guide](https://rustc-dev-guide.rust-lang.org/coroutine-closures.html#follow-up-when-do-async-closures-implement-the-regular-fn-traits) for a detailed explanation for the situations where this may not be possible due to the lending nature of async closures.

#### Other notable features of async closures shared with synchronous closures

* Async closures are `Copy` and/or `Clone` if their captures are `Copy`/`Clone`.
* Async closures do closure signature inference: If an async closure is passed to a function with a `AsyncFn` or `Fn` trait bound, we can eagerly infer the argument types of the closure. More details are provided in [the dev guide](https://rustc-dev-guide.rust-lang.org/coroutine-closures.html#closure-signature-inference).

#### Lints

This PR also stabilizes the `CLOSURE_RETURNING_ASYNC_BLOCK` lint as an `allow` lint. This lints on "old-style" async closures:

```rust
#![warn(closure_returning_async_block)]
let c = |x: &str| async {};
```

We should encourage users to use `async || {}` where possible. This lint remains `allow` and may be refined in the future because it has a few false positives (namely, see: "Where do we expect rewriting `|| async {}` into `async || {}` to fail?")

An alternative that could be made at the time of stabilization is to put this lint behind another gate, so we can decide to stabilize it later.

## What isn't stabilized (aka, potential future work)

#### `async Fn*()` bound syntax

We decided to stabilize async closures without the `async Fn*()` bound modifier syntax. The general direction of this syntax and how it fits is still being considered by T-lang (e.g. in [RFC 3710](https://github.com/rust-lang/rfcs/pull/3710)).

#### Naming the futures returned by async closures

This stabilization PR does not provide a way of naming the futures returned by calling `AsyncFn*`.

Exposing a stable way to refer to these futures is important for building async-closure-aware combinators, and will be an important future step.

#### Return type notation-style bounds for async closures

The RFC described an RTN-like syntax for putting bounds on the future returned by an async closure:

```rust
async fn foo(x: F) -> Result<()>
where
    F: AsyncFn(&str) -> Result<()>,
    // The future from calling `F` is `Send` and `'static`.
    F(..): Send + 'static,
{}
```

This stabilization PR does not stabilize that syntax yet, which remains unimplemented (though will be soon).

#### `dyn AsyncFn*()`

`AsyncFn*` are not dyn-compatible yet. This will likely be implemented in the future along with the dyn-compatibility of async fn in trait, since the same issue (dealing with the future returned by a call) applies there.

## Tests

Tests exist for this feature in [`tests/ui/async-await/async-closures`](5b54286640/tests/ui/async-await/async-closures).

<details>
    <summary>A selected set of tests:</summary>

* Lending behavior of async closures
    * `tests/ui/async-await/async-closures/mutate.rs`
    * `tests/ui/async-await/async-closures/captures.rs`
    * `tests/ui/async-await/async-closures/precise-captures.rs`
    * `tests/ui/async-await/async-closures/no-borrow-from-env.rs`
* Async closures may be higher-ranked
    * `tests/ui/async-await/async-closures/higher-ranked.rs`
    * `tests/ui/async-await/async-closures/higher-ranked-return.rs`
* Async closures may implement `Fn*` traits
    * `tests/ui/async-await/async-closures/is-fn.rs`
    * `tests/ui/async-await/async-closures/implements-fnmut.rs`
* Async closures may be cloned
    * `tests/ui/async-await/async-closures/clone-closure.rs`
* Ownership of the upvars when `AsyncFnOnce` is called
    * `tests/ui/async-await/async-closures/drop.rs`
    * `tests/ui/async-await/async-closures/move-is-async-fn.rs`
    * `tests/ui/async-await/async-closures/force-move-due-to-inferred-kind.rs`
    * `tests/ui/async-await/async-closures/force-move-due-to-actually-fnonce.rs`
* Closure signature inference
    * `tests/ui/async-await/async-closures/signature-deduction.rs`
    * `tests/ui/async-await/async-closures/sig-from-bare-fn.rs`
    * `tests/ui/async-await/async-closures/signature-inference-from-two-part-bound.rs`

</details>

## Remaining bugs and open issues

* https://github.com/rust-lang/rust/issues/120694 tracks moving onto more general `LendingFn*` traits. No action needed, since it's not observable.
* https://github.com/rust-lang/rust/issues/124020 - Polymorphization ICE. Polymorphization needs to be heavily reworked. No action needed.
* https://github.com/rust-lang/rust/issues/127227 - Tracking reworking the way that rustdoc re-sugars bounds.
    * The part relevant to to `AsyncFn` is fixed by https://github.com/rust-lang/rust/pull/132697.

## Where do we expect rewriting `|| async {}` into `async || {}` to fail?

* Fn pointer coercions
    * Currently, it is not possible to coerce an async closure to an fn pointer like regular closures can be. This functionality may be implemented in the future.
```rust
let x: fn() -> _ = async || {};
```
* Argument capture
    * Like async functions, async closures always capture their input arguments. This is in contrast to something like `|t: T| async {}`, which doesn't capture `t` unless it is used in the async block. This may affect the `Send`-ness of the future or affect its outlives.
```rust
fn needs_send_future(_: impl Fn(NotSendArg) -> Fut)
where
    Fut: Future<Output = ()>,
{}

needs_send_future(async |_| {});
```

## History

#### Important feature history

- https://github.com/rust-lang/rust/pull/51580
- https://github.com/rust-lang/rust/pull/62292
- https://github.com/rust-lang/rust/pull/120361
- https://github.com/rust-lang/rust/pull/120712
- https://github.com/rust-lang/rust/pull/121857
- https://github.com/rust-lang/rust/pull/123660
- https://github.com/rust-lang/rust/pull/125259
- https://github.com/rust-lang/rust/pull/128506
- https://github.com/rust-lang/rust/pull/127482

## Acknowledgements

Thanks to `@oli-obk` for reviewing the bulk of the work for this feature. Thanks to `@nikomatsakis` for his design blog posts which generated interest for this feature, `@traviscross` for feedback and additions to this stabilization report. All errors are my own.

r? `@ghost`
2024-12-13 00:37:51 +00:00
Michael Goulet
c605c84be8 Stabilize async closures 2024-12-13 00:04:56 +00:00
Esteban Küber
49a22a4245 Filter empty lines, comments and delimiters from previous to last multiline span rendering 2024-12-12 23:36:27 +00:00
Esteban Küber
65a54a7f27 Tweak multispan rendering
Consider comments and bare delimiters the same as an "empty line" for purposes of hiding rendered code output of long multispans. This results in more aggressive shortening of rendered output without losing too much context, specially in `*.stderr` tests that have "hidden" comments.
2024-12-12 23:36:27 +00:00
bors
915e7eb9b9 Auto merge of #132961 - adetaylor:arbitrary-self-types-the-big-bit, r=compiler-errors,wesleywiser
Arbitrary self types v2: main compiler changes

This is the main PR in a series of PRs related to Arbitrary Self Types v2, tracked in #44874. Specifically this is step 7 of the plan [described here](https://github.com/rust-lang/rust/issues/44874#issuecomment-2122179688), for [RFC 3519](https://github.com/rust-lang/rfcs/pull/3519).

Overall this PR:
* Switches from the `Deref` trait to the new `Receiver` trait when the unstable `arbitrary_self_types` feature is enabled (the simple bit)
* Introduces new algorithms to spot "shadowing"; that is, the case where a newly-added method in an outer smart pointer might end up overriding a pre-existing method in the pointee (the complex bit). Most of this bit was explored in [this earlier perf-testing PR](https://github.com/rust-lang/rust/pull/127812#issuecomment-2236911900).
* Lots of tests

This should not break compatibility for:
* Stable users, where it should have no effect
* Users of the existing `arbitrary_self_types` feature (because we implement `Receiver` for `T: Deref`) _unless_ those folks have added methods which may shadow methods in inner types, which we no longer want to allow

Subsequent PRs will add better diagnostics.

It's probably easiest to review this commit-by-commit.

r? `@wesleywiser`
2024-12-12 21:40:39 +00:00
Adrian Taylor
e75660dad3 Arbitrary self types v2: use Receiver trait
In this new version of Arbitrary Self Types, we no longer use the Deref trait
exclusively when working out which self types are valid. Instead, we follow a
chain of Receiver traits. This enables methods to be called on smart pointer
types which fundamentally cannot support Deref (for instance because they are
wrappers for pointers that don't follow Rust's aliasing rules).

This includes:
* Changes to tests appropriately
* New tests for:
  * The basics of the feature
  * Ensuring lifetime elision works properly
  * Generic Receivers
  * A copy of the method subst test enhanced with Receiver

This is really the heart of the 'arbitrary self types v2' feature, and
is the most critical commit in the current PR.

Subsequent commits are focused on:
* Detecting "shadowing" problems, where a smart pointer type can hide
  methods in the pointee.
* Diagnostics and cleanup.

Naming: in this commit, the "Autoderef" type is modified so that it no
longer solely focuses on the "Deref" trait, but can now consider the
"Receiver" trait instead. Should it be renamed, to something like
"TraitFollower"? This was considered, but rejected, because
* even in the Receiver case, it still considers built-in derefs
* the name Autoderef is short and snappy.
2024-12-11 11:59:12 +00:00
Michael Goulet
a7fa4cbcb4 Implement projection and shim for AFIDT 2024-12-10 16:52:20 +00:00
León Orell Valerian Liehr
193a95d30b
Rollup merge of #134017 - compiler-errors:call-once-deduction, r=jieyouxu
Don't use `AsyncFnOnce::CallOnceFuture` bounds for signature deduction

We shouldn't be using `AsyncFnOnce::CallOnceFuture` projection bounds to deduce anything about the return type of an async closure, **only** `AsyncFnOnce::Output`. This was accidental b/c all we were looking at was the def id of the trait, rather than the projection. This PR fixes that.

This doesn't affect stable code, since `CallOnceFuture` bounds cannot be written on stable.

Fixes #134015
2024-12-10 13:51:10 +01:00
Michael Goulet
88669aed22 Don't use AsyncFnOnce::CallOnceFuture bounds for signature deduction 2024-12-08 00:01:21 +00:00
Esteban Küber
d860e5b088 Mention type parameter in more cases and don't suggest ~const bound already there 2024-12-07 21:37:13 +00:00