about summary refs log tree commit diff
path: root/tests/ui/async-await/async-closures
AgeCommit message (Collapse)AuthorLines
2025-10-02Auto merge of #147138 - jackh726:split-canonical-bound, r=lcnrbors-3/+28
Split Bound index into Canonical and Bound See [#t-types/trait-system-refactor > perf `async-closures/post-mono-higher-ranked-hang.rs`](https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/perf.20.60async-closures.2Fpost-mono-higher-ranked-hang.2Ers.60/with/541535613) for context Things compile and tests pass, but not sure if this actually solves the perf issue (edit: it does). Opening up this to do a perf (and maybe crater) run. r? lcnr
2025-09-30Split Bound into Canonical and Boundjackh726-3/+28
2025-09-28reword noteEsteban Küber-5/+5
2025-09-28Point at lifetime requirement origin in more casesEsteban Küber-4/+10
2025-09-28Point at fn bound that introduced lifetime obligationEsteban Küber-1/+70
``` error[E0597]: `c` does not live long enough --> $DIR/without-precise-captures-we-are-powerless.rs:19:20 | LL | fn simple<'a>(x: &'a i32) { | -- lifetime `'a` defined here ... LL | let c = async move || { println!("{}", *x); }; | - binding `c` declared here LL | outlives::<'a>(c()); | ---------------^--- | | | | | borrowed value does not live long enough | argument requires that `c` is borrowed for `'a` LL | outlives::<'a>(call_once(c)); LL | } | - `c` dropped here while still borrowed | note: requirement that `c` is borrowed for `'a` introduced here --> $DIR/without-precise-captures-we-are-powerless.rs:7:33 | LL | fn outlives<'a>(_: impl Sized + 'a) {} | ^^ ``` When encountering a `ConstraintCategory::Predicate` in a funtion call, point at the `Span` for that `Predicate` to explain where the lifetime obligation originates from.
2025-08-19Pretty print the name of an future from calling async closureMichael Goulet-0/+18
2025-07-31Remove the witness type from coroutine argsMichael Goulet-2/+2
2025-07-23Point at the type that doesn't impl `Clone` in more cases beyond closuresEsteban Küber-5/+7
2025-07-17Eagerly unify coroutine witness in old solverMichael Goulet-2/+2
2025-06-09Make E0621 missing lifetime suggestion verboseEsteban Küber-6/+10
``` error[E0621]: explicit lifetime required in the type of `x` --> $DIR/42701_one_named_and_one_anonymous.rs:10:9 | LL | &*x | ^^^ lifetime `'a` required | help: add explicit lifetime `'a` to the type of `x` | LL | fn foo2<'a>(a: &'a Foo, x: &'a i32) -> &'a i32 { | ++ ```
2025-05-26Support opaque_types_defined_by for SyntheticCoroutineBodyMichael Goulet-0/+13
2025-05-21Fix FnOnce impl for AsyncFn/AsyncFnMut closures in new solverMichael Goulet-0/+15
2025-05-05Do not gather local all together at the beginning of typeckMichael Goulet-2/+2
2025-04-26Rollup merge of #140318 - compiler-errors:specialized-async-fn-kind-err, ↵Matthias Krüger-0/+43
r=fee1-dead Simply try to unpeel AsyncFnKindHelper goal in `emit_specialized_closure_kind_error` Tweak the handling of `AsyncFnKindHelper` goals in `emit_specialized_closure_kind_error` to not be so special-casey, and just try to unpeel one or two layers of obligation causes to get to their underlying `AsyncFn*` goal. Fixes https://github.com/rust-lang/rust/issues/140292
2025-04-26Simply try to unpeel AsyncFnKindHelper goal in ↵Michael Goulet-0/+43
emit_specialized_closure_kind_error
2025-04-23MoreMichael Goulet-5/+4
2025-04-10replace `//@ compile-flags: --edition` with `//@ edition`Pietro Albini-3/+4
2025-03-31Feed HIR for by-move coroutine body def, since the inliner tries to read its ↵Michael Goulet-0/+28
attrs
2025-03-14Improve upvar analysis for deref of child captureMichael Goulet-0/+109
2025-03-03Improve error message for AsyncFn trait failure for RPITMichael Goulet-0/+31
2025-02-12Rollup merge of #134090 - veluca93:stable-tf11, r=oli-obkJacob Pratt-7/+6
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/`](https://github.com/rust-lang/rust/tree/f6cb952dc115fd1311b02b694933e31d8dc8b002/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. https://github.com/rust-lang/stdarch/blob/2e29bdf90832931ea499755bb4ad7a6b0809295a/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-10Show diff suggestion format on verbose replacementEsteban Küber-2/+3
``` 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-02Shorten error message for callable with wrong return typeEsteban Küber-3/+3
``` 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-01-27Stabilize target_feature_11Caleb Zulawski-7/+6
2025-01-26Add cache to FoldEscapingRegionsMichael Goulet-0/+125
2025-01-22Use `structurally_normalize` instead of manual `normalizes-to` goalsBoxy-5/+27
2025-01-15Render fn defs with target_features attrs with the attributeOli Scherer-2/+3
2025-01-15Treat safe target_feature functions as unsafe by defaultOli Scherer-2/+2
2025-01-06`best_blame_constraint`: don't filter constraints by sup SCCdianne-24/+24
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.
2024-12-31Make sure we check the future type is Sized in AsyncFn*Michael Goulet-0/+51
2024-12-25Actually print all the relevant parts of a coroutine in verbose modeMichael Goulet-2/+2
2024-12-13Stabilize async closuresMichael Goulet-173/+60
2024-12-08Don't use AsyncFnOnce::CallOnceFuture bounds for signature deductionMichael Goulet-0/+14
2024-12-05Stabilize noop_wakerEric Holk-3/+3
Co-authored-by: zachs18 <8355914+zachs18@users.noreply.github.com>
2024-12-02Move tests back to using AsyncFnMichael Goulet-53/+53
2024-11-22Pretty print AsyncFn traits tooMichael Goulet-6/+37
2024-11-02Auto merge of #132147 - estebank:long-types-2, r=davidtwcobors-1/+2
Tweak E0277 output when a candidate is available *Follow up to #132086.* Go from ``` error[E0277]: the trait bound `Then<Ignored<chumsky::combinator::Filter<chumsky::primitive::Any<&str, chumsky::extra::Full<EmptyErr, (), ()>>, {closure@src/main.rs:9:17: 9:27}>, char>, chumsky::combinator::Map<impl CSTParser<'a, O>, O, {closure@src/main.rs:11:24: 11:27}>, (), (), chumsky::extra::Full<EmptyErr, (), ()>>: CSTParser<'a>` is not satisfied --> src/main.rs:7:50 | 7 | fn leaf<'a, O>(parser: impl CSTParser<'a, O>) -> impl CSTParser<'a, ()> { | ^^^^^^^^^^^^^^^^^^^^^^ the trait `chumsky::private::ParserSealed<'_, &str, (), chumsky::extra::Full<EmptyErr, (), ()>>` is not implemented for `Then<Ignored<Filter<Any<&str, ...>, ...>, ...>, ..., ..., ..., ...>`, which is required by `Then<Ignored<chumsky::combinator::Filter<chumsky::primitive::Any<&str, chumsky::extra::Full<EmptyErr, (), ()>>, {closure@src/main.rs:9:17: 9:27}>, char>, chumsky::combinator::Map<impl CSTParser<'a, O>, O, {closure@src/main.rs:11:24: 11:27}>, (), (), chumsky::extra::Full<EmptyErr, (), ()>>: CSTParser<'a>` | = help: the trait `chumsky::private::ParserSealed<'_, &'a str, ((), ()), chumsky::extra::Full<EmptyErr, (), ()>>` is implemented for `Then<Ignored<chumsky::combinator::Filter<chumsky::primitive::Any<&str, chumsky::extra::Full<EmptyErr, (), ()>>, {closure@src/main.rs:9:17: 9:27}>, char>, chumsky::combinator::Map<impl CSTParser<'a, O>, O, {closure@src/main.rs:11:24: 11:27}>, (), (), chumsky::extra::Full<EmptyErr, (), ()>>` = help: for that trait implementation, expected `((), ())`, found `()` = note: required for `Then<Ignored<Filter<Any<&str, ...>, ...>, ...>, ..., ..., ..., ...>` to implement `Parser<'_, &str, ()>` note: required for `Then<Ignored<Filter<Any<&str, ...>, ...>, ...>, ..., ..., ..., ...>` to implement `CSTParser<'a>` --> src/main.rs:5:16 | 5 | impl<'a, O, T> CSTParser<'a, O> for T where T: Parser<'a, &'a str, O> {} | ^^^^^^^^^^^^^^^^ ^ ---------------------- unsatisfied trait bound introduced here = note: the full name for the type has been written to '/home/gh-estebank/longlong/target/debug/deps/longlong-0008f9a4f2023b08.long-type-13239977239800463552.txt' = note: consider using `--verbose` to print the full type name to the console = note: the full name for the type has been written to '/home/gh-estebank/longlong/target/debug/deps/longlong-0008f9a4f2023b08.long-type-13239977239800463552.txt' = note: consider using `--verbose` to print the full type name to the console ``` to ``` error[E0277]: the trait bound `Then<Ignored<chumsky::combinator::Filter<chumsky::primitive::Any<&str, chumsky::extra::Full<EmptyErr, (), ()>>, {closure@src/main.rs:9:17: 9:27}>, char>, chumsky::combinator::Map<impl CSTParser<'a, O>, O, {closure@src/main.rs:11:24: 11:27}>, (), (), chumsky::extra::Full<EmptyErr, (), ()>>: CSTParser<'a>` is not satisfied --> src/main.rs:7:50 | 7 | fn leaf<'a, O>(parser: impl CSTParser<'a, O>) -> impl CSTParser<'a, ()> { | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound ... 11 | ws.then(parser.map(|_| ())) | --------------------------- return type was inferred to be `Then<Ignored<..., ...>, ..., ..., ..., ...>` here | = help: the trait `ParserSealed<'_, &_, (), Full<_, _, _>>` is not implemented for `Then<Ignored<..., ...>, ..., ..., ..., ...>` but trait `ParserSealed<'_, &'a _, ((), ()), Full<_, _, _>>` is implemented for it = help: for that trait implementation, expected `((), ())`, found `()` = note: required for `Then<Ignored<..., ...>, ..., ..., ..., ...>` to implement `Parser<'_, &str, ()>` note: required for `Then<Ignored<..., ...>, ..., ..., ..., ...>` to implement `CSTParser<'a>` --> src/main.rs:5:16 | 5 | impl<'a, O, T> CSTParser<'a, O> for T where T: Parser<'a, &'a str, O> {} | ^^^^^^^^^^^^^^^^ ^ ---------------------- unsatisfied trait bound introduced here = note: the full name for the type has been written to '/home/gh-estebank/longlong/target/debug/deps/longlong-df9d52be87eada65.long-type-1337037744507305372.txt' = note: consider using `--verbose` to print the full type name to the console ``` * Remove redundant wording * Introduce trait diff highlighting logic and use it * Fix incorrect "long type written to path" logic (can be split off) * Point at tail expression in more cases in E0277 * Avoid long primary span labels in E0277 by moving them to a `help` Fix #132013. There are individual commits that can be their own PR. If the review load is too big, happy to split them off.
2024-11-02Remove or fix some FIXME(async_closure)Michael Goulet-15/+24
2024-11-02On long E0277 primary span label, move it to a `help`Esteban Küber-1/+2
Long span labels don't read well.
2024-10-29Remove detail from label/note that is already available in other noteEsteban Küber-1/+1
Remove the "which is required by `{root_obligation}`" post-script in "the trait `X` is not implemented for `Y`" explanation in E0277. This information is already conveyed in the notes explaining requirements, making it redundant while making the text (particularly in labels) harder to read. ``` error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-static-type.rs:10:13 | LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None }; | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy` | = note: required for `Option<NotCopy>` to implement `Copy` note: required by a bound in `IsCopy` --> $DIR/wf-static-type.rs:7:17 | LL | struct IsCopy<T:Copy> { t: T } | ^^^^ required by this bound in `IsCopy` ``` vs the prior ``` error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-static-type.rs:10:13 | LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None }; | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option<NotCopy>: Copy` | = note: required for `Option<NotCopy>` to implement `Copy` note: required by a bound in `IsCopy` --> $DIR/wf-static-type.rs:7:17 | LL | struct IsCopy<T:Copy> { t: T } | ^^^^ required by this bound in `IsCopy` ```
2024-09-16Fix a couple more DefKind discrepancies between DefKind::Closure and ↵Michael Goulet-0/+34
DefKind::SyntheticCoroutineBody
2024-09-16Encode coroutine_by_move_body_def_id in crate metadataMichael Goulet-0/+5
2024-09-16Don't ICE when generating Fn shim for async closure with borrowck errorMichael Goulet-0/+45
2024-09-14Consider synthetic closure bodies to be typeck childrenMichael Goulet-0/+19
2024-09-10Don't call closure_by_move_body_def_id on FnOnce async closures in MIR ↵Michael Goulet-0/+20
validation
2024-09-07Rollup merge of #129847 - compiler-errors:async-cycle, r=davidtwcoMatthias Krüger-0/+19
Do not call query to compute coroutine layout for synthetic body of async closure There is code in the MIR validator that attempts to prevent query cycles when inlining a coroutine into itself, and will use the coroutine layout directly from the body when it detects that's the same coroutine as the one that's being validated. After #128506, this logic didn't take into account the fact that the coroutine def id will differ if it's the "by-move body" of an async closure. This PR implements that. Fixes #129811
2024-09-07Don't build by-move body when async closure is taintedMichael Goulet-0/+27
2024-09-01Replace walk with visit so we dont skip outermost expr kind in def collectorMichael Goulet-0/+12
2024-09-01Do not call query to compute coroutine layout for synthetic body of async ↵Michael Goulet-0/+19
closure
2024-08-15Rollup merge of #129101 - compiler-errors:deref-on-parent-by-ref, r=lcnrMatthias Krüger-0/+34
Fix projections when parent capture is by-ref but child capture is by-value in the `ByMoveBody` pass This fixes a somewhat strange bug where we build the incorrect MIR in #129074. This one is weird, but I don't expect it to actually matter in practice since it almost certainly results in a move error in borrowck. However, let's not ICE. Given the code: ``` #![feature(async_closure)] // NOT copy. struct Ty; fn hello(x: &Ty) { let c = async || { *x; //~^ ERROR cannot move out of `*x` which is behind a shared reference }; } fn main() {} ``` The parent coroutine-closure captures `x: &Ty` by-ref, resulting in an upvar of `&&Ty`. The child coroutine captures `x` by-value, resulting in an upvar of `&Ty`. When constructing the by-move body for the coroutine-closure, we weren't applying an additional deref projection to convert the parent capture into the child capture, resulting in an type error in assignment, which is a validation ICE. As I said above, this only occurs (AFAICT) in code that eventually results in an error, because it is only triggered by HIR that attempts to move a non-copy value out of a ref. This doesn't occur if `Ty` is `Copy`, since we'd instead capture `x` by-ref in the child coroutine. Fixes #129074