Merge pull request #19954 from lnicola/sync-from-rust
minor: Sync from downstream
This commit is contained in:
commit
92f36d9dae
1
.mailmap
1
.mailmap
|
|
@ -3,3 +3,4 @@ Jynn Nelson <github@jyn.dev> <joshua@yottadb.com>
|
|||
Jynn Nelson <github@jyn.dev> <jyn.nelson@redjack.com>
|
||||
Jynn Nelson <github@jyn.dev> <jnelson@cloudflare.com>
|
||||
Jynn Nelson <github@jyn.dev>
|
||||
Tshepang Mbambo <hopsi@tuta.io> <tshepang@gmail.com>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
414482f6a0d4e7290f614300581a0b55442552a3
|
||||
c68032fd4c442d275f4daa571ba19c076106b490
|
||||
|
|
|
|||
|
|
@ -134,9 +134,9 @@
|
|||
|
||||
- [Command-line arguments](./cli.md)
|
||||
- [rustc_driver and rustc_interface](./rustc-driver/intro.md)
|
||||
- [Remarks on perma-unstable features](./rustc-driver/remarks-on-perma-unstable-features.md)
|
||||
- [Example: Type checking](./rustc-driver/interacting-with-the-ast.md)
|
||||
- [Example: Getting diagnostics](./rustc-driver/getting-diagnostics.md)
|
||||
- [Remarks on perma-unstable features](./rustc-driver/remarks-on-perma-unstable-features.md)
|
||||
- [Errors and lints](diagnostics.md)
|
||||
- [Diagnostic and subdiagnostic structs](./diagnostics/diagnostic-structs.md)
|
||||
- [Translation](./diagnostics/translation.md)
|
||||
|
|
|
|||
|
|
@ -46,3 +46,4 @@ These are videos where various experts explain different parts of the compiler:
|
|||
|
||||
## Code Generation
|
||||
- [January 2019: Cranelift](https://www.youtube.com/watch?v=9OIA7DTFQWU)
|
||||
- [December 2024: LLVM Developers' Meeting - Rust ❤️ LLVM](https://www.youtube.com/watch?v=Kqz-umsAnk8)
|
||||
|
|
@ -16,7 +16,9 @@ LooseTypes // Risk incorrect derivatives instead of aborting when missing Type I
|
|||
```
|
||||
|
||||
<div class="warning">
|
||||
|
||||
`LooseTypes` is often helpful to get rid of Enzyme errors stating `Can not deduce type of <X>` 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.
|
||||
|
||||
</div>
|
||||
|
||||
### Benchmark flags
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ format is specific to `rustc`, and may change over time. This file contains:
|
|||
[`-C embed-bitcode=no`][embed-bitcode] CLI option to improve compile times
|
||||
and reduce disk space if LTO is not needed.
|
||||
* `rustc` [metadata], in a file named `lib.rmeta`.
|
||||
* A symbol table, which is generally a list of symbols with offsets to the
|
||||
object file that contain that symbol. This is pretty standard for archive
|
||||
* A symbol table, which is essentially a list of symbols with offsets to the
|
||||
object files that contain that symbol. This is pretty standard for archive
|
||||
files.
|
||||
|
||||
[archive file]: https://en.wikipedia.org/wiki/Ar_(Unix)
|
||||
|
|
@ -46,12 +46,11 @@ A `dylib` is a platform-specific shared library. It includes the `rustc`
|
|||
|
||||
### rmeta
|
||||
|
||||
An `rmeta` file is custom binary format that contains the [metadata] for the
|
||||
crate. This file can be used for fast "checks" of a project by skipping all
|
||||
code generation (as is done with `cargo check`), collecting enough information
|
||||
for documentation (as is done with `cargo doc`), or for
|
||||
[pipelining](#pipelining). This file is created if the
|
||||
[`--emit=metadata`][emit] CLI option is used.
|
||||
An `rmeta` file is a custom binary format that contains the [metadata] for the
|
||||
crate. This file can be used for fast "checks" of a project by skipping all code
|
||||
generation (as is done with `cargo check`), collecting enough information for
|
||||
documentation (as is done with `cargo doc`), or for [pipelining](#pipelining).
|
||||
This file is created if the [`--emit=metadata`][emit] CLI option is used.
|
||||
|
||||
`rmeta` files do not support linking, since they do not contain compiled
|
||||
object files.
|
||||
|
|
@ -60,8 +59,8 @@ object files.
|
|||
|
||||
## Metadata
|
||||
|
||||
The metadata contains a wide swath of different elements. This guide will not
|
||||
go into detail of every field it contains. You are encouraged to browse the
|
||||
The metadata contains a wide swath of different elements. This guide will not go
|
||||
into detail about every field it contains. You are encouraged to browse the
|
||||
[`CrateRoot`] definition to get a sense of the different elements it contains.
|
||||
Everything about metadata encoding and decoding is in the [`rustc_metadata`]
|
||||
package.
|
||||
|
|
@ -122,9 +121,9 @@ much more.
|
|||
|
||||
By default, all Rust symbols are mangled and incorporate the stable crate id.
|
||||
This allows multiple versions of the same crate to be included together. Cargo
|
||||
automatically generates `-C metadata` hashes based on a variety of factors,
|
||||
like the package version, source, and the target kind (a lib and test can have
|
||||
the same crate name, so they need to be disambiguated).
|
||||
automatically generates `-C metadata` hashes based on a variety of factors, like
|
||||
the package version, source, and target kind (a lib and test can have the same
|
||||
crate name, so they need to be disambiguated).
|
||||
|
||||
[`StableCrateId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/def_id/struct.StableCrateId.html
|
||||
[`StableCrateId::new`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/def_id/struct.StableCrateId.html#method.new
|
||||
|
|
@ -154,7 +153,7 @@ will also look at the [sysroot] to find dependencies.
|
|||
|
||||
As crates are loaded, they are kept in the [`CStore`] with the crate metadata
|
||||
wrapped in the [`CrateMetadata`] struct. After resolution and expansion, the
|
||||
`CStore` will make its way into the [`GlobalCtxt`] for the rest of
|
||||
`CStore` will make its way into the [`GlobalCtxt`] for the rest of the
|
||||
compilation.
|
||||
|
||||
[name resolution]: ../name-resolution.md
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ borrow.
|
|||
[`AutoBorrow`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adjustment/enum.AutoBorrow.html
|
||||
[converted]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/cx/expr/trait.ToBorrowKind.html#method.to_borrow_kind
|
||||
[`BorrowKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.BorrowKind.html
|
||||
[`GatherBorrows`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/visit/trait.Visitor.html#method.visit_local
|
||||
[`GatherBorrows`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/borrow_set/struct.GatherBorrows.html
|
||||
[`BorrowData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/borrow_set/struct.BorrowData.html
|
||||
|
||||
## Checking two-phase borrows
|
||||
|
|
|
|||
|
|
@ -45,13 +45,13 @@ compiler.
|
|||
|
||||
```mermaid
|
||||
graph TD
|
||||
s0c["stage0 compiler (1.63)"]:::downloaded -->|A| s0l("stage0 std (1.64)"):::with-s0c;
|
||||
s0c["stage0 compiler (1.86.0-beta.1)"]:::downloaded -->|A| s0l("stage0 std (1.86.0-beta.1)"):::downloaded;
|
||||
s0c & s0l --- stepb[ ]:::empty;
|
||||
stepb -->|B| s0ca["stage0 compiler artifacts (1.64)"]:::with-s0c;
|
||||
s0ca -->|copy| s1c["stage1 compiler (1.64)"]:::with-s0c;
|
||||
s1c -->|C| s1l("stage1 std (1.64)"):::with-s1c;
|
||||
stepb -->|B| s0ca["stage0 compiler artifacts (1.87.0-dev)"]:::with-s0c;
|
||||
s0ca -->|copy| s1c["stage1 compiler (1.87.0-dev)"]:::with-s0c;
|
||||
s1c -->|C| s1l("stage1 std (1.87.0-dev)"):::with-s1c;
|
||||
s1c & s1l --- stepd[ ]:::empty;
|
||||
stepd -->|D| s1ca["stage1 compiler artifacts (1.64)"]:::with-s1c;
|
||||
stepd -->|D| s1ca["stage1 compiler artifacts (1.87.0-dev)"]:::with-s1c;
|
||||
s1ca -->|copy| s2c["stage2 compiler"]:::with-s1c;
|
||||
|
||||
classDef empty width:0px,height:0px;
|
||||
|
|
@ -62,19 +62,21 @@ graph TD
|
|||
|
||||
### Stage 0: the pre-compiled compiler
|
||||
|
||||
The stage0 compiler is usually the current _beta_ `rustc` compiler and its
|
||||
The stage0 compiler is by default the very recent _beta_ `rustc` compiler and its
|
||||
associated dynamic libraries, which `./x.py` will download for you. (You can
|
||||
also configure `./x.py` to use something else.)
|
||||
also configure `./x.py` to change stage0 to something else.)
|
||||
|
||||
The stage0 compiler is then used only to compile [`src/bootstrap`],
|
||||
[`library/std`], and [`compiler/rustc`]. When assembling the libraries and
|
||||
binaries that will become the stage1 `rustc` compiler, the freshly compiled
|
||||
`std` and `rustc` are used. There are two concepts at play here: a compiler
|
||||
(with its set of dependencies) and its 'target' or 'object' libraries (`std` and
|
||||
`rustc`). Both are staged, but in a staggered manner.
|
||||
The precompiled stage0 compiler is then used only to compile [`src/bootstrap`] and [`compiler/rustc`]
|
||||
with precompiled stage0 std.
|
||||
|
||||
Note that to build the stage1 compiler we use the precompiled stage0 compiler and std.
|
||||
Therefore, to use a compiler with a std that is freshly built from the tree, you need to
|
||||
build the stage2 compiler.
|
||||
|
||||
There are two concepts at play here: a compiler (with its set of dependencies) and its
|
||||
'target' or 'object' libraries (`std` and `rustc`). Both are staged, but in a staggered manner.
|
||||
|
||||
[`compiler/rustc`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc
|
||||
[`library/std`]: https://github.com/rust-lang/rust/tree/master/library/std
|
||||
[`src/bootstrap`]: https://github.com/rust-lang/rust/tree/master/src/bootstrap
|
||||
|
||||
### Stage 1: from current code, by an earlier compiler
|
||||
|
|
@ -84,16 +86,14 @@ The rustc source code is then compiled with the `stage0` compiler to produce the
|
|||
|
||||
### Stage 2: the truly current compiler
|
||||
|
||||
We then rebuild our `stage1` compiler with itself to produce the `stage2`
|
||||
We then rebuild the compiler using `stage1` compiler with in-tree std to produce the `stage2`
|
||||
compiler.
|
||||
|
||||
In theory, the `stage1` compiler is functionally identical to the `stage2`
|
||||
compiler, but in practice there are subtle differences. In particular, the
|
||||
`stage1` compiler itself was built by `stage0` and hence not by the source in
|
||||
your working directory. This means that the ABI generated by the `stage0`
|
||||
compiler may not match the ABI that would have been made by the `stage1`
|
||||
compiler, which can cause problems for dynamic libraries, tests, and tools using
|
||||
`rustc_private`.
|
||||
The `stage1` compiler itself was built by precompiled `stage0` compiler and std
|
||||
and hence not by the source in your working directory. This means that the ABI
|
||||
generated by the `stage0` compiler may not match the ABI that would have been made
|
||||
by the `stage1` compiler, which can cause problems for dynamic libraries, tests
|
||||
and tools using `rustc_private`.
|
||||
|
||||
Note that the `proc_macro` crate avoids this issue with a `C` FFI layer called
|
||||
`proc_macro::bridge`, allowing it to be used with `stage1`.
|
||||
|
|
@ -101,9 +101,10 @@ Note that the `proc_macro` crate avoids this issue with a `C` FFI layer called
|
|||
The `stage2` compiler is the one distributed with `rustup` and all other install
|
||||
methods. However, it takes a very long time to build because one must first
|
||||
build the new compiler with an older compiler and then use that to build the new
|
||||
compiler with itself. For development, you usually only want the `stage1`
|
||||
compiler, which you can build with `./x build library`. See [Building the
|
||||
compiler](../how-to-build-and-run.html#building-the-compiler).
|
||||
compiler with itself.
|
||||
|
||||
For development, you usually only want to use `--stage 1` flag to build things.
|
||||
See [Building the compiler](../how-to-build-and-run.html#building-the-compiler).
|
||||
|
||||
### Stage 3: the same-result test
|
||||
|
||||
|
|
@ -114,10 +115,11 @@ something has broken.
|
|||
### Building the stages
|
||||
|
||||
The script [`./x`] tries to be helpful and pick the stage you most likely meant
|
||||
for each subcommand. These defaults are as follows:
|
||||
for each subcommand. Here are some `x` commands with their default stages:
|
||||
|
||||
- `check`: `--stage 0`
|
||||
- `doc`: `--stage 0`
|
||||
- `check`: `--stage 1`
|
||||
- `clippy`: `--stage 1`
|
||||
- `doc`: `--stage 1`
|
||||
- `build`: `--stage 1`
|
||||
- `test`: `--stage 1`
|
||||
- `dist`: `--stage 2`
|
||||
|
|
@ -191,8 +193,8 @@ include, but are not limited to:
|
|||
without building `rustc` from source ('build with `stage0`, then test the
|
||||
artifacts'). If you're working on the standard library, this is normally the
|
||||
test command you want.
|
||||
- `./x build --stage 0` means to build with the beta `rustc`.
|
||||
- `./x doc --stage 0` means to document using the beta `rustdoc`.
|
||||
- `./x build --stage 0` means to build with the stage0 `rustc`.
|
||||
- `./x doc --stage 0` means to document using the stage0 `rustdoc`.
|
||||
|
||||
#### Examples of what *not* to do
|
||||
|
||||
|
|
@ -208,9 +210,6 @@ include, but are not limited to:
|
|||
|
||||
### Building vs. running
|
||||
|
||||
Note that `build --stage N compiler/rustc` **does not** build the stage N
|
||||
compiler: instead it builds the stage N+1 compiler _using_ the stage N compiler.
|
||||
|
||||
In short, _stage 0 uses the `stage0` compiler to create `stage0` artifacts which
|
||||
will later be uplifted to be the stage1 compiler_.
|
||||
|
||||
|
|
@ -268,23 +267,6 @@ However, when cross-compiling, `stage1` `std` will only run on the host. So the
|
|||
|
||||
(See in the table how `stage2` only builds non-host `std` targets).
|
||||
|
||||
### Why does only libstd use `cfg(bootstrap)`?
|
||||
|
||||
For docs on `cfg(bootstrap)` itself, see [Complications of
|
||||
Bootstrapping](#complications-of-bootstrapping).
|
||||
|
||||
The `rustc` generated by the `stage0` compiler is linked to the freshly-built
|
||||
`std`, which means that for the most part only `std` needs to be `cfg`-gated, so
|
||||
that `rustc` can use features added to `std` immediately after their addition,
|
||||
without need for them to get into the downloaded `beta` compiler.
|
||||
|
||||
Note this is different from any other Rust program: `stage1` `rustc` is built by
|
||||
the _beta_ compiler, but using the _master_ version of `libstd`!
|
||||
|
||||
The only time `rustc` uses `cfg(bootstrap)` is when it adds internal lints that
|
||||
use diagnostic items, or when it uses unstable library features that were
|
||||
recently changed.
|
||||
|
||||
### What is a 'sysroot'?
|
||||
|
||||
When you build a project with `cargo`, the build artifacts for dependencies are
|
||||
|
|
@ -459,7 +441,6 @@ compiler itself uses to run. These aren't actually used by artifacts the new
|
|||
compiler generates. This step also copies the `rustc` and `rustdoc` binaries we
|
||||
generated into `build/$HOST/stage/bin`.
|
||||
|
||||
The `stage1/bin/rustc` is a fully functional compiler, but it doesn't yet have
|
||||
any libraries to link built binaries or libraries to. The next 3 steps will
|
||||
provide those libraries for it; they are mostly equivalent to constructing the
|
||||
`stage1/bin` compiler so we don't go through them individually here.
|
||||
The `stage1/bin/rustc` is a fully functional compiler built with stage0 (precompiled) compiler and std.
|
||||
To use a compiler built entirely from source with the in-tree compiler and std, you need to build the
|
||||
stage2 compiler, which is compiled using the stage1 (in-tree) compiler and std.
|
||||
|
|
|
|||
|
|
@ -217,7 +217,6 @@ probably the best "go to" command for building a local compiler:
|
|||
This may *look* like it only builds the standard library, but that is not the case.
|
||||
What this command does is the following:
|
||||
|
||||
- Build `std` using the stage0 compiler
|
||||
- Build `rustc` using the stage0 compiler
|
||||
- This produces the stage1 compiler
|
||||
- Build `std` using the stage1 compiler
|
||||
|
|
@ -241,8 +240,7 @@ build. The **full** `rustc` build (what you get with `./x build
|
|||
--stage 2 compiler/rustc`) has quite a few more steps:
|
||||
|
||||
- Build `rustc` with the stage1 compiler.
|
||||
- The resulting compiler here is called the "stage2" compiler.
|
||||
- Build `std` with stage2 compiler.
|
||||
- The resulting compiler here is called the "stage2" compiler, which uses stage1 std from the previous command.
|
||||
- Build `librustdoc` and a bunch of other things with the stage2 compiler.
|
||||
|
||||
You almost never need to do this.
|
||||
|
|
@ -250,14 +248,14 @@ You almost never need to do this.
|
|||
### Build specific components
|
||||
|
||||
If you are working on the standard library, you probably don't need to build
|
||||
the compiler unless you are planning to use a recently added nightly feature.
|
||||
Instead, you can just build using the bootstrap compiler.
|
||||
every other default component. Instead, you can build a specific component by
|
||||
providing its name, like this:
|
||||
|
||||
```bash
|
||||
./x build --stage 0 library
|
||||
./x build --stage 1 library
|
||||
```
|
||||
|
||||
If you choose the `library` profile when running `x setup`, you can omit `--stage 0` (it's the
|
||||
If you choose the `library` profile when running `x setup`, you can omit `--stage 1` (it's the
|
||||
default).
|
||||
|
||||
## Creating a rustup toolchain
|
||||
|
|
@ -271,7 +269,6 @@ you will likely need to build at some point; for example, if you want
|
|||
to run the entire test suite).
|
||||
|
||||
```bash
|
||||
rustup toolchain link stage0 build/host/stage0-sysroot # beta compiler + stage0 std
|
||||
rustup toolchain link stage1 build/host/stage1
|
||||
rustup toolchain link stage2 build/host/stage2
|
||||
```
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ Look for existing targets to use as examples.
|
|||
After adding your target to the `rustc_target` crate you may want to add
|
||||
`core`, `std`, ... with support for your new target. In that case you will
|
||||
probably need access to some `target_*` cfg. Unfortunately when building with
|
||||
stage0 (the beta compiler), you'll get an error that the target cfg is
|
||||
stage0 (a precompiled compiler), you'll get an error that the target cfg is
|
||||
unexpected because stage0 doesn't know about the new target specification and
|
||||
we pass `--check-cfg` in order to tell it to check.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -91,7 +99,7 @@ for two reasons:
|
|||
additional rebuilds in some cases.
|
||||
|
||||
To avoid these problems:
|
||||
- Add `--build-dir=build-rust-analyzer` to all of the custom `x` commands in
|
||||
- Add `--build-dir=build/rust-analyzer` to all of the custom `x` commands in
|
||||
your editor's rust-analyzer configuration.
|
||||
(Feel free to choose a different directory name if desired.)
|
||||
- Modify the `rust-analyzer.rustfmt.overrideCommand` setting so that it points
|
||||
|
|
@ -100,10 +108,7 @@ To avoid these problems:
|
|||
copy of `rust-analyzer-proc-macro-srv` in that other build directory.
|
||||
|
||||
Using separate build directories for command-line builds and rust-analyzer
|
||||
requires extra disk space, and also means that running `./x clean` on the
|
||||
command-line will not clean out the separate build directory. To clean the
|
||||
separate build directory, run `./x clean --build-dir=build-rust-analyzer`
|
||||
instead.
|
||||
requires extra disk space.
|
||||
|
||||
### Visual Studio Code
|
||||
|
||||
|
|
@ -137,7 +142,7 @@ Task] instead:
|
|||
|
||||
### Neovim
|
||||
|
||||
For Neovim users there are several options for configuring for rustc. The
|
||||
For Neovim users, there are a few options. The
|
||||
easiest way is by using [neoconf.nvim](https://github.com/folke/neoconf.nvim/),
|
||||
which allows for project-local configuration files with the native LSP. The
|
||||
steps for how to use it are below. Note that they require rust-analyzer to
|
||||
|
|
@ -310,51 +315,15 @@ lets you use `cargo fmt`.
|
|||
[the section on vscode]: suggested.md#configuring-rust-analyzer-for-rustc
|
||||
[the section on rustup]: how-to-build-and-run.md?highlight=rustup#creating-a-rustup-toolchain
|
||||
|
||||
## Faster builds with `--keep-stage`.
|
||||
## Faster Builds with CI-rustc
|
||||
|
||||
Sometimes just checking whether the compiler builds is not enough. A common
|
||||
example is that you need to add a `debug!` statement to inspect the value of
|
||||
some state or better understand the problem. In that case, you don't really need
|
||||
a full build. By bypassing bootstrap's cache invalidation, you can often get
|
||||
these builds to complete very fast (e.g., around 30 seconds). The only catch is
|
||||
this requires a bit of fudging and may produce compilers that don't work (but
|
||||
that is easily detected and fixed).
|
||||
|
||||
The sequence of commands you want is as follows:
|
||||
|
||||
- Initial build: `./x build library`
|
||||
- As [documented previously], this will build a functional stage1 compiler as
|
||||
part of running all stage0 commands (which include building a `std`
|
||||
compatible with the stage1 compiler) as well as the first few steps of the
|
||||
"stage 1 actions" up to "stage1 (sysroot stage1) builds std".
|
||||
- Subsequent builds: `./x build library --keep-stage 1`
|
||||
- Note that we added the `--keep-stage 1` flag here
|
||||
|
||||
[documented previously]: ./how-to-build-and-run.md#building-the-compiler
|
||||
|
||||
As mentioned, the effect of `--keep-stage 1` is that we just _assume_ that the
|
||||
old standard library can be re-used. If you are editing the compiler, this is
|
||||
almost always true: you haven't changed the standard library, after all. But
|
||||
sometimes, it's not true: for example, if you are editing the "metadata" part of
|
||||
the compiler, which controls how the compiler encodes types and other states
|
||||
into the `rlib` files, or if you are editing things that wind up in the metadata
|
||||
(such as the definition of the MIR).
|
||||
|
||||
**The TL;DR is that you might get weird behavior from a compile when using
|
||||
`--keep-stage 1`** -- for example, strange [ICEs](../appendix/glossary.html#ice)
|
||||
or other panics. In that case, you should simply remove the `--keep-stage 1`
|
||||
from the command and rebuild. That ought to fix the problem.
|
||||
|
||||
You can also use `--keep-stage 1` when running tests. Something like this:
|
||||
|
||||
- Initial test run: `./x test tests/ui`
|
||||
- Subsequent test run: `./x test tests/ui --keep-stage 1`
|
||||
|
||||
### Iterating the standard library with `--keep-stage`
|
||||
|
||||
If you are making changes to the standard library, you can use `./x build
|
||||
--keep-stage 0 library` to iteratively rebuild the standard library without
|
||||
rebuilding the compiler.
|
||||
If you are not working on the compiler, you often don't need to build the compiler tree.
|
||||
For example, you can skip building the compiler and only build the `library` tree or the
|
||||
tools under `src/tools`. To achieve that, you have to enable this by setting the `download-rustc`
|
||||
option in your configuration. This tells bootstrap to use the latest nightly compiler for `stage > 0`
|
||||
steps, meaning it will have two precompiled compilers: stage0 compiler and `download-rustc` compiler
|
||||
for `stage > 0` steps. This way, it will never need to build the in-tree compiler. As a result, your
|
||||
build time will be significantly reduced by not building the in-tree compiler.
|
||||
|
||||
## Using incremental compilation
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,6 @@ adding a new command-line argument.
|
|||
unstable-options` flag.
|
||||
|
||||
[cli-docs]: https://doc.rust-lang.org/rustc/command-line-arguments.html
|
||||
[forge guide for new options]: https://forge.rust-lang.org/compiler/new_option.html
|
||||
[forge guide for new options]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#compiler-flags
|
||||
[unstable book]: https://doc.rust-lang.org/nightly/unstable-book/
|
||||
[`parse_bool`]: https://github.com/rust-lang/rust/blob/e5335592e78354e33d798d20c04bcd677c1df62d/src/librustc_session/options.rs#L307-L313
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
# Async closures/"coroutine-closures"
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
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,9 +12,11 @@ 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].
|
||||
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]: <https://github.com/rust-lang/rust/blob/5ca0e9fa9b2f92b463a0a2b0b34315e09c0b7236/compiler/rustc_ast_lowering/src/expr.rs#L1147>
|
||||
|
||||
|
|
@ -24,7 +30,7 @@ Like `async fn`, when lowering an async closure's body, we need to unconditional
|
|||
|
||||
[^l3]: <https://github.com/rust-lang/rust/blob/5ca0e9fa9b2f92b463a0a2b0b34315e09c0b7236/compiler/rustc_hir_typeck/src/upvar.rs#L250-L256>
|
||||
|
||||
## `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 +78,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,11 +104,11 @@ 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.
|
||||
|
||||
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.
|
||||
|
||||
|
|
@ -120,7 +126,7 @@ Since we've synthesized a new def id, this query is also responsible for feeding
|
|||
|
||||
[^b3]: <https://github.com/rust-lang/rust/blob/5ca0e9fa9b2f92b463a0a2b0b34315e09c0b7236/compiler/rustc_mir_transform/src/lib.rs#L339-L342>
|
||||
|
||||
## 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 +179,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 +268,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 +288,7 @@ This is represented by the `ConstructCoroutineInClosureShim`[^i1]. The `receiver
|
|||
|
||||
[^i3]: <https://github.com/rust-lang/rust/blob/07cbbdd69363da97075650e9be24b78af0bcdd23/compiler/rustc_middle/src/ty/instance.rs#L841>
|
||||
|
||||
## 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -866,19 +866,17 @@ struct](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/json/struct
|
|||
(and sub-structs) for the JSON serialization. Don't confuse this with
|
||||
[`errors::Diag`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html)!
|
||||
|
||||
## `#[rustc_on_unimplemented(...)]`
|
||||
## `#[rustc_on_unimplemented]`
|
||||
|
||||
The `#[rustc_on_unimplemented]` attribute allows trait definitions to add specialized
|
||||
notes to error messages when an implementation was expected but not found.
|
||||
You can refer to the trait's generic arguments by name and to the resolved type using `Self`.
|
||||
|
||||
For example:
|
||||
This attribute allows trait definitions to modify error messages when an implementation was
|
||||
expected but not found. The string literals in the attribute are format strings and can be
|
||||
formatted with named parameters. See the Formatting
|
||||
section below for what parameters are permitted.
|
||||
|
||||
```rust,ignore
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_on_unimplemented="an iterator over elements of type `{A}` \
|
||||
cannot be built from a collection of type `{Self}`"]
|
||||
#[rustc_on_unimplemented(message = "an iterator over \
|
||||
elements of type `{A}` cannot be built from a \
|
||||
collection of type `{Self}`")]
|
||||
trait MyIterator<A> {
|
||||
fn next(&mut self) -> A;
|
||||
}
|
||||
|
|
@ -895,32 +893,26 @@ fn main() {
|
|||
When the user compiles this, they will see the following;
|
||||
|
||||
```txt
|
||||
error[E0277]: the trait bound `&[{integer}]: MyIterator<char>` is not satisfied
|
||||
--> <anon>:14:5
|
||||
error[E0277]: an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]`
|
||||
--> src/main.rs:13:19
|
||||
|
|
||||
14 | iterate_chars(&[1, 2, 3][..]);
|
||||
| ^^^^^^^^^^^^^ an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]`
|
||||
13 | iterate_chars(&[1, 2, 3][..]);
|
||||
| ------------- ^^^^^^^^^^^^^^ the trait `MyIterator<char>` is not implemented for `&[{integer}]`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
|
||||
= note: required by `iterate_chars`
|
||||
note: required by a bound in `iterate_chars`
|
||||
```
|
||||
|
||||
`rustc_on_unimplemented` also supports advanced filtering for better targeting
|
||||
of messages, as well as modifying specific parts of the error message. You
|
||||
target the text of:
|
||||
|
||||
You can modify the contents of:
|
||||
- the main error message (`message`)
|
||||
- the label (`label`)
|
||||
- an extra note (`note`)
|
||||
- the note(s) (`note`)
|
||||
|
||||
For example, the following attribute
|
||||
|
||||
```rust,ignore
|
||||
#[rustc_on_unimplemented(
|
||||
message="message",
|
||||
label="label",
|
||||
note="note"
|
||||
)]
|
||||
#[rustc_on_unimplemented(message = "message", label = "label", note = "note")]
|
||||
trait MyIterator<A> {
|
||||
fn next(&mut self) -> A;
|
||||
}
|
||||
|
|
@ -930,45 +922,61 @@ Would generate the following output:
|
|||
|
||||
```text
|
||||
error[E0277]: message
|
||||
--> <anon>:14:5
|
||||
--> <file>:10:19
|
||||
|
|
||||
14 | iterate_chars(&[1, 2, 3][..]);
|
||||
| ^^^^^^^^^^^^^ label
|
||||
10 | iterate_chars(&[1, 2, 3][..]);
|
||||
| ------------- ^^^^^^^^^^^^^^ label
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: note
|
||||
= help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
|
||||
= note: required by `iterate_chars`
|
||||
= note: note
|
||||
note: required by a bound in `iterate_chars`
|
||||
```
|
||||
|
||||
To allow more targeted error messages, it is possible to filter the
|
||||
application of these fields based on a variety of attributes when using
|
||||
`on`:
|
||||
The functionality discussed so far is also available with
|
||||
[`#[diagnostic::on_unimplemented]`](https://doc.rust-lang.org/nightly/reference/attributes/diagnostics.html#the-diagnosticon_unimplemented-attribute).
|
||||
If you can, you should use that instead.
|
||||
|
||||
### Filtering
|
||||
|
||||
To allow more targeted error messages, it is possible to filter the
|
||||
application of these fields with `on`.
|
||||
|
||||
You can filter on the following boolean flags:
|
||||
- `crate_local`: whether the code causing the trait bound to not be
|
||||
fulfilled is part of the user's crate. This is used to avoid suggesting
|
||||
code changes that would require modifying a dependency.
|
||||
- Any of the generic arguments that can be substituted in the text can be
|
||||
referred by name as well for filtering, like `Rhs="i32"`, except for
|
||||
`Self`.
|
||||
- `_Self`: to filter only on a particular calculated trait resolution, like
|
||||
`Self="std::iter::Iterator<char>"`. This is needed because `Self` is a
|
||||
keyword which cannot appear in attributes.
|
||||
- `direct`: user-specified rather than derived obligation.
|
||||
- `from_desugaring`: usable both as boolean (whether the flag is present)
|
||||
or matching against a particular desugaring. The desugaring is identified
|
||||
with its variant name in the `DesugaringKind` enum.
|
||||
- `direct`: whether this is an user-specified rather than derived obligation.
|
||||
- `from_desugaring`: whether we are in some kind of desugaring, like `?`
|
||||
or a `try` block for example. This flag can also be matched on, see below.
|
||||
|
||||
For example, the `Iterator` trait can be annotated in the following way:
|
||||
You can match on the following names and values, using `name = "value"`:
|
||||
- `cause`: Match against one variant of the `ObligationCauseCode`
|
||||
enum. Only `"MainFunctionType"` is supported.
|
||||
- `from_desugaring`: Match against a particular variant of the `DesugaringKind`
|
||||
enum. The desugaring is identified by its variant name, for example
|
||||
`"QuestionMark"` for `?` desugaring or `"TryBlock"` for `try` blocks.
|
||||
- `Self` and any generic arguments of the trait, like `Self = "alloc::string::String"`
|
||||
or `Rhs="i32"`.
|
||||
|
||||
The compiler can provide several values to match on, for example:
|
||||
- the self_ty, pretty printed with and without type arguments resolved.
|
||||
- `"{integral}"`, if self_ty is an integral of which the type is known.
|
||||
- `"[]"`, `"[{ty}]"`, `"[{ty}; _]"`, `"[{ty}; $N]"` when applicable.
|
||||
- references to said slices and arrays.
|
||||
- `"fn"`, `"unsafe fn"` or `"#[target_feature] fn"` when self is a function.
|
||||
- `"{integer}"` and `"{float}"` if the type is a number but we haven't inferred it yet.
|
||||
- combinations of the above, like `"[{integral}; _]"`.
|
||||
|
||||
For example, the `Iterator` trait can be filtered in the following way:
|
||||
|
||||
```rust,ignore
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
_Self="&str",
|
||||
note="call `.chars()` or `.as_bytes()` on `{Self}`"
|
||||
),
|
||||
message="`{Self}` is not an iterator",
|
||||
label="`{Self}` is not an iterator",
|
||||
note="maybe try calling `.iter()` or a similar method"
|
||||
on(Self = "&str", note = "call `.chars()` or `.as_bytes()` on `{Self}`"),
|
||||
message = "`{Self}` is not an iterator",
|
||||
label = "`{Self}` is not an iterator",
|
||||
note = "maybe try calling `.iter()` or a similar method"
|
||||
)]
|
||||
pub trait Iterator {}
|
||||
```
|
||||
|
|
@ -997,15 +1005,47 @@ error[E0277]: `&str` is not an iterator
|
|||
= note: required by `std::iter::IntoIterator::into_iter`
|
||||
```
|
||||
|
||||
If you need to filter on multiple attributes, you can use `all`, `any` or
|
||||
`not` in the following way:
|
||||
The `on` filter accepts `all`, `any` and `not` predicates similar to the `cfg` attribute:
|
||||
|
||||
```rust,ignore
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
all(_Self="&str", T="std::string::String"),
|
||||
note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`"
|
||||
)
|
||||
)]
|
||||
pub trait From<T>: Sized { /* ... */ }
|
||||
#[rustc_on_unimplemented(on(
|
||||
all(Self = "&str", T = "alloc::string::String"),
|
||||
note = "you can coerce a `{T}` into a `{Self}` by writing `&*variable`"
|
||||
))]
|
||||
pub trait From<T>: Sized {
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
### Formatting
|
||||
|
||||
The string literals are format strings that accept parameters wrapped in braces
|
||||
but positional and listed parameters and format specifiers are not accepted.
|
||||
The following parameter names are valid:
|
||||
- `Self` and all generic parameters of the trait.
|
||||
- `This`: the name of the trait the attribute is on, without generics.
|
||||
- `Trait`: the name of the "sugared" trait. See `TraitRefPrintSugared`.
|
||||
- `ItemContext`: the kind of `hir::Node` we're in, things like `"an async block"`,
|
||||
`"a function"`, `"an async function"`, etc.
|
||||
|
||||
Something like:
|
||||
|
||||
```rust,ignore
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_on_unimplemented(message = "Self = `{Self}`, \
|
||||
T = `{T}`, this = `{This}`, trait = `{Trait}`, \
|
||||
context = `{ItemContext}`")]
|
||||
pub trait From<T>: Sized {
|
||||
fn from(x: T) -> Self;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: i8 = From::from(42_i32);
|
||||
}
|
||||
```
|
||||
|
||||
Will format the message into
|
||||
```text
|
||||
"Self = `i8`, T = `i32`, this = `From`, trait = `From<i32>`, context = `a function`"
|
||||
```
|
||||
|
|
|
|||
|
|
@ -174,7 +174,8 @@ As mentioned previously, the distinction between early and late bound parameters
|
|||
- When naming a function (early)
|
||||
- When calling a function (late)
|
||||
|
||||
There currently is no syntax for explicitly specifying generic arguments for late bound parameters as part of the call step, only specifying generic arguments when naming a function. The syntax `foo::<'static>();`, despite being part of a function call, behaves as `(foo::<'static>)();` and instantiates the early bound generic parameters on the function item type.
|
||||
There is currently no syntax for explicitly specifying generic arguments for late bound parameters during the call step; generic arguments can only be specified for early bound parameters when naming a function.
|
||||
The syntax `foo::<'static>();`, despite being part of a function call, behaves as `(foo::<'static>)();` and instantiates the early bound generic parameters on the function item type.
|
||||
|
||||
See the following example:
|
||||
```rust
|
||||
|
|
|
|||
|
|
@ -73,21 +73,32 @@ To build a corpus, you may want to use:
|
|||
|
||||
- The rustc/rust-analyzer/clippy test suites (or even source code) --- though avoid
|
||||
tests that are already known to cause failures, which often begin with comments
|
||||
like `// failure-status: 101` or `// known-bug: #NNN`.
|
||||
- The already-fixed ICEs in [Glacier][glacier] --- though avoid the unfixed
|
||||
ones in `ices/`!
|
||||
like `//@ failure-status: 101` or `//@ known-bug: #NNN`.
|
||||
- The already-fixed ICEs in the archived [Glacier][glacier] repository --- though
|
||||
avoid the unfixed ones in `ices/`!
|
||||
|
||||
[glacier]: https://github.com/rust-lang/glacier
|
||||
|
||||
## Extra credit
|
||||
|
||||
Here are a few things you can do to help the Rust project after filing an ICE.
|
||||
|
||||
- [Bisect][bisect] the bug to figure out when it was introduced
|
||||
- [Bisect][bisect] the bug to figure out when it was introduced.
|
||||
If you find the regressing PR / commit, you can mark the issue with the label
|
||||
`S-has-bisection`. If not, consider applying `E-needs-bisection` instead.
|
||||
- Fix "distractions": problems with the test case that don't contribute to
|
||||
triggering the ICE, such as syntax errors or borrow-checking errors
|
||||
- Minimize the test case (see below)
|
||||
- Add the minimal test case to [Glacier][glacier]
|
||||
- Minimize the test case (see below). If successful, you can label the
|
||||
issue with `S-has-mcve`. Otherwise, you can apply `E-needs-mcve`.
|
||||
- Add the minimal test case to the rust-lang/rust repo as a [crashes test].
|
||||
While you're at it, consider including other "untracked" crashes in your PR.
|
||||
Please don't forget to mark your issue with `S-bug-has-test` afterwards.
|
||||
|
||||
See also [applying and removing labels][labeling].
|
||||
|
||||
[bisect]: https://rust-lang.github.io/cargo-bisect-rustc/
|
||||
[crashes test]: tests/compiletest.html#crashes-tests
|
||||
[labeling]: https://forge.rust-lang.org/release/issue-triaging.html#applying-and-removing-labels
|
||||
|
||||
## Minimization
|
||||
|
||||
|
|
@ -143,7 +154,6 @@ ICEs that require debug assertions to reproduce should be tagged
|
|||
- [tree-splicer][tree-splicer] generates new source files by combining existing
|
||||
ones while maintaining correct syntax
|
||||
|
||||
[glacier]: https://github.com/rust-lang/glacier
|
||||
[fuzz-rustc]: https://github.com/dwrensha/fuzz-rustc
|
||||
[icemaker]: https://github.com/matthiaskrgr/icemaker/
|
||||
[tree-splicer]: https://github.com/langston-barrett/tree-splicer/
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ filtering the search to areas you're interested in. For example:
|
|||
Not all important or beginner work has issue labels.
|
||||
See below for how to find work that isn't labelled.
|
||||
|
||||
[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+
|
||||
[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+-linked%3Apr+
|
||||
[Triage]: ./contributing.md#issue-triage
|
||||
|
||||
### Recurring work
|
||||
|
|
@ -98,8 +98,6 @@ Some work is too large to be done by a single person. In this case, it's common
|
|||
issues" to co-ordinate the work between contributors. Here are some example tracking issues where
|
||||
it's easy to pick up work without a large time commitment:
|
||||
|
||||
- [Rustdoc Askama Migration](https://github.com/rust-lang/rust/issues/108868)
|
||||
- [Diagnostic Translation](https://github.com/rust-lang/rust/issues/100717)
|
||||
- [Move UI tests to subdirectories](https://github.com/rust-lang/rust/issues/73494)
|
||||
|
||||
If you find more recurring work, please feel free to add it here!
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`).
|
|||
[`mk_args`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.mk_args
|
||||
[adtdefid]: ./ty_module/generic_arguments.md#adtdef-and-defid
|
||||
[`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html
|
||||
[`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TraitRef.html
|
||||
[`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TraitRef.html
|
||||
[`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/type.TyKind.html
|
||||
[traits]: ./traits/resolution.md
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,10 @@ In this example:
|
|||
|
||||
When interfacing with the type system it will often be the case that it's necessary to request a type be normalized. There are a number of different entry points to the underlying normalization logic and each entry point should only be used in specific parts of the compiler.
|
||||
|
||||
An additional complication is that the compiler is currently undergoing a transition from the old trait solver to the new trait solver. As part of this transition our approach to normalization in the compiler has changed somewhat significantly, resulting in some normalization entry points being "old solver only" slated for removal in the long-term once the new solver has stabilized.
|
||||
<!-- date-check: May 2025 -->
|
||||
An additional complication is that the compiler is currently undergoing a transition from the old trait solver to the new trait solver.
|
||||
As part of this transition our approach to normalization in the compiler has changed somewhat significantly, resulting in some normalization entry points being "old solver only" slated for removal in the long-term once the new solver has stabilized.
|
||||
The transition can be tracked via the [WG-trait-system-refactor](https://github.com/rust-lang/rust/labels/WG-trait-system-refactor) label in Github.
|
||||
|
||||
Here is a rough overview of the different entry points to normalization in the compiler:
|
||||
- `infcx.at.structurally_normalize`
|
||||
|
|
@ -262,13 +265,13 @@ Another problem was that it was not possible to normalize `ParamEnv`s correctly
|
|||
|
||||
Given a type such as `for<'a> fn(<?x as Trait<'a>::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> <?x as Trait<'a>>::Assoc -> ?y`, this would result in errors in cases where `<?x as Trait<'a>>::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> <?x as Trait<'a>>::Assoc -> ?y`, this would result in errors in cases where `<?x as Trait<'a>>::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]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html#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
|
||||
|
|
@ -306,4 +309,4 @@ Const aliases differ from type aliases a bit here; well formedness of const alia
|
|||
|
||||
[^5]: Const aliases certainly wouldn't be *less* sound than type aliases if we stopped doing this
|
||||
|
||||
[const_evaluatable]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ClauseKind.html#variant.ConstEvaluatable
|
||||
[const_evaluatable]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ClauseKind.html#variant.ConstEvaluatable
|
||||
|
|
|
|||
|
|
@ -13,13 +13,16 @@ it can work across functions and function bodies.
|
|||
To help explain how it works, let's consider an example.
|
||||
|
||||
```rust
|
||||
#![feature(type_alias_impl_trait)]
|
||||
mod m {
|
||||
pub type Seq<T> = impl IntoIterator<Item = T>;
|
||||
|
||||
#[define_opaque(Seq)]
|
||||
pub fn produce_singleton<T>(t: T) -> Seq<T> {
|
||||
vec![t]
|
||||
}
|
||||
|
||||
#[define_opaque(Seq)]
|
||||
pub fn produce_doubleton<T>(t: T, u: T) -> Seq<T> {
|
||||
vec![t, u]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ trait Foo {
|
|||
|
||||
Failing because a down-stream impl could theoretically provide an
|
||||
implementation for `RPITIT` without providing an implementation of
|
||||
`foo`:
|
||||
`bar`:
|
||||
|
||||
```text
|
||||
error[E0308]: mismatched types
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ It acts as the glue for running the various phases of the compiler in the correc
|
|||
using the interface defined in the [`rustc_interface`] crate. Where possible, using [`rustc_driver`] rather than [`rustc_interface`] is recommended.
|
||||
|
||||
The main entry point of [`rustc_driver`] is [`rustc_driver::run_compiler`][rd_rc].
|
||||
This builder accepts the same command-line args as rustc as well as an implementation of [`Callbacks`][cb] and a couple of other optional options.
|
||||
[`Callbacks`][cb] is a `trait` that allows for custom compiler configuration,
|
||||
This builder accepts the same command-line args as rustc as well as an implementation of [`Callbacks`] and a couple of other optional options.
|
||||
[`Callbacks`] is a `trait` that allows for custom compiler configuration,
|
||||
as well as allowing custom code to run after different phases of the compilation.
|
||||
|
||||
## `rustc_interface`
|
||||
|
|
@ -33,14 +33,8 @@ specifically [`rustc_driver_impl::run_compiler`][rdi_rc]
|
|||
[`Compiler`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Compiler.html
|
||||
[`rustc_driver`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/
|
||||
[`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html
|
||||
[`Session`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html
|
||||
[`SourceMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/source_map/struct.SourceMap.html
|
||||
[`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html
|
||||
[Appendix A]: appendix/stupid-stats.html
|
||||
[cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html
|
||||
[`Callbacks`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html
|
||||
[example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-interface-example.rs
|
||||
[i_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/fn.run_compiler.html
|
||||
[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html
|
||||
[rdi_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver_impl/fn.run_compiler.html
|
||||
[stupid-stats]: https://github.com/nrc/stupid-stats
|
||||
[`nightly-rustc`]: https://doc.rust-lang.org/nightly/nightly-rustc/
|
||||
|
|
|
|||
|
|
@ -281,10 +281,10 @@ using `XPath` notation to get a precise look at the output. The full
|
|||
description of all the commands available to `rustdoc` tests (e.g. [`@has`] and
|
||||
[`@matches`]) is in [`htmldocck.py`].
|
||||
|
||||
To use multiple crates in a `rustdoc` test, add `// aux-build:filename.rs`
|
||||
To use multiple crates in a `rustdoc` test, add `//@ aux-build:filename.rs`
|
||||
to the top of the test file. `filename.rs` should be placed in an `auxiliary`
|
||||
directory relative to the test file with the comment. If you need to build
|
||||
docs for the auxiliary file, use `// build-aux-docs`.
|
||||
docs for the auxiliary file, use `//@ build-aux-docs`.
|
||||
|
||||
In addition, there are separate tests for the search index and `rustdoc`'s
|
||||
ability to query it. The files in `tests/rustdoc-js` each contain a
|
||||
|
|
|
|||
|
|
@ -93,13 +93,13 @@ does is call the `main()` that's in this crate's `lib.rs`, though.)
|
|||
interactivity. For information on how to write this form of test,
|
||||
see [`tests/rustdoc-gui/README.md`][rustdoc-gui-readme]
|
||||
as well as [the description of the `.goml` format][goml-script]
|
||||
* Additionally, JavaScript type annotations are written using [TypeScript-flavored JSDoc]
|
||||
comments and an external d.ts file. The code itself is plain, valid JavaScript; we only
|
||||
use tsc as a linter.
|
||||
* The tests on the structure of rustdoc HTML output are located in `tests/rustdoc`,
|
||||
* Tests on the structure of rustdoc HTML output are located in `tests/rustdoc`,
|
||||
where they're handled by the test runner of bootstrap and
|
||||
the supplementary script `src/etc/htmldocck.py`.
|
||||
[These tests have several extra directives available to them](./rustdoc-internals/rustdoc-test-suite.md).
|
||||
* Additionally, JavaScript type annotations are written using [TypeScript-flavored JSDoc]
|
||||
comments and an external d.ts file. The code itself is plain, valid JavaScript; we only
|
||||
use tsc as a linter.
|
||||
|
||||
[TypeScript-flavored JSDoc]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html
|
||||
[rustdoc-gui-readme]: https://github.com/rust-lang/rust/blob/master/tests/rustdoc-gui/README.md
|
||||
|
|
@ -116,6 +116,28 @@ Certain browser features that require secure origins, like `localStorage` and
|
|||
Service Workers, don't work reliably. We can still use such features but we
|
||||
should make sure pages are still usable without them.
|
||||
|
||||
Rustdoc [does not type-check function bodies][platform-specific docs].
|
||||
This works by [overriding the built-in queries for typeck][override queries],
|
||||
by [silencing name resolution errors], and by [not resolving opaque types].
|
||||
This comes with several caveats: in particular, rustdoc *cannot* run any parts of the compiler that
|
||||
require type-checking bodies; for example it cannot generate `.rlib` files or run most lints.
|
||||
We want to move away from this model eventually, but we need some alternative for
|
||||
[the people using it][async-std]; see [various][zulip stop accepting broken code]
|
||||
[previous][rustdoc meeting 2024-07-08] [zulip][compiler meeting 2023-01-26] [discussion][notriddle rfc].
|
||||
For examples of code that breaks if this hack is removed, see
|
||||
[`tests/rustdoc-ui/error-in-impl-trait`].
|
||||
|
||||
[platform-specific docs]: https://doc.rust-lang.org/rustdoc/advanced-features.html#interactions-between-platform-specific-docs
|
||||
[override queries]: https://github.com/rust-lang/rust/blob/52bf0cf795dfecc8b929ebb1c1e2545c3f41d4c9/src/librustdoc/core.rs#L299-L323
|
||||
[silencing name resolution errors]: https://github.com/rust-lang/rust/blob/52bf0cf795dfecc8b929ebb1c1e2545c3f41d4c9/compiler/rustc_resolve/src/late.rs#L4517
|
||||
[not resolving opaque types]: https://github.com/rust-lang/rust/blob/52bf0cf795dfecc8b929ebb1c1e2545c3f41d4c9/compiler/rustc_hir_analysis/src/check/check.rs#L188-L194
|
||||
[async-std]: https://github.com/rust-lang/rust/issues/75100
|
||||
[rustdoc meeting 2024-07-08]: https://rust-lang.zulipchat.com/#narrow/channel/393423-t-rustdoc.2Fmeetings/topic/meeting.202024-07-08/near/449969836
|
||||
[compiler meeting 2023-01-26]: https://rust-lang.zulipchat.com/#narrow/channel/238009-t-compiler.2Fmeetings/topic/.5Bweekly.5D.202023-01-26/near/323755789
|
||||
[zulip stop accepting broken code]: https://rust-lang.zulipchat.com/#narrow/stream/266220-rustdoc/topic/stop.20accepting.20broken.20code
|
||||
[notriddle rfc]: https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/Pre-RFC.3A.20stop.20accepting.20broken.20code
|
||||
[`tests/rustdoc-ui/error-in-impl-trait`]: https://github.com/rust-lang/rust/tree/163cb4ea3f0ae3bc7921cc259a08a7bf92e73ee6/tests/rustdoc-ui/error-in-impl-trait
|
||||
|
||||
## Multiple runs, same output directory
|
||||
|
||||
Rustdoc can be run multiple times for varying inputs, with its output set to the
|
||||
|
|
|
|||
|
|
@ -237,14 +237,14 @@ Alternatively, we could simply always treat the equate branch of `normalizes_to`
|
|||
Any cycles should result in infinite types, which aren't supported anyways and would only
|
||||
result in overflow when deeply normalizing for codegen.
|
||||
|
||||
experimentation and examples: https://hackmd.io/-8p0AHnzSq2VAE6HE_wX-w?view
|
||||
experimentation and examples: <https://hackmd.io/-8p0AHnzSq2VAE6HE_wX-w?view>
|
||||
|
||||
Another attempt at a summary.
|
||||
- in projection eq, we must make progress with constraining the rhs
|
||||
- a cycle is only ok if while equating we have a rigid ty on the lhs after norm at least once
|
||||
- cycles outside of the recursive `eq` call of `normalizes_to` are always fine
|
||||
|
||||
[^1]: related: https://coq.inria.fr/refman/language/core/coinductive.html#top-level-definitions-of-corecursive-functions
|
||||
[^1]: related: <https://coq.inria.fr/refman/language/core/coinductive.html#top-level-definitions-of-corecursive-functions>
|
||||
|
||||
[perfect derive]: https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive
|
||||
[ex1]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0a9c3830b93a2380e6978d6328df8f72
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
# Opaque types in the new solver
|
||||
|
||||
The way opaque types are handled in the new solver differs from the old implementation.
|
||||
The way [opaque types] are handled in the new solver differs from the old implementation.
|
||||
This should be a self-contained explanation of the behavior in the new solver.
|
||||
|
||||
[opaque types]: ../opaque-types-type-alias-impl-trait.md
|
||||
|
||||
## opaques are alias types
|
||||
|
||||
Opaque types are treated the same as other aliases, most notabily associated types,
|
||||
|
|
|
|||
|
|
@ -66,9 +66,9 @@ kinds of builds (sets of jobs).
|
|||
### Pull Request builds
|
||||
|
||||
After each push to a pull request, a set of `pr` jobs are executed. Currently,
|
||||
these execute the `x86_64-gnu-llvm-X`, `x86_64-gnu-tools`, `mingw-check` and
|
||||
`mingw-check-tidy` jobs, all running on Linux. These execute a relatively short
|
||||
(~30 minutes) and lightweight test suite that should catch common issues. More
|
||||
these execute the `x86_64-gnu-llvm-X`, `x86_64-gnu-tools`, `mingw-check-1`, `mingw-check-2`
|
||||
and `mingw-check-tidy` jobs, all running on Linux. These execute a relatively short
|
||||
(~40 minutes) and lightweight test suite that should catch common issues. More
|
||||
specifically, they run a set of lints, they try to perform a cross-compile check
|
||||
build to Windows mingw (without producing any artifacts) and they test the
|
||||
compiler using a *system* version of LLVM. Unfortunately, it would take too many
|
||||
|
|
@ -100,8 +100,8 @@ Most platforms only run the build steps, some run a restricted set of tests,
|
|||
only a subset run the full suite of tests (see Rust's [platform tiers]).
|
||||
|
||||
Auto jobs are defined in the `auto` section of [`jobs.yml`]. They are executed
|
||||
on the `auto` branch under the `rust-lang-ci/rust` repository[^rust-lang-ci] and
|
||||
their results can be seen [here](https://github.com/rust-lang-ci/rust/actions),
|
||||
on the `auto` branch under the `rust-lang/rust` repository and
|
||||
their results can be seen [here](https://github.com/rust-lang/rust/actions),
|
||||
although usually you will be notified of the result by a comment made by bors on
|
||||
the corresponding PR.
|
||||
|
||||
|
|
@ -110,9 +110,6 @@ more [here](#merging-prs-serially-with-bors).
|
|||
|
||||
[platform tiers]: https://forge.rust-lang.org/release/platform-support.html#rust-platform-support
|
||||
|
||||
[^rust-lang-ci]: The `auto` and `try` jobs run under the `rust-lang-ci` fork for
|
||||
historical reasons. This may change in the future.
|
||||
|
||||
### Try builds
|
||||
|
||||
Sometimes we want to run a subset of the test suite on CI for a given PR, or
|
||||
|
|
@ -179,8 +176,8 @@ the pattern as Markdown.
|
|||
> that are exercised this way.
|
||||
|
||||
Try jobs are defined in the `try` section of [`jobs.yml`]. They are executed on
|
||||
the `try` branch under the `rust-lang-ci/rust` repository[^rust-lang-ci] and
|
||||
their results can be seen [here](https://github.com/rust-lang-ci/rust/actions),
|
||||
the `try` branch under the `rust-lang/rust` repository and
|
||||
their results can be seen [here](https://github.com/rust-lang/rust/actions),
|
||||
although usually you will be notified of the result by a comment made by bors on
|
||||
the corresponding PR.
|
||||
|
||||
|
|
@ -189,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.
|
||||
|
||||
<div class="warning">
|
||||
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.
|
||||
|
||||
</div>
|
||||
|
||||
[rustc-perf]: https://github.com/rust-lang/rustc-perf
|
||||
|
|
@ -355,7 +354,7 @@ invalidated if one of the following changes:
|
|||
- Files copied into the Docker image in the Dockerfile
|
||||
- The architecture of the GitHub runner (x86 or ARM)
|
||||
|
||||
[ghcr.io]: https://github.com/rust-lang-ci/rust/pkgs/container/rust-ci
|
||||
[ghcr.io]: https://github.com/rust-lang/rust/pkgs/container/rust-ci
|
||||
[Docker registry caching]: https://docs.docker.com/build/cache/backends/registry/
|
||||
|
||||
### LLVM caching with sccache
|
||||
|
|
@ -446,7 +445,7 @@ particular job, it is probably easiest to just look at the build log. To do
|
|||
this:
|
||||
|
||||
1. Go to
|
||||
<https://github.com/rust-lang-ci/rust/actions?query=branch%3Aauto+is%3Asuccess>
|
||||
<https://github.com/rust-lang/rust/actions?query=branch%3Aauto+is%3Asuccess>
|
||||
to find the most recently successful build, and click on it.
|
||||
2. Choose the job you are interested in on the left-hand side.
|
||||
3. Click on the gear icon and choose "View raw logs"
|
||||
|
|
@ -458,7 +457,6 @@ this:
|
|||
[`jobs.yml`]: https://github.com/rust-lang/rust/blob/master/src/ci/github-actions/jobs.yml
|
||||
[`.github/workflows/ci.yml`]: https://github.com/rust-lang/rust/blob/master/.github/workflows/ci.yml
|
||||
[`src/ci/citool`]: https://github.com/rust-lang/rust/blob/master/src/ci/citool
|
||||
[rust-lang-ci]: https://github.com/rust-lang-ci/rust/actions
|
||||
[bors]: https://github.com/bors
|
||||
[homu]: https://github.com/rust-lang/homu
|
||||
[merge queue]: https://bors.rust-lang.org/queue/rust
|
||||
|
|
|
|||
|
|
@ -438,7 +438,9 @@ To work around this when working on a particular test, temporarily create a
|
|||
with these contents:
|
||||
|
||||
<div class="warning">
|
||||
|
||||
Be careful not to add this `Cargo.toml` or its `Cargo.lock` to your actual PR!
|
||||
|
||||
</div>
|
||||
|
||||
```toml
|
||||
|
|
@ -546,10 +548,10 @@ only running the main `coverage` suite.
|
|||
|
||||
[`tests/crashes`] serve as a collection of tests that are expected to cause the
|
||||
compiler to ICE, panic or crash in some other way, so that accidental fixes are
|
||||
tracked. This was formally done at <https://github.com/rust-lang/glacier> but
|
||||
tracked. Formerly, this was done at <https://github.com/rust-lang/glacier> but
|
||||
doing it inside the rust-lang/rust testsuite is more convenient.
|
||||
|
||||
It is imperative that a test in the suite causes rustc to ICE, panic or crash
|
||||
It is imperative that a test in the suite causes rustc to ICE, panic, or
|
||||
crash in some other way. A test will "pass" if rustc exits with an exit status
|
||||
other than 1 or 0.
|
||||
|
||||
|
|
@ -560,9 +562,12 @@ If you want to see verbose stdout/stderr, you need to set
|
|||
$ COMPILETEST_VERBOSE_CRASHES=1 ./x test tests/crashes/999999.rs --stage 1
|
||||
```
|
||||
|
||||
When adding crashes from <https://github.com/rust-lang/rust/issues>, the issue
|
||||
number should be noted in the file name (`12345.rs` should suffice) and also
|
||||
inside the file include a `//@ known-bug: #4321` directive.
|
||||
Anyone can add ["untracked" crashes] from the issue tracker. It's strongly
|
||||
recommended to include test cases from several issues in a single PR.
|
||||
When you do so, each issue number should be noted in the file name (`12345.rs`
|
||||
should suffice) and also inside the file by means of a `//@ known-bug: #12345`
|
||||
directive. Please [label][labeling] the relevant issues with `S-bug-has-test`
|
||||
afterwards.
|
||||
|
||||
If you happen to fix one of the crashes, please move it to a fitting
|
||||
subdirectory in `tests/ui` and give it a meaningful name. Please add a doc
|
||||
|
|
@ -585,6 +590,8 @@ a subset first. The issue numbers can be found in the file name or the `//@
|
|||
known-bug` directive inside the test file.
|
||||
|
||||
[`tests/crashes`]: https://github.com/rust-lang/rust/tree/master/tests/crashes
|
||||
["untracked" crashes]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+state%3Aopen+label%3AI-ICE%2CI-crash+label%3AT-compiler+label%3AS-has-mcve+-label%3AS-bug-has-test
|
||||
[labeling]: https://forge.rust-lang.org/release/issue-triaging.html#applying-and-removing-labels
|
||||
|
||||
## Building auxiliary crates
|
||||
|
||||
|
|
@ -614,7 +621,7 @@ file). The `-L` flag is used to find the extern crates.
|
|||
`aux-crate` is very similar to `aux-build`. However, it uses the `--extern` flag
|
||||
to link to the extern crate to make the crate be available as an extern prelude.
|
||||
That allows you to specify the additional syntax of the `--extern` flag, such as
|
||||
renaming a dependency. For example, `// aux-crate:foo=bar.rs` will compile
|
||||
renaming a dependency. For example, `//@ aux-crate:foo=bar.rs` will compile
|
||||
`auxiliary/bar.rs` and make it available under then name `foo` within the test.
|
||||
This is similar to how Cargo does dependency renaming.
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ not be exhaustive. Directives can generally be found by browsing the
|
|||
| `aux-crate` | Like `aux-build` but makes available as extern prelude | All except `run-make` | `<extern_prelude_name>=<path/to/aux/file.rs>` |
|
||||
| `aux-codegen-backend` | Similar to `aux-build` but pass the compiled dylib to `-Zcodegen-backend` when building the main file | `ui-fulldeps` | Path to codegen backend file |
|
||||
| `proc-macro` | Similar to `aux-build`, but for aux forces host and don't use `-Cprefer-dynamic`[^pm]. | All except `run-make` | Path to auxiliary proc-macro `.rs` file |
|
||||
| `build_aux_docs` | Build docs for auxiliaries as well | All except `run-make` | N/A |
|
||||
| `build-aux-docs` | Build docs for auxiliaries as well | All except `run-make` | N/A |
|
||||
|
||||
[^pm]: please see the Auxiliary proc-macro section in the
|
||||
[compiletest](./compiletest.md) chapter for specifics.
|
||||
|
|
@ -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 |
|
||||
|
||||
<div class="warning">
|
||||
|
||||
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.
|
||||
|
||||
</div>
|
||||
|
||||
### Rustdoc
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
<div class="warning">
|
||||
|
||||
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.
|
||||
|
||||
</div>
|
||||
|
||||
A test can use [`minicore`] by specifying the `//@ add-core-stubs` directive.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
<div class="warning">
|
||||
|
||||
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.
|
||||
|
||||
</div>
|
||||
|
||||
```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.
|
||||
|
||||
<div class="warning">
|
||||
|
||||
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.
|
||||
|
||||
</div>
|
||||
|
||||
### Run all tests using a stage 2 compiler
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ They have several forms, but generally are a comment with the diagnostic level
|
|||
to write out the entire message, just make sure to include the important part of
|
||||
the message to make it self-documenting.
|
||||
|
||||
The error annotation needs to match with the line of the diagnostic. There are
|
||||
Most error annotations need to match with the line of the diagnostic. There are
|
||||
several ways to match the message with the line (see the examples below):
|
||||
|
||||
* `~`: Associates the error level and message with the *current* line
|
||||
|
|
@ -205,9 +205,6 @@ several ways to match the message with the line (see the examples below):
|
|||
* `~v`: Associates the error level and message with the *next* error
|
||||
annotation line. Each symbol (`v`) that you add adds a line to this, so `~vvv`
|
||||
is three lines below the error annotation line.
|
||||
* `~?`: Used to match error levels and messages with errors not having line
|
||||
information. These can be placed on any line in the test file, but are
|
||||
conventionally placed at the end.
|
||||
|
||||
Example:
|
||||
|
||||
|
|
@ -222,6 +219,10 @@ The space character between `//~` (or other variants) and the subsequent text is
|
|||
negligible (i.e. there is no semantic difference between `//~ ERROR` and
|
||||
`//~ERROR` although the former is more common in the codebase).
|
||||
|
||||
`~? <diagnostic kind>` (example being `~? ERROR`)
|
||||
is used to match diagnostics without line information.
|
||||
These can be placed on any line in the test file, but are conventionally placed at the end.
|
||||
|
||||
### Error annotation examples
|
||||
|
||||
Here are examples of error annotations on different lines of UI test source.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# `Binder` and Higher ranked regions
|
||||
|
||||
Sometimes we define generic parameters not on an item but as part of a type or a where clauses. As an example the type `for<'a> fn(&'a u32)` or the where clause `for<'a> T: Trait<'a>` both introduce a generic lifetime named `'a`. Currently there is no stable syntax for `for<T>` or `for<const N: usize>` but on nightly `feature(non_lifetime_binders)` feature can be used to write where clauses (but not types) using `for<T>`/`for<const N: usize>`.
|
||||
Sometimes we define generic parameters not on an item but as part of a type or a where clause. As an example the type `for<'a> fn(&'a u32)` or the where clause `for<'a> T: Trait<'a>` both introduce a generic lifetime named `'a`. Currently there is no stable syntax for `for<T>` or `for<const N: usize>` but on nightly `feature(non_lifetime_binders)` can be used to write where clauses (but not types) using `for<T>`/`for<const N: usize>`.
|
||||
|
||||
The `for` is referred to as a "binder" because it brings new names into scope. In rustc we use the `Binder` type to track where these parameters are introduced and what the parameters are (i.e. how many and whether the parameter is a type/const/region). A type such as `for<'a> fn(&'a u32)` would be
|
||||
represented in rustc as:
|
||||
|
|
@ -13,8 +13,9 @@ Binder(
|
|||
|
||||
Usages of these parameters is represented by the `RegionKind::Bound` (or `TyKind::Bound`/`ConstKind::Bound` variants). These bound regions/types/consts are composed of two main pieces of data:
|
||||
- A [DebruijnIndex](../appendix/background.md#what-is-a-de-bruijn-index) to specify which binder we are referring to.
|
||||
- A [`BoundVar`] which specifies which of the parameters the `Binder` introduces we are referring to.
|
||||
- We also sometimes store some extra information for diagnostics reasons via the [`BoundTyKind`]/[`BoundRegionKind`] but this is not important for type equality or more generally the semantics of `Ty`. (omitted from the above example)
|
||||
- A [`BoundVar`] which specifies which of the parameters that the `Binder` introduces we are referring to.
|
||||
|
||||
We also sometimes store some extra information for diagnostics reasons via the [`BoundTyKind`]/[`BoundRegionKind`] but this is not important for type equality or more generally the semantics of `Ty`. (omitted from the above example)
|
||||
|
||||
In debug output (and also informally when talking to each other) we tend to write these bound variables in the format of `^DebruijnIndex_BoundVar`. The above example would instead be written as `Binder(fn(&'^0_0), &[BoundVariableKind::Region])`. Sometimes when the `DebruijnIndex` is `0` we just omit it and would write `^0`.
|
||||
|
||||
|
|
@ -43,7 +44,7 @@ Binder(
|
|||
&[BoundVariableKind::Region(...)],
|
||||
)
|
||||
```
|
||||
This would cause all kinds of issues as the region `'^1_0` refers to a binder at a higher level than the outermost binder i.e. it is an escaping bound var. The `'^1` region (also writeable as `'^0_1`) is also ill formed as the binder it refers to does not introduce a second parameter. Modern day rustc will ICE when constructing this binder due to both of those regions, in the past we would have simply allowed this to work and then ran into issues in other parts of the codebase.
|
||||
This would cause all kinds of issues as the region `'^1_0` refers to a binder at a higher level than the outermost binder i.e. it is an escaping bound var. The `'^1` region (also writeable as `'^0_1`) is also ill formed as the binder it refers to does not introduce a second parameter. Modern day rustc will ICE when constructing this binder due to both of those reasons, in the past we would have simply allowed this to work and then ran into issues in other parts of the codebase.
|
||||
|
||||
[`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html
|
||||
[`BoundVar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.BoundVar.html
|
||||
|
|
|
|||
|
|
@ -105,7 +105,8 @@ the `RePlaceholder` for the `'b` parameter is in a higher universe to track the
|
|||
|
||||
## Instantiating with `ReLateParam`
|
||||
|
||||
As discussed in a previous chapter, `RegionKind` has two variants for representing generic parameters, `ReLateParam` and `ReEarlyParam`. `ReLateParam` is conceptually a `Placeholder` that is always in the root universe (`U0`). It is used when instantiating late bound parameters of functions/closures while inside of them. Its actual representation is relatively different from both `ReEarlyParam` and `RePlaceholder`:
|
||||
As discussed in [the chapter about representing types][representing-types], `RegionKind` has two variants for representing generic parameters, `ReLateParam` and `ReEarlyParam`.
|
||||
`ReLateParam` is conceptually a `Placeholder` that is always in the root universe (`U0`). It is used when instantiating late bound parameters of functions/closures while inside of them. Its actual representation is relatively different from both `ReEarlyParam` and `RePlaceholder`:
|
||||
- A `DefId` for the item that introduced the late bound generic parameter
|
||||
- A [`BoundRegionKind`] which either specifies the `DefId` of the generic parameter and its name (via a `Symbol`), or that this placeholder is representing the anonymous lifetime of a `Fn`/`FnMut` closure's self borrow. There is also a variant for `BrAnon` but this is not used for `ReLateParam`.
|
||||
|
||||
|
|
@ -133,6 +134,7 @@ Generally whenever we have a `Binder` for late bound parameters on a function/cl
|
|||
As a concrete example, accessing the signature of a function we are type checking will be represented as `EarlyBinder<Binder<FnSig>>`. As we are already "inside" of these binders, we would call `instantiate_identity` followed by `liberate_late_bound_regions`.
|
||||
|
||||
[`liberate_late_bound_regions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.liberate_late_bound_regions
|
||||
[representing-types]: param_ty_const_regions.md
|
||||
[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html
|
||||
[`enter_forall`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/struct.InferCtxt.html#method.enter_forall
|
||||
[ch_placeholders_universes]: ../borrow_check/region_inference/placeholders_and_universes.md
|
||||
|
|
|
|||
|
|
@ -11,15 +11,15 @@ TyKind::Ref(
|
|||
|
||||
There are three separate ways we represent usages of generic parameters:
|
||||
- [`TyKind::Param`]/[`ConstKind::Param`]/[`RegionKind::EarlyParam`] for early bound generic parameters (note: all type and const parameters are considered early bound, see the [chapter on early vs late bound parameters][ch_early_late_bound] for more information)
|
||||
- [`TyKind::Bound`]/[`ConstKind::Bound`]/[`RegionKind::Bound`] for references to parameters introduced via higher ranked bounds or higher ranked types i.e. `for<'a> fn(&'a u32)` or `for<'a> T: Trait<'a>`. This will be discussed in the [chapter on `Binder`s][ch_binders].
|
||||
- [`RegionKind::LateParam`] for late bound lifetime parameters, `LateParam` will be discussed in the [chapter on instantiating `Binder`s][ch_instantiating_binders].
|
||||
- [`TyKind::Bound`]/[`ConstKind::Bound`]/[`RegionKind::Bound`] for references to parameters introduced via higher ranked bounds or higher ranked types i.e. `for<'a> fn(&'a u32)` or `for<'a> T: Trait<'a>`. This is discussed in the [chapter on `Binder`s][ch_binders].
|
||||
- [`RegionKind::LateParam`] for late bound lifetime parameters, `LateParam` is discussed in the [chapter on instantiating `Binder`s][ch_instantiating_binders].
|
||||
|
||||
This chapter will only cover `TyKind::Param` `ConstKind::Param` and `RegionKind::EarlyParam`.
|
||||
This chapter only covers `TyKind::Param` `ConstKind::Param` and `RegionKind::EarlyParam`.
|
||||
|
||||
## Ty/Const Parameters
|
||||
|
||||
As `TyKind::Param` and `ConstKind::Param` are implemented identically this section will only refer to `TyKind::Param` for simplicity. However
|
||||
you should keep in mind that everything here also is true of `ConstKind::Param`
|
||||
As `TyKind::Param` and `ConstKind::Param` are implemented identically this section only refers to `TyKind::Param` for simplicity.
|
||||
However you should keep in mind that everything here also is true of `ConstKind::Param`
|
||||
|
||||
Each `TyKind::Param` contains two things: the name of the parameter and an index.
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ fn foo<'a, 'b, T: 'a>(one: T, two: &'a &'b u32) -> &'b u32 {
|
|||
}
|
||||
```
|
||||
|
||||
`RegionKind::LateParam` will be discussed more in the chapter on [instantiating binders][ch_instantiating_binders].
|
||||
`RegionKind::LateParam` is discussed more in the chapter on [instantiating binders][ch_instantiating_binders].
|
||||
|
||||
[ch_early_late_bound]: ../early_late_parameters.md
|
||||
[ch_binders]: ./binders.md
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ where
|
|||
<T as Trait>::Assoc: Clone,
|
||||
{}
|
||||
```
|
||||
If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as normalization (TODO: write a chapter about normalization and link it), evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc.
|
||||
If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as [normalization], evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc.
|
||||
|
||||
A more concrete example:
|
||||
```rust
|
||||
|
|
@ -70,6 +70,7 @@ fn foo2<T>(a: T) {
|
|||
[predicates_of]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/predicates_of/fn.predicates_of.html
|
||||
[method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html
|
||||
[query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env
|
||||
[normalization]: normalization.md
|
||||
|
||||
### Acquiring a `ParamEnv`
|
||||
|
||||
|
|
@ -199,8 +200,8 @@ In the next-gen trait solver the requirement for all where clauses in the `Param
|
|||
|
||||
Depending on what context we are performing type system operations in, different behaviour may be required. For example during coherence there are stronger requirements about when we can consider goals to not hold or when we can consider types to be unequal.
|
||||
|
||||
Tracking which "phase" of the compiler type system operations are being performed in is done by the [`TypingMode`][tenv] enum. The documentation on the `TypingMode` enum is quite good so instead of repeating it here verbatim we would recommend reading the API documentation directly.
|
||||
Tracking which "phase" of the compiler type system operations are being performed in is done by the [`TypingMode`][tmode] enum. The documentation on the `TypingMode` enum is quite good so instead of repeating it here verbatim we would recommend reading the API documentation directly.
|
||||
|
||||
[penv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html
|
||||
[tenv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/infer_ctxt/enum.TypingMode.html
|
||||
[tenv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypingEnv.html
|
||||
[tmode]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TypingMode.html
|
||||
|
|
|
|||
|
|
@ -1,18 +1,82 @@
|
|||
[assign]
|
||||
# This file's format is documented at
|
||||
# https://forge.rust-lang.org/triagebot/pr-assignment.html#configuration
|
||||
|
||||
[autolabel."needs-triage"]
|
||||
new_issue = true
|
||||
exclude_labels = [
|
||||
"A-diagnostics",
|
||||
"C-tracking-issue",
|
||||
]
|
||||
|
||||
[review-submitted]
|
||||
# This label is added when a "request changes" review is submitted.
|
||||
reviewed_label = "S-waiting-on-author"
|
||||
# These labels are removed when a "request changes" review is submitted.
|
||||
review_labels = ["S-waiting-on-review"]
|
||||
|
||||
[review-requested]
|
||||
# Those labels are removed when PR author requests a review from an assignee
|
||||
remove_labels = ["S-waiting-on-author"]
|
||||
# Those labels are added when PR author requests a review from an assignee
|
||||
add_labels = ["S-waiting-on-review"]
|
||||
|
||||
# Enable shortcuts like `@rustbot ready`
|
||||
# Documentation at: https://forge.rust-lang.org/triagebot/shortcuts.html
|
||||
[shortcut]
|
||||
|
||||
[autolabel."S-waiting-on-review"]
|
||||
new_pr = true
|
||||
|
||||
# Enable issue transfers within the org
|
||||
# Documentation at: https://forge.rust-lang.org/triagebot/transfer.html
|
||||
[transfer]
|
||||
|
||||
[relabel]
|
||||
allow-unauthenticated = [
|
||||
"waiting-on-review",
|
||||
"waiting-on-author",
|
||||
"blocked",
|
||||
"-Z*",
|
||||
"A-*",
|
||||
"C-*",
|
||||
"D-*",
|
||||
"E-*",
|
||||
"F-*",
|
||||
"I-*",
|
||||
"L-*",
|
||||
"O-*",
|
||||
"PG-*",
|
||||
"S-*",
|
||||
"T-*",
|
||||
"WG-*",
|
||||
"needs-triage",
|
||||
]
|
||||
|
||||
# Enable `@rustbot note` functionality
|
||||
# Documentation at: https://forge.rust-lang.org/triagebot/note.html
|
||||
[note]
|
||||
|
||||
# Prevents mentions in commits to avoid users being spammed
|
||||
# Documentation at: https://forge.rust-lang.org/triagebot/no-mentions.html
|
||||
[no-mentions]
|
||||
|
||||
[canonicalize-issue-links]
|
||||
# Canonicalize issue numbers to avoid closing the wrong issue
|
||||
# when commits are included in subtrees, as well as warning links in commits.
|
||||
# Documentation at: https://forge.rust-lang.org/triagebot/issue-links.html
|
||||
[issue-links]
|
||||
|
||||
# Automatically close and reopen PRs made by bots to run CI on them
|
||||
[bot-pull-requests]
|
||||
|
||||
[behind-upstream]
|
||||
days-threshold = 7
|
||||
days-threshold = 7
|
||||
|
||||
# Enable triagebot (PR) assignment.
|
||||
# Documentation at: https://forge.rust-lang.org/triagebot/pr-assignment.html
|
||||
[assign]
|
||||
|
||||
# Keep members alphanumerically sorted.
|
||||
[assign.adhoc_groups]
|
||||
rustc-dev-guide = [
|
||||
"@BoxyUwU",
|
||||
"@jieyouxu",
|
||||
"@jyn514",
|
||||
"@tshepang",
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in New Issue