From 9ad4ab9bb57c64b5e66e93d4ca9d15d7036af5bf Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Jun 2025 12:30:08 +0200 Subject: [PATCH 1/8] use a relative path, so that this also works offline --- src/normalization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/normalization.md b/src/normalization.md index 9705b1a2..beeeb9e3 100644 --- a/src/normalization.md +++ b/src/normalization.md @@ -271,7 +271,7 @@ Leaving the alias unnormalized would also be wrong as the old solver expects all Ultimately this means that it is not always possible to ensure all aliases inside of a value are rigid. -[universes]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html#what-is-a-universe +[universes]: borrow_check/region_inference/placeholders_and_universes.md#what-is-a-universe [deeply_normalize]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/normalize/trait.NormalizeExt.html#tymethod.deeply_normalize ## Handling uses of diverging aliases From 39300c4b70526a271837cb2b8aabaa1d706aa03c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 2 Jun 2025 12:34:19 +0200 Subject: [PATCH 2/8] distracting indirection --- src/normalization.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/normalization.md b/src/normalization.md index beeeb9e3..eb0962a4 100644 --- a/src/normalization.md +++ b/src/normalization.md @@ -265,13 +265,13 @@ Another problem was that it was not possible to normalize `ParamEnv`s correctly Given a type such as `for<'a> fn(::Assoc>)`, it is not possible to correctly handle this with the old solver's approach to normalization. -If we were to normalize it to `for<'a> fn(?y)` and register a goal to normalize `for<'a> >::Assoc -> ?y`, this would result in errors in cases where `>::Assoc` normalized to `&'a u32`. The inference variable `?y` would be in a lower [universe][universes] than the placeholders made when instantiating the `for<'a>` binder. +If we were to normalize it to `for<'a> fn(?y)` and register a goal to normalize `for<'a> >::Assoc -> ?y`, this would result in errors in cases where `>::Assoc` normalized to `&'a u32`. The inference variable `?y` would be in a lower [universe] than the placeholders made when instantiating the `for<'a>` binder. Leaving the alias unnormalized would also be wrong as the old solver expects all aliases to be rigid. This was a soundness bug before the new solver was stabilized in coherence: [relating projection substs is unsound during coherence](https://github.com/rust-lang/rust/issues/102048). Ultimately this means that it is not always possible to ensure all aliases inside of a value are rigid. -[universes]: borrow_check/region_inference/placeholders_and_universes.md#what-is-a-universe +[universe]: borrow_check/region_inference/placeholders_and_universes.md#what-is-a-universe [deeply_normalize]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/normalize/trait.NormalizeExt.html#tymethod.deeply_normalize ## Handling uses of diverging aliases From 64ccd09863e925fdf2c5080889a4739bfe37b3fd Mon Sep 17 00:00:00 2001 From: Stan Manilov Date: Mon, 2 Jun 2025 17:02:34 +0300 Subject: [PATCH 3/8] Trivial: dedup word --- src/coroutine-closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coroutine-closures.md b/src/coroutine-closures.md index 04742d03..4a708fc8 100644 --- a/src/coroutine-closures.md +++ b/src/coroutine-closures.md @@ -102,7 +102,7 @@ See the "follow-up: when do..." section below for an elaborated answer. The full 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 by-move MIR body for calling `AsyncFnOnce::call_once` on a coroutine-closure that can be called by-ref. +To work around this limitation, we synthesize a separate by-move MIR body for calling `AsyncFnOnce::call_once` on a coroutine-closure that can be called by-ref. This body operates identically to the "normal" coroutine returned from calling the coroutine-closure, except for the fact that it has a different set of upvars, since we must *move* the captures from the parent coroutine-closure into the child coroutine. From f362726205ce4d9aa0d6f3b85e9d41310f86f32b Mon Sep 17 00:00:00 2001 From: Stan Manilov Date: Mon, 2 Jun 2025 17:16:29 +0300 Subject: [PATCH 4/8] Add title and toc to Async chapter This is standard for other chapters. --- src/coroutine-closures.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/coroutine-closures.md b/src/coroutine-closures.md index 04742d03..314bd13b 100644 --- a/src/coroutine-closures.md +++ b/src/coroutine-closures.md @@ -1,6 +1,10 @@ +# Async closures/"coroutine-closures" + + + Please read [RFC 3668](https://rust-lang.github.io/rfcs/3668-async-closures.html) to understand the general motivation of the feature. This is a very technical and somewhat "vertical" chapter; ideally we'd split this and sprinkle it across all the relevant chapters, but for the purposes of understanding async closures *holistically*, I've put this together all here in one chapter. -# Coroutine-closures -- a technical deep dive +## Coroutine-closures -- a technical deep dive Coroutine-closures are a generalization of async closures, being special syntax for closure expressions which return a coroutine, notably one that is allowed to capture from the closure's upvars. @@ -8,7 +12,7 @@ For now, the only usable kind of coroutine-closure is the async closure, and sup As a consequence of the code being somewhat general, this document may flip between calling them "async closures" and "coroutine-closures". The future that is returned by the async closure will generally be called the "coroutine" or the "child coroutine". -## HIR +### HIR Async closures (and in the future, other coroutine flavors such as `gen`) are represented in HIR as a `hir::Closure` whose closure-kind is `ClosureKind::CoroutineClosure(_)`[^k1], which wraps an async block, which is also represented in HIR as a `hir::Closure`) and whose closure-kind is `ClosureKind::Closure(CoroutineKind::Desugared(_, CoroutineSource::Closure))`[^k2]. @@ -24,7 +28,7 @@ Like `async fn`, when lowering an async closure's body, we need to unconditional [^l3]: -## `rustc_middle::ty` Representation +### `rustc_middle::ty` Representation For the purposes of keeping the implementation mostly future-compatible (i.e. with gen `|| {}` and `async gen || {}`), most of this section calls async closures "coroutine-closures". @@ -72,7 +76,7 @@ To most easily construct the `Coroutine` that a coroutine-closure returns, you c Most of the args to that function will be components that you can get out of the `CoroutineArgs`, except for the `goal_kind: ClosureKind` which controls which flavor of coroutine to return based off of the `ClosureKind` passed in -- i.e. it will prepare the by-ref coroutine if `ClosureKind::Fn | ClosureKind::FnMut`, and the by-move coroutine if `ClosureKind::FnOnce`. -## Trait Hierarchy +### Trait Hierarchy We introduce a parallel hierarchy of `Fn*` traits that are implemented for . The motivation for the introduction was covered in a blog post: [Async Closures](https://hackmd.io/@compiler-errors/async-closures). @@ -98,7 +102,7 @@ We mention above that "regular" callable types can implement `AsyncFn*`, but the See the "follow-up: when do..." section below for an elaborated answer. The full answer describes a pretty interesting and hopefully thorough heuristic that is used to ensure that most async closures "just work". -## Tale of two bodies... +### Tale of two bodies... 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. @@ -120,7 +124,7 @@ Since we've synthesized a new def id, this query is also responsible for feeding [^b3]: -## Closure signature inference +### Closure signature inference The closure signature inference algorithm for async closures is a bit more complicated than the inference algorithm for "traditional" closures. Like closures, we iterate through all of the clauses that may be relevant (for the expectation type passed in)[^deduce1]. @@ -173,7 +177,7 @@ s.as_bytes(); So *instead*, we use this alias (in this case, a projection: `AsyncFnKindHelper::Upvars<'env, ...>`) to delay the computation of the *tupled upvars* and give us something to put in its place, while still allowing us to return a `TyKind::Coroutine` (which is a rigid type) and we may successfully confirm the built-in traits we need (in our case, `Future`), since the `Future` implementation doesn't depend on the upvars at all. -## Upvar analysis +### Upvar analysis By and large, the upvar analysis for coroutine-closures and their child coroutines proceeds like normal upvar analysis. However, there are several interesting bits that happen to account for async closures' special natures: @@ -262,7 +266,7 @@ let c = async || { If either of these cases apply, then we should capture the borrow with the lifetime of the parent coroutine-closure's env. Luckily, if this function is not correct, then the program is not unsound, since we still borrowck and validate the choices made from this function -- the only side-effect is that the user may receive unnecessary borrowck errors. -## Instance resolution +### Instance resolution If a coroutine-closure has a closure-kind of `FnOnce`, then its `AsyncFnOnce::call_once` and `FnOnce::call_once` implementations resolve to the coroutine-closure's body[^res1], and the `Future::poll` of the coroutine that gets returned resolves to the body of the child closure. @@ -282,7 +286,7 @@ This is represented by the `ConstructCoroutineInClosureShim`[^i1]. The `receiver [^i3]: -## Borrow-checking +### Borrow-checking It turns out that borrow-checking async closures is pretty straightforward. After adding a new `DefiningTy::CoroutineClosure`[^bck1] variant, and teaching borrowck how to generate the signature of the coroutine-closure[^bck2], borrowck proceeds totally fine. From 6e608e5671423c96910ad81d95b386642ca52be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 2 Jun 2025 16:21:40 +0200 Subject: [PATCH 5/8] Fix some warning blocks that contain Markdown Contents inside of an HTML element only get interpreted as Markdown (as opposed to HTML) if its separated from the HTML tags with line breaks. --- src/autodiff/flags.md | 2 ++ src/tests/ci.md | 4 +++- src/tests/compiletest.md | 2 ++ src/tests/directives.md | 2 ++ src/tests/minicore.md | 2 ++ src/tests/running.md | 4 ++++ 6 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/autodiff/flags.md b/src/autodiff/flags.md index 946ae1d0..65287d9b 100644 --- a/src/autodiff/flags.md +++ b/src/autodiff/flags.md @@ -16,7 +16,9 @@ LooseTypes // Risk incorrect derivatives instead of aborting when missing Type I ```
+ `LooseTypes` is often helpful to get rid of Enzyme errors stating `Can not deduce type of ` and to be able to run some code. But please keep in mind that this flag absolutely has the chance to cause incorrect gradients. Even worse, the gradients might be correct for certain input values, but not for others. So please create issues about such bugs and only use this flag temporarily while you wait for your bug to be fixed. +
### Benchmark flags diff --git a/src/tests/ci.md b/src/tests/ci.md index d8be8224..edfc870e 100644 --- a/src/tests/ci.md +++ b/src/tests/ci.md @@ -186,9 +186,11 @@ Note that if you start the default try job using `@bors try`, it will skip build Multiple try builds can execute concurrently across different PRs.
-bors identify try jobs by commit hash. This means that if you have two PRs + +Bors identifies try jobs by commit hash. This means that if you have two PRs containing the same (latest) commits, running `@bors try` will result in the *same* try job and it really confuses `bors`. Please refrain from doing so. +
[rustc-perf]: https://github.com/rust-lang/rustc-perf diff --git a/src/tests/compiletest.md b/src/tests/compiletest.md index e1b23748..ee06ca3b 100644 --- a/src/tests/compiletest.md +++ b/src/tests/compiletest.md @@ -438,7 +438,9 @@ To work around this when working on a particular test, temporarily create a with these contents:
+ Be careful not to add this `Cargo.toml` or its `Cargo.lock` to your actual PR! +
```toml diff --git a/src/tests/directives.md b/src/tests/directives.md index 8a862417..2dff21ed 100644 --- a/src/tests/directives.md +++ b/src/tests/directives.md @@ -248,11 +248,13 @@ ignoring debuggers. | `no-prefer-dynamic` | Don't use `-C prefer-dynamic`, don't build as a dylib via a `--crate-type=dylib` preset flag | `ui`, `crashes` | N/A |
+ Tests (outside of `run-make`) that want to use incremental tests not in the incremental test-suite must not pass `-C incremental` via `compile-flags`, and must instead use the `//@ incremental` directive. Consider writing the test as a proper incremental test instead. +
### Rustdoc diff --git a/src/tests/minicore.md b/src/tests/minicore.md index 507b259e..def9aaf8 100644 --- a/src/tests/minicore.md +++ b/src/tests/minicore.md @@ -7,9 +7,11 @@ ui/codegen/assembly test suites. It provides `core` stubs for tests that need to build for cross-compiled targets but do not need/want to run.
+ Please note that [`minicore`] is only intended for `core` items, and explicitly **not** `std` or `alloc` items because `core` items are applicable to a wider range of tests. +
A test can use [`minicore`] by specifying the `//@ add-core-stubs` directive. diff --git a/src/tests/running.md b/src/tests/running.md index 73c38736..6526fe9c 100644 --- a/src/tests/running.md +++ b/src/tests/running.md @@ -8,6 +8,7 @@ development because it takes a really long time. For local development, see the subsection after on how to run a subset of tests.
+ Running plain `./x test` will build the stage 1 compiler and then run the whole test suite. This not only include `tests/`, but also `library/`, `compiler/`, `src/tools/` package tests and more. @@ -16,6 +17,7 @@ You usually only want to run a subset of the test suites (or even a smaller set of tests than that) which you expect will exercise your changes. PR CI exercises a subset of test collections, and merge queue CI will exercise all of the test collection. +
```text @@ -116,8 +118,10 @@ By listing which test suites you want to run, you avoid having to run tests for components you did not change at all.
+ Note that bors only runs the tests with the full stage 2 build; therefore, while the tests **usually** work fine with stage 1, there are some limitations. +
### Run all tests using a stage 2 compiler From c58ec2174934f040e442706b70d036810024e537 Mon Sep 17 00:00:00 2001 From: Stan Manilov Date: Mon, 2 Jun 2025 16:49:06 +0300 Subject: [PATCH 6/8] Simplify long sentence --- src/coroutine-closures.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coroutine-closures.md b/src/coroutine-closures.md index 04742d03..5a6f28e0 100644 --- a/src/coroutine-closures.md +++ b/src/coroutine-closures.md @@ -10,7 +10,9 @@ As a consequence of the code being somewhat general, this document may flip betw ## HIR -Async closures (and in the future, other coroutine flavors such as `gen`) are represented in HIR as a `hir::Closure` whose closure-kind is `ClosureKind::CoroutineClosure(_)`[^k1], which wraps an async block, which is also represented in HIR as a `hir::Closure`) and whose closure-kind is `ClosureKind::Closure(CoroutineKind::Desugared(_, CoroutineSource::Closure))`[^k2]. +Async closures (and in the future, other coroutine flavors such as `gen`) are represented in HIR as a `hir::Closure`. +The closure-kind of the `hir::Closure` is `ClosureKind::CoroutineClosure(_)`[^k1], which wraps an async block, which is also represented in HIR as a `hir::Closure`. +The closure-kind of the async block is `ClosureKind::Closure(CoroutineKind::Desugared(_, CoroutineSource::Closure))`[^k2]. [^k1]: From 91be3cb103b4e316bcac7bc7d207d3631a21ff11 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 3 Jun 2025 20:16:00 +0800 Subject: [PATCH 7/8] Preparing for merge from rustc --- rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-version b/rust-version index b1e9eec5..8b48bd51 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -99e7c15e81385b38a8186b51edc4577d5d7b5bdd +c68032fd4c442d275f4daa571ba19c076106b490 From cda721a97fec79bbe69aa476075369db61fb9407 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 4 Jun 2025 15:16:57 +0300 Subject: [PATCH 8/8] document `skip-std-check-if-no-download-rustc` in rustc-dev-guide Signed-off-by: onur-ozkan --- src/building/suggested.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/building/suggested.md b/src/building/suggested.md index 76c39608..bfb2f4d1 100644 --- a/src/building/suggested.md +++ b/src/building/suggested.md @@ -59,6 +59,14 @@ always overrides the inner ones. ## Configuring `rust-analyzer` for `rustc` +### Checking the "library" tree + +Checking the "library" tree requires a stage1 compiler, which can be a heavy process on some computers. +For this reason, bootstrap has a flag called `--skip-std-check-if-no-download-rustc` that skips checking the +"library" tree if `rust.download-rustc` isn't available. If you want to avoid putting a heavy load on your computer +with `rust-analyzer`, you can add the `--skip-std-check-if-no-download-rustc` flag to your `./x check` command in +the `rust-analyzer` configuration. + ### Project-local rust-analyzer setup `rust-analyzer` can help you check and format your code whenever you save a