diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:24 +0000 |
commit | 023939b627b7dc93b01471f7d41fb8553ddb4ffa (patch) | |
tree | 60fc59477c605c72b0a1051409062ddecc43f877 /src/doc/rustc-dev-guide | |
parent | Adding debian version 1.72.1+dfsg1-1. (diff) | |
download | rustc-023939b627b7dc93b01471f7d41fb8553ddb4ffa.tar.xz rustc-023939b627b7dc93b01471f7d41fb8553ddb4ffa.zip |
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/doc/rustc-dev-guide')
68 files changed, 1324 insertions, 549 deletions
diff --git a/src/doc/rustc-dev-guide/README.md b/src/doc/rustc-dev-guide/README.md index fdf6c5050..131651e38 100644 --- a/src/doc/rustc-dev-guide/README.md +++ b/src/doc/rustc-dev-guide/README.md @@ -118,7 +118,7 @@ git submodule update --remote src/doc/rustc-dev-guide git add -u git commit -m "Update rustc-dev-guide" # Note that you can use -i, which is short for --incremental, in the following command -./x.py test --incremental src/doc/rustc-dev-guide # This is optional and should succeed anyway +./x test --incremental src/doc/rustc-dev-guide # This is optional and should succeed anyway # Open a PR in rust-lang/rust ``` diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 9f7c9cf1b..97f3503ae 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -40,12 +40,12 @@ - [Using Git](./git.md) - [Mastering @rustbot](./rustbot.md) - [Walkthrough: a typical contribution](./walkthrough.md) -- [Procedures for Breaking Changes](./bug-fix-procedure.md) -- [Implementing new features](./implementing_new_features.md) +- [Implementing new language features](./implementing_new_features.md) - [Stability attributes](./stability.md) - [Stabilizing Features](./stabilization_guide.md) - [Feature Gates](./feature-gates.md) - [Coding conventions](./conventions.md) +- [Procedures for Breaking Changes](./bug-fix-procedure.md) - [Using external repositories](./external-repos.md) - [Fuzzing](./fuzzing.md) - [Notification groups](notification-groups/about.md) @@ -109,9 +109,10 @@ - [`TypeFolder` and `TypeFoldable`](./ty-fold.md) - [Generic arguments](./generic_arguments.md) - [Constants in the type system](./constants.md) + - [Bound vars and Parameters](./bound-vars-and-params.md) - [Type inference](./type-inference.md) - [Trait solving](./traits/resolution.md) - - [Early and Late Bound Parameters](./early-late-bound.md) + - [Early and Late Bound Parameter Definitions](./early-late-bound.md) - [Higher-ranked trait bounds](./traits/hrtb.md) - [Caching subtleties](./traits/caching.md) - [Specialization](./traits/specialization.md) @@ -124,11 +125,13 @@ - [Canonicalization](./solve/canonicalization.md) - [Coinduction](./solve/coinduction.md) - [Proof trees](./solve/proof-trees.md) + - [Normalization](./solve/normalization.md) - [Type checking](./type-checking.md) - [Method Lookup](./method-lookup.md) - [Variance](./variance.md) - [Opaque Types](./opaque-types-type-alias-impl-trait.md) - [Inference details](./opaque-types-impl-trait-inference.md) + - [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md) - [Pattern and Exhaustiveness Checking](./pat-exhaustive-checking.md) - [MIR dataflow](./mir/dataflow.md) - [Drop elaboration](./mir/drop-elaboration.md) diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md index 944ebf5a8..f43f86e5f 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -66,7 +66,6 @@ You might also find the following sites useful: of the team procedures, active working groups, and the team calendar. - [std-dev-guide] -- a similar guide for developing the standard library. - [The t-compiler zulip][z] -- [The Forge](https://forge.rust-lang.org/) has more documentation about various procedures. - `#contribute` and `#wg-rustup` on [Discord](https://discord.gg/rust-lang). - The [Rust Internals forum][rif], a place to ask questions and discuss Rust's internals diff --git a/src/doc/rustc-dev-guide/src/appendix/background.md b/src/doc/rustc-dev-guide/src/appendix/background.md index 0b83b010f..05d01be0f 100644 --- a/src/doc/rustc-dev-guide/src/appendix/background.md +++ b/src/doc/rustc-dev-guide/src/appendix/background.md @@ -300,7 +300,7 @@ does not. > Thanks to `mem`, `scottmcm`, and `Levi` on the official Discord for the > recommendations, and to `tinaun` for posting a link to a [twitter thread from -> Graydon Hoare](https://twitter.com/graydon_pub/status/1039615569132118016) +> Graydon Hoare](https://web.archive.org/web/20181230012554/https://twitter.com/graydon_pub/status/1039615569132118016) > which had some more recommendations! > > Other sources: https://gcc.gnu.org/wiki/ListOfCompilerBooks diff --git a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md index a02011149..08af10f89 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -90,16 +90,16 @@ so let's go through each in detail. `src/llvm-project` to ensure submodule updates aren't reverted. Some commands you should execute are: - * `./x.py build src/llvm` - test that LLVM still builds - * `./x.py build src/tools/lld` - same for LLD - * `./x.py build` - build the rest of rustc + * `./x build src/llvm` - test that LLVM still builds + * `./x build src/tools/lld` - same for LLD + * `./x build` - build the rest of rustc You'll likely need to update [`llvm-wrapper/*.cpp`][`llvm-wrapper`] to compile with updated LLVM bindings. Note that you should use `#ifdef` and such to ensure that the bindings still compile on older LLVM versions. - Note that `profile = "compiler"` and other defaults set by `./x.py setup` + Note that `profile = "compiler"` and other defaults set by `./x setup` download LLVM from CI instead of building it from source. You should disable this temporarily to make sure your changes are being used. This is done by having the following setting in `config.toml`: diff --git a/src/doc/rustc-dev-guide/src/bound-vars-and-params.md b/src/doc/rustc-dev-guide/src/bound-vars-and-params.md new file mode 100644 index 000000000..50d5cefb1 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/bound-vars-and-params.md @@ -0,0 +1,59 @@ +# Bound vars and parameters + +## Early-bound parameters + +Early-bound parameters in rustc are identified by an index, stored in the +[`ParamTy`] struct for types or the [`EarlyBoundRegion`] struct for lifetimes. +The index counts from the outermost declaration in scope. This means that as you +add more binders inside, the index doesn't change. + +For example, + +```rust,ignore +trait Foo<T> { + type Bar<U> = (Self, T, U); +} +``` + +Here, the type `(Self, T, U)` would be `($0, $1, $2)`, where `$N` means a +[`ParamTy`] with the index of `N`. + +In rustc, the [`Generics`] structure carries this information. So the +[`Generics`] for `Bar` above would be just like for `U` and would indicate the +'parent' generics of `Foo`, which declares `Self` and `T`. You can read more +in [this chapter](./generics.md). + +[`ParamTy`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamTy.html +[`EarlyBoundRegion`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.EarlyBoundRegion.html +[`Generics`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html + +## Late-bound parameters + +Late-bound parameters in `rustc` are handled differently. We indicate their +presence by a [`Binder`] type. The [`Binder`] doesn't know how many variables +there are at that binding level. This can only be determined by walking the +type itself and collecting them. So a type like `for<'a, 'b> ('a, 'b)` would be +`for (^0.a, ^0.b)`. Here, we just write `for` because we don't know the names +of the things bound within. + +Moreover, a reference to a late-bound lifetime is written `^0.a`: + +- The `0` is the index; it identifies that this lifetime is bound in the + innermost binder (the `for`). +- The `a` is the "name"; late-bound lifetimes in rustc are identified by a + "name" -- the [`BoundRegionKind`] enum. This enum can contain a + [`DefId`][defid] or it might have various "anonymous" numbered names. The + latter arise from types like `fn(&u32, &u32)`, which are equivalent to + something like `for<'a, 'b> fn(&'a u32, &'b u32)`, but the names of those + lifetimes must be generated. + +This setup of not knowing the full set of variables at a binding level has some +advantages and some disadvantages. The disadvantage is that you must walk the +type to find out what is bound at the given level and so forth. The advantage +is primarily that, when constructing types from Rust syntax, if we encounter +anonymous regions like in `fn(&u32)`, we just create a fresh index and don't have +to update the binder. + +[`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html +[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html +[defid]: ./hir.html#identifiers-in-the-hir diff --git a/src/doc/rustc-dev-guide/src/bug-fix-procedure.md b/src/doc/rustc-dev-guide/src/bug-fix-procedure.md index e69ce48f9..388e39b93 100644 --- a/src/doc/rustc-dev-guide/src/bug-fix-procedure.md +++ b/src/doc/rustc-dev-guide/src/bug-fix-procedure.md @@ -304,7 +304,7 @@ self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS, We want to convert this into an error. In some cases, there may be an existing error for this scenario. In others, we will need to allocate a fresh diagnostic code. [Instructions for allocating a fresh diagnostic -code can be found here.](./diagnostics/diagnostic-codes.md) You may want +code can be found here.](./diagnostics/error-codes.md) You may want to mention in the extended description that the compiler behavior changed on this point, and include a reference to the tracking issue for the change. @@ -325,7 +325,7 @@ general, if the test used to have `#[deny(overlapping_inherent_impls)]`, that can just be removed. ``` -./x.py test +./x test ``` #### All done! diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping.md b/src/doc/rustc-dev-guide/src/building/bootstrapping.md index d53896f81..936c75f36 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping.md @@ -96,7 +96,7 @@ 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.py build library`. +which you can build with `./x build library`. See [Building the compiler](./how-to-build-and-run.html#building-the-compiler). ### Stage 3: the same-result test @@ -107,7 +107,7 @@ to be identical to before, unless something has broken. ### Building the stages -`x.py` tries to be helpful and pick the stage you most likely meant for each subcommand. +`x` tries to be helpful and pick the stage you most likely meant for each subcommand. These defaults are as follows: - `check`: `--stage 0` @@ -152,7 +152,7 @@ bootstrapping the compiler. This is a detailed look into the separate bootstrap stages. -The convention `x.py` uses is that: +The convention `x` uses is that: - A `--stage N` flag means to run the stage N compiler (`stageN/rustc`). - A "stage N artifact" is a build artifact that is _produced_ by the stage N compiler. @@ -161,7 +161,7 @@ The convention `x.py` uses is that: #### Build artifacts -Anything you can build with `x.py` is a _build artifact_. +Anything you can build with `x` is a _build artifact_. Build artifacts include, but are not limited to: - binaries, like `stage0-rustc/rustc-main` @@ -173,27 +173,27 @@ Build artifacts include, but are not limited to: #### Examples -- `./x.py build --stage 0` means to build with the beta `rustc`. -- `./x.py doc --stage 0` means to document using the beta `rustdoc`. -- `./x.py test --stage 0 library/std` means to run tests on the standard library - without building `rustc` from source ('build with stage 0, then test the +- `./x build --stage 0` means to build with the beta `rustc`. +- `./x doc --stage 0` means to document using the beta `rustdoc`. +- `./x test --stage 0 library/std` means to run tests on the standard library + without building `rustc` from source ('build with stage 0, then test the artifacts'). If you're working on the standard library, this is normally the test command you want. -- `./x.py test tests/ui` means to build the stage 1 compiler and run +- `./x test tests/ui` means to build the stage 1 compiler and run `compiletest` on it. If you're working on the compiler, this is normally the test command you want. #### Examples of what *not* to do -- `./x.py test --stage 0 tests/ui` is not useful: it runs tests on the +- `./x test --stage 0 tests/ui` is not useful: it runs tests on the _beta_ compiler and doesn't build `rustc` from source. Use `test tests/ui` instead, which builds stage 1 from source. -- `./x.py test --stage 0 compiler/rustc` builds the compiler but runs no tests: +- `./x test --stage 0 compiler/rustc` builds the compiler but runs no tests: it's running `cargo test -p rustc`, but cargo doesn't understand Rust's tests. You shouldn't need to use this, use `test` instead (without arguments). -- `./x.py build --stage 0 compiler/rustc` builds the compiler, but does not build - libstd or even libcore. Most of the time, you'll want `./x.py build - library` instead, which allows compiling programs without needing to define +- `./x build --stage 0 compiler/rustc` builds the compiler, but does not build + libstd or even libcore. Most of the time, you'll want `./x build +library` instead, which allows compiling programs without needing to define lang items. ### Building vs. running @@ -243,7 +243,7 @@ artifacts into the appropriate place, skipping the cargo invocation. For instance, you might want to build an ARM version of rustc using an x86 machine. Building stage2 `std` is different when you are cross-compiling. -This is because `x.py` uses a trick: if `HOST` and `TARGET` are the same, +This is because `x` uses a trick: if `HOST` and `TARGET` are the same, it will reuse stage1 `std` for stage2! This is sound because stage1 `std` was compiled with the stage1 compiler, i.e. a compiler using the source code you currently have checked out. So it should be identical (and therefore ABI-compatible) @@ -362,7 +362,7 @@ You can find more discussion about sysroots in: ## Passing flags to commands invoked by `bootstrap` -`x.py` allows you to pass stage-specific flags to `rustc` and `cargo` when bootstrapping. +`x` allows you to pass stage-specific flags to `rustc` and `cargo` when bootstrapping. The `RUSTFLAGS_BOOTSTRAP` environment variable is passed as `RUSTFLAGS` to the bootstrap stage (stage0), and `RUSTFLAGS_NOT_BOOTSTRAP` is passed when building artifacts for later stages. `RUSTFLAGS` will work, but also affects the build of `bootstrap` itself, so it will be rare to want @@ -395,7 +395,7 @@ If `./stageN/bin/rustc` gives an error about environment variables, that usually means something is quite wrong -- or you're trying to compile e.g. `rustc` or `std` or something that depends on environment variables. In the unlikely case that you actually need to invoke rustc in such a situation, -you can tell the bootstrap shim to print all env variables by adding `-vvv` to your `x.py` command. +you can tell the bootstrap shim to print all env variables by adding `-vvv` to your `x` command. Finally, bootstrap makes use of the [cc-rs crate] which has [its own method][env-vars] of configuring C compilers and C flags via environment @@ -408,7 +408,7 @@ variables. In this part, we will investigate the build command's stdout in an action (similar, but more detailed and complete documentation compare to topic above). -When you execute `x.py build --dry-run` command, the build output will be something +When you execute `x build --dry-run` command, the build output will be something like the following: ```text diff --git a/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md b/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md index 4ec3f958a..df3037469 100644 --- a/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md +++ b/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md @@ -3,22 +3,22 @@ You might want to build and package up the compiler for distribution. You’ll want to run this command to do it: - ```bash - ./x.py dist - ``` +```bash +./x dist +``` # Install distribution artifacts If you’ve built a distribution artifact you might want to install it and test that it works on your target system. You’ll want to run this command: - ```bash - ./x.py install - ``` +```bash +./x install +``` Note: If you are testing out a modification to a compiler, you might want to use it to compile some project. - Usually, you do not want to use `./x.py install` for testing. + Usually, you do not want to use `./x install` for testing. Rather, you should create a toolchain as discussed in [here][create-rustup-toolchain]. diff --git a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md index 4e72bf994..948571ce8 100644 --- a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md +++ b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md @@ -10,13 +10,13 @@ like the standard library (std) or the compiler (rustc). as rustdoc is under active development: ```bash - ./x.py doc + ./x doc ``` If you want to be sure the documentation looks the same as on CI: ```bash - ./x.py doc --stage 1 + ./x doc --stage 1 ``` This ensures that (current) rustdoc gets built, @@ -26,9 +26,9 @@ like the standard library (std) or the compiler (rustc). you can build just the documentation you want: ```bash - ./x.py doc src/doc/book - ./x.py doc src/doc/nomicon - ./x.py doc compiler library + ./x doc src/doc/book + ./x doc src/doc/nomicon + ./x doc compiler library ``` See [the nightly docs index page](https://doc.rust-lang.org/nightly/) for a full list of books. @@ -36,7 +36,7 @@ like the standard library (std) or the compiler (rustc). - Document internal rustc items Compiler documentation is not built by default. - To create it by default with `x.py doc`, modify `config.toml`: + To create it by default with `x doc`, modify `config.toml`: ```toml [build] diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 6444aab5f..0865f1955 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -5,9 +5,6 @@ The compiler is built using a tool called `x.py`. You will need to have Python installed to run it. -For instructions on how to install Python and other prerequisites, -see [the `rust-lang/rust` README][readme]. - ## Get the source code The main repository is [`rust-lang/rust`][repo]. This contains the compiler, @@ -15,7 +12,6 @@ the standard library (including `core`, `alloc`, `test`, `proc_macro`, etc), and a bunch of tools (e.g. `rustdoc`, the bootstrapping infrastructure, etc). [repo]: https://github.com/rust-lang/rust -[readme]: https://github.com/rust-lang/rust#building-on-a-unix-like-system The very first step to work on `rustc` is to clone the repository: @@ -57,7 +53,75 @@ if you want to learn more about `x.py`, [read this chapter][bootstrap]. [bootstrap]: ./bootstrapping.md -### Running `x.py` slightly more conveniently +Also, using `x` rather than `x.py` is recommended as: + +> `./x` is the most likely to work on every system (on Unix it runs the shell script +> that does python version detection, on Windows it will probably run the +> powershell script - certainly less likely to break than `./x.py` which often just +> opens the file in an editor).[^1] + +(You can find the platform related scripts around the `x.py`, like `x.ps1`) + +Notice that this is not absolute, for instance, using Nushell in VSCode on Win10, +typing `x` or `./x` still open the `x.py` in editor rather invoke the program :) + +In the rest of documents, we use `x` to represent the straightly usage of `x.py`, which +means the following command: + +```bash +./x check +``` + +could be replaced by: + +```bash +./x.py check +``` + +### Running `x.py` + +The `x.py` command can be run directly on most Unix systems in the following format: + +```sh +./x <subcommand> [flags] +``` + +This is how the documentation and examples assume you are running `x.py`. +Some alternative ways are: + +```sh +# On a Unix shell if you don't have the necessary `python3` command +./x <subcommand> [flags] + +# In Windows Powershell (if powershell is configured to run scripts) +./x <subcommand> [flags] +./x.ps1 <subcommand> [flags] + +# On the Windows Command Prompt (if .py files are configured to run Python) +x.py <subcommand> [flags] + +# You can also run Python yourself, e.g.: +python x.py <subcommand> [flags] +``` + +On Windows, the Powershell commands may give you an error that looks like this: +``` +PS C:\Users\vboxuser\rust> ./x +./x : File C:\Users\vboxuser\rust\x.ps1 cannot be loaded because running scripts is disabled on this system. For more +information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170. +At line:1 char:1 ++ ./x ++ ~~~ + + CategoryInfo : SecurityError: (:) [], PSSecurityException + + FullyQualifiedErrorId : UnauthorizedAccess +``` + +You can avoid this error by allowing powershell to run local scripts: +``` +Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser +``` + +#### Running `x.py` slightly more conveniently There is a binary that wraps `x.py` called `x` in `src/tools/x`. All it does is run `x.py`, but it can be installed system-wide and run from any subdirectory @@ -65,9 +129,14 @@ of a checkout. It also looks up the appropriate version of `python` to use. You can install it with `cargo install --path src/tools/x`. +To clarify that this is another global installed binary util, which is +similar to the one declared in section [What is `x.py`](#what-is-xpy), but +it works as an independent process to execute the `x.py` rather than calling the +shell to run the platform related scripts. + ## Create a `config.toml` -To start, run `./x.py setup` and select the `compiler` defaults. This will do some initialization +To start, run `./x setup` and select the `compiler` defaults. This will do some initialization and create a `config.toml` for you with reasonable defaults. If you use a different default (which you'll likely want to do if you want to contribute to an area of rust other than the compiler, such as rustdoc), make sure to read information about that default (located in `src/bootstrap/defaults`) @@ -77,35 +146,35 @@ Alternatively, you can write `config.toml` by hand. See `config.example.toml` fo settings and explanations of them. See `src/bootstrap/defaults` for common settings to change. If you have already built `rustc` and you change settings related to LLVM, then you may have to -execute `rm -rf build` for subsequent configuration changes to take effect. Note that `./x.py +execute `rm -rf build` for subsequent configuration changes to take effect. Note that `./x clean` will not cause a rebuild of LLVM. -## Common `x.py` commands +## Common `x` commands -Here are the basic invocations of the `x.py` commands most commonly used when +Here are the basic invocations of the `x` commands most commonly used when working on `rustc`, `std`, `rustdoc`, and other tools. -| Command | When to use it | -| --- | --- | -| `./x.py check` | Quick check to see if most things compile; [rust-analyzer can run this automatically for you][rust-analyzer] | -| `./x.py build` | Builds `rustc`, `std`, and `rustdoc` | -| `./x.py test` | Runs all tests | -| `./x.py fmt` | Formats all code | +| Command | When to use it | +| ----------- | ------------------------------------------------------------------------------------------------------------ | +| `./x check` | Quick check to see if most things compile; [rust-analyzer can run this automatically for you][rust-analyzer] | +| `./x build` | Builds `rustc`, `std`, and `rustdoc` | +| `./x test` | Runs all tests | +| `./x fmt` | Formats all code | As written, these commands are reasonable starting points. However, there are additional options and arguments for each of them that are worth learning for -serious development work. In particular, `./x.py build` and `./x.py test` +serious development work. In particular, `./x build` and `./x test` provide many ways to compile or test a subset of the code, which can save a lot of time. -Also, note that `x.py` supports all kinds of path suffixes for `compiler`, `library`, -and `src/tools` directories. So, you can simply run `x.py test tidy` instead of -`x.py test src/tools/tidy`. Or, `x.py build std` instead of `x.py build library/std`. +Also, note that `x` supports all kinds of path suffixes for `compiler`, `library`, +and `src/tools` directories. So, you can simply run `x test tidy` instead of +`x test src/tools/tidy`. Or, `x build std` instead of `x build library/std`. [rust-analyzer]: suggested.html#configuring-rust-analyzer-for-rustc -See the chapters on [building](how-to-build-and-run), -[testing](../tests/intro), and [rustdoc](../rustdoc) for more details. +See the chapters on +[testing](../tests/running.md) and [rustdoc](../rustdoc.md) for more details. ### Building the compiler @@ -113,11 +182,11 @@ Note that building will require a relatively large amount of storage space. You may want to have upwards of 10 or 15 gigabytes available to build the compiler. Once you've created a `config.toml`, you are now ready to run -`x.py`. There are a lot of options here, but let's start with what is +`x`. There are a lot of options here, but let's start with what is probably the best "go to" command for building a local compiler: ```bash -./x.py build library +./x build library ``` This may *look* like it only builds the standard library, but that is not the case. @@ -140,10 +209,10 @@ see [the section on avoiding rebuilds for std][keep-stage]. Sometimes you don't need a full build. When doing some kind of "type-based refactoring", like renaming a method, or changing the -signature of some function, you can use `./x.py check` instead for a much faster build. +signature of some function, you can use `./x check` instead for a much faster build. Note that this whole command just gives you a subset of the full `rustc` -build. The **full** `rustc` build (what you get with `./x.py build +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. @@ -160,10 +229,10 @@ the compiler unless you are planning to use a recently added nightly feature. Instead, you can just build using the bootstrap compiler. ```bash -./x.py build --stage 0 library +./x build --stage 0 library ``` -If you choose the `library` profile when running `x.py setup`, you can omit `--stage 0` (it's the +If you choose the `library` profile when running `x setup`, you can omit `--stage 0` (it's the default). ## Creating a rustup toolchain @@ -198,7 +267,7 @@ LLVM version: 11.0 ``` The rustup toolchain points to the specified toolchain compiled in your `build` directory, -so the rustup toolchain will be updated whenever `x.py build` or `x.py test` are run for +so the rustup toolchain will be updated whenever `x build` or `x test` are run for that toolchain/stage. **Note:** the toolchain we've built does not include `cargo`. In this case, `rustup` will @@ -213,25 +282,25 @@ custom toolchain for a project (e.g. via `rustup override set stage1`) you may want to build this component: ```bash -./x.py build proc-macro-srv-cli +./x build proc-macro-srv-cli ``` ## Building targets for cross-compilation To produce a compiler that can cross-compile for other targets, -pass any number of `target` flags to `x.py build`. +pass any number of `target` flags to `x build`. For example, if your host platform is `x86_64-unknown-linux-gnu` and your cross-compilation target is `wasm32-wasi`, you can build with: ```bash -./x.py build --target x86_64-unknown-linux-gnu --target wasm32-wasi +./x build --target x86_64-unknown-linux-gnu --target wasm32-wasi ``` Note that if you want the resulting compiler to be able to build crates that involve proc macros or build scripts, you must be sure to explicitly build target support for the host platform (in this case, `x86_64-unknown-linux-gnu`). -If you want to always build for other targets without needing to pass flags to `x.py build`, +If you want to always build for other targets without needing to pass flags to `x build`, you can configure this in the `[build]` section of your `config.toml` like so: ```toml @@ -260,24 +329,24 @@ then once you have built your compiler you will be able to use it to cross-compi cargo +stage1 build --target wasm32-wasi ``` -## Other `x.py` commands +## Other `x` commands -Here are a few other useful `x.py` commands. We'll cover some of them in detail +Here are a few other useful `x` commands. We'll cover some of them in detail in other sections: - Building things: - - `./x.py build` – builds everything using the stage 1 compiler, + - `./x build` – builds everything using the stage 1 compiler, not just up to `std` - - `./x.py build --stage 2` – builds everything with the stage 2 compiler including + - `./x build --stage 2` – builds everything with the stage 2 compiler including `rustdoc` - Running tests (see the [section on running tests](../tests/running.html) for more details): - - `./x.py test library/std` – runs the unit tests and integration tests from `std` - - `./x.py test tests/ui` – runs the `ui` test suite - - `./x.py test tests/ui/const-generics` - runs all the tests in - the `const-generics/` subdirectory of the `ui` test suite - - `./x.py test tests/ui/const-generics/const-types.rs` - runs - the single test `const-types.rs` from the `ui` test suite + - `./x test library/std` – runs the unit tests and integration tests from `std` + - `./x test tests/ui` – runs the `ui` test suite + - `./x test tests/ui/const-generics` - runs all the tests in + the `const-generics/` subdirectory of the `ui` test suite + - `./x test tests/ui/const-generics/const-types.rs` - runs + the single test `const-types.rs` from the `ui` test suite ### Cleaning out build directories @@ -287,8 +356,10 @@ you should file a bug as to what is going wrong. If you do need to clean everything up then you only need to run one command! ```bash -./x.py clean +./x clean ``` `rm -rf build` works too, but then you have to rebuild LLVM, which can take a long time even on fast computers. + +[^1]: issue[#1707](https://github.com/rust-lang/rustc-dev-guide/issues/1707) diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md index 629445be6..83973f2c9 100644 --- a/src/doc/rustc-dev-guide/src/building/new-target.md +++ b/src/doc/rustc-dev-guide/src/building/new-target.md @@ -10,7 +10,7 @@ relevant to your desired goal. For very new targets, you may need to use a different fork of LLVM than what is currently shipped with Rust. In that case, navigate to -the `src/llvm-project` git submodule (you might need to run `./x.py +the `src/llvm-project` git submodule (you might need to run `./x check` at least once so the submodule is updated), check out the appropriate commit for your fork, then commit that new submodule reference in the main Rust repository. @@ -135,7 +135,7 @@ cross-compile `rustc`: ``` DESTDIR=/path/to/install/in \ -./x.py install -i --stage 1 --host aarch64-apple-darwin.json --target aarch64-apple-darwin \ +./x install -i --stage 1 --host aarch64-apple-darwin.json --target aarch64-apple-darwin \ compiler/rustc library/std ``` diff --git a/src/doc/rustc-dev-guide/src/building/prerequisites.md b/src/doc/rustc-dev-guide/src/building/prerequisites.md index 3dc2ea934..c511c7c81 100644 --- a/src/doc/rustc-dev-guide/src/building/prerequisites.md +++ b/src/doc/rustc-dev-guide/src/building/prerequisites.md @@ -20,7 +20,7 @@ recommend trying to build on a Raspberry Pi! We recommend the following. * 2+ cores. Having more cores really helps. 10 or 20 or more is not too many! Beefier machines will lead to much faster builds. If your machine is not very -powerful, a common strategy is to only use `./x.py check` on your local machine +powerful, a common strategy is to only use `./x check` on your local machine and let the CI build test your changes when you push to a PR branch. Building the compiler takes more than half an hour on my moderately powerful diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 9dcc795f2..0da3f60cf 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -10,14 +10,14 @@ to make your life easier. CI will automatically fail your build if it doesn't pass `tidy`, our internal tool for ensuring code quality. If you'd like, you can install a [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) -that will automatically run `./x.py test tidy` on each push, to ensure -your code is up to par. If the hook fails then run `./x.py test tidy --bless` +that will automatically run `./x test tidy` on each push, to ensure +your code is up to par. If the hook fails then run `./x test tidy --bless` and commit the changes. If you decide later that the pre-push behavior is undesirable, you can delete the `pre-push` file in `.git/hooks`. A prebuilt git hook lives at [`src/etc/pre-push.sh`](https://github.com/rust-lang/rust/blob/master/src/etc/pre-push.sh) which can be copied into your `.git/hooks` folder as `pre-push` (without the `.sh` extension!). -You can also install the hook as a step of running `./x.py setup`! +You can also install the hook as a step of running `./x setup`! ## Configuring `rust-analyzer` for `rustc` @@ -26,22 +26,19 @@ You can also install the hook as a step of running `./x.py setup`! `rust-analyzer` can help you check and format your code whenever you save a file. By default, `rust-analyzer` runs the `cargo check` and `rustfmt` commands, but you can override these commands to use more adapted versions -of these tools when hacking on `rustc`. For example, `x.py setup vscode` will prompt +of these tools when hacking on `rustc`. For example, `x setup vscode` will prompt you to create a `.vscode/settings.json` file which will configure Visual Studio code. -This will ask `rust-analyzer` to use `./x.py check` to check the sources, and the +This will ask `rust-analyzer` to use `./x check` to check the sources, and the stage 0 rustfmt to format them. The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_settings.json`]. -If you have enough free disk space and you would like to be able to run `x.py` commands while +If you have enough free disk space and you would like to be able to run `x` commands while rust-analyzer runs in the background, you can also add `--build-dir build-rust-analyzer` to the -`overrideCommand` to avoid x.py locking. - -If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a -`.vim/coc-settings.json` and copy the settings from [`src/etc/rust_analyzer_settings.json`]. +`overrideCommand` to avoid x locking. [`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json -If running `./x.py check` on save is inconvenient, in VS Code you can use a [Build +If running `./x check` on save is inconvenient, in VS Code you can use a [Build Task] instead: ```JSON @@ -50,8 +47,8 @@ Task] instead: "version": "2.0.0", "tasks": [ { - "label": "./x.py check", - "command": "./x.py check", + "label": "./x check", + "command": "./x check", "type": "shell", "problemMatcher": "$rustc", "presentation": { "clear": true }, @@ -73,13 +70,13 @@ Rust-Analyzer to already be configured with Neovim. Steps for this can be [found here](https://rust-analyzer.github.io/manual.html#nvim-lsp). 1. First install the plugin. This can be done by following the steps in the README. -2. Run `x.py setup`, which will have a prompt for it to create a `.vscode/settings.json` file. -`neoconf` is able to read and update Rust-Analyzer settings automatically when the project is -opened when this file is detected. +2. Run `x setup`, which will have a prompt for it to create a `.vscode/settings.json` file. + `neoconf` is able to read and update Rust-Analyzer settings automatically when the project is + opened when this file is detected. If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a `.vim/coc-settings.json` and copy the settings from -[this file](https://github.com/rust-lang/rust/blob/master/src/etc/vscode_settings.json). +[this file](https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json). Another way is without a plugin, and creating your own logic in your configuration. To do this you must translate the JSON to Lua yourself. The translation is 1:1 and fairly straight-forward. It @@ -94,11 +91,11 @@ follow the same instructions as above. ## Check, check, and check again -When doing simple refactorings, it can be useful to run `./x.py check` +When doing simple refactorings, it can be useful to run `./x check` continuously. If you set up `rust-analyzer` as described above, this will be done for you every time you save a file. Here you are just checking that the compiler can **build**, but often that is all you need (e.g., when renaming a -method). You can then run `./x.py build` when you actually need to +method). You can then run `./x build` when you actually need to run tests. In fact, it is sometimes useful to put off tests even when you are not @@ -141,11 +138,11 @@ directories you have [setup a worktree for]. You may need to use the pinned nightly version from `src/stage0.json`, but often the normal `nightly` channel will work. -**Note** see [the section on vscode] for how to configure it with this real rustfmt `x.py` uses, +**Note** see [the section on vscode] for how to configure it with this real rustfmt `x` uses, and [the section on rustup] for how to setup `rustup` toolchain for your bootstrapped compiler **Note** This does _not_ allow you to build `rustc` with cargo directly. You -still have to use `x.py` to work on the compiler or standard library, this just +still have to use `x` to work on the compiler or standard library, this just lets you use `cargo fmt`. [installing a nightly toolchain]: https://rust-lang.github.io/rustup/concepts/channels.html?highlight=nightl#working-with-nightly-rust @@ -166,13 +163,13 @@ don't work (but that is easily detected and fixed). The sequence of commands you want is as follows: -- Initial build: `./x.py build library` +- 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.py build library --keep-stage 1` +- 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 @@ -194,8 +191,8 @@ rebuild. That ought to fix the problem. You can also use `--keep-stage 1` when running tests. Something like this: -- Initial test run: `./x.py test tests/ui` -- Subsequent test run: `./x.py test tests/ui --keep-stage 1` +- Initial test run: `./x test tests/ui` +- Subsequent test run: `./x test tests/ui --keep-stage 1` ## Using incremental compilation @@ -203,7 +200,7 @@ You can further enable the `--incremental` flag to save additional time in subsequent rebuilds: ```bash -./x.py test tests/ui --incremental --test-args issue-1234 +./x test tests/ui --incremental --test-args issue-1234 ``` If you don't want to include the flag with every command, you can @@ -348,4 +345,4 @@ Zsh support will also be included once issues with [`clap_complete`](https://cra You can use `source ./src/etc/completions/x.py.<extension>` to load completions for your shell of choice, or `source .\src\etc\completions\x.py.ps1` for PowerShell. -Adding this to your shell's startup script (e.g. `.bashrc`) will automatically load this completion.
\ No newline at end of file +Adding this to your shell's startup script (e.g. `.bashrc`) will automatically load this completion. diff --git a/src/doc/rustc-dev-guide/src/closure.md b/src/doc/rustc-dev-guide/src/closure.md index e356f415d..786c831ee 100644 --- a/src/doc/rustc-dev-guide/src/closure.md +++ b/src/doc/rustc-dev-guide/src/closure.md @@ -115,10 +115,10 @@ Let's start with defining a term that we will be using quite a bit in the rest o *upvar*. An **upvar** is a variable that is local to the function where the closure is defined. So, in the above examples, **x** will be an upvar to the closure. They are also sometimes referred to as the *free variables* meaning they are not bound to the context of the closure. -[`compiler/rustc_middle/src/ty/query/mod.rs`][upvars] defines a query called *upvars_mentioned* +[`compiler/rustc_passes/src/upvars.rs`][upvars] defines a query called *upvars_mentioned* for this purpose. -[upvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_query_impl/queries/struct.upvars_mentioned.html +[upvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_passes/upvars/index.html Other than lazy invocation, one other thing that distinguishes a closure from a normal function is that it can use the upvars. It borrows these upvars from its surrounding diff --git a/src/doc/rustc-dev-guide/src/compiler-src.md b/src/doc/rustc-dev-guide/src/compiler-src.md index 9c7d0bb2e..6090c6787 100644 --- a/src/doc/rustc-dev-guide/src/compiler-src.md +++ b/src/doc/rustc-dev-guide/src/compiler-src.md @@ -195,11 +195,8 @@ These include: run a lot of tests on a lot of platforms. - [`src/doc`]: Various documentation, including submodules for a few books. - [`src/etc`]: Miscellaneous utilities. -- [`src/tools/rustc-workspace-hack`], and others: Various workarounds to make - cargo work with bootstrapping. - And more... [`src/ci`]: https://github.com/rust-lang/rust/tree/master/src/ci [`src/doc`]: https://github.com/rust-lang/rust/tree/master/src/doc [`src/etc`]: https://github.com/rust-lang/rust/tree/master/src/etc -[`src/tools/rustc-workspace-hack`]: https://github.com/rust-lang/rust/tree/master/src/tools/rustc-workspace-hack diff --git a/src/doc/rustc-dev-guide/src/constants.md b/src/doc/rustc-dev-guide/src/constants.md index 91d21bd32..56d01cc79 100644 --- a/src/doc/rustc-dev-guide/src/constants.md +++ b/src/doc/rustc-dev-guide/src/constants.md @@ -77,6 +77,6 @@ the constant doesn't use them in any way. This can cause [some interesting errors][pcg-unused-substs] and breaks some already stable code. [`ty::Const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Const.html -[`ty::ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.ConstKind.html +[`ty::ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.ConstKind.html [`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html [pcg-unused-substs]: https://github.com/rust-lang/project-const-generics/issues/33 diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index d6037c7f1..d6b9fc84d 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -2,7 +2,7 @@ <!-- toc --> -## Bug Reports +## Bug reports While bugs are unfortunate, they're a reality in software. We can't fix what we don't know about, so please report liberally. If you're not sure if something @@ -16,8 +16,7 @@ please follow our [instructions for reporting security vulnerabilities][vuln]**. If you're using the nightly channel, please check if the bug exists in the latest toolchain before filing your bug. It might be fixed already. -If you have the chance, before reporting a bug, please [search existing -issues](https://github.com/rust-lang/rust/issues?q=is%3Aissue), +If you have the chance, before reporting a bug, please [search existing issues], as it's possible that someone else has already reported your error. This doesn't always work, and sometimes it's hard to know what to search for, so consider this extra credit. We won't mind if you accidentally file a duplicate report. @@ -33,22 +32,22 @@ Opening an issue is as easy as following [this link](https://github.com/rust-lang/rust/issues/new/choose) and filling out the fields in the appropriate provided template. -## Bug Fixes or "Normal" code changes +## Bug fixes or "normal" code changes -For most PRs, no special procedures are needed. You can just [open a PR][prs], and it +For most PRs, no special procedures are needed. You can just [open a PR], and it will be reviewed, approved, and merged. This includes most bug fixes, refactorings, and other user-invisible changes. The next few sections talk about exceptions to this rule. -Also, note that it is perfectly acceptable to open WIP PRs or GitHub [Draft -PRs][draft]. Some people prefer to do this so they can get feedback along the +Also, note that it is perfectly acceptable to open WIP PRs or GitHub [Draft PRs]. +Some people prefer to do this so they can get feedback along the way or share their code with a collaborator. Others do this so they can utilize -the CI to build and test their PR (e.g. if you are developing on a laptop). +the CI to build and test their PR (e.g. when developing on a slow machine). -[prs]: #pull-requests -[draft]: https://github.blog/2019-02-14-introducing-draft-pull-requests/ +[open a PR]: #pull-requests +[Draft PRs]: https://github.blog/2019-02-14-introducing-draft-pull-requests/ -## New Features +## New features Rust has strong backwards-compatibility guarantees. Thus, new features can't just be implemented directly in stable Rust. Instead, we have 3 release @@ -63,13 +62,11 @@ channels: stable, beta, and nightly. See [this chapter on implementing new features](./implementing_new_features.md) for more information. -### Breaking Changes +### Breaking changes -Breaking changes have a [dedicated section][breaking-changes] in the dev-guide. +Breaking changes have a [dedicated section][Breaking Changes] in the dev-guide. -[breaking-changes]: ./bug-fix-procedure.md - -### Major Changes +### Major changes The compiler team has a special process for large changes, whether or not they cause breakage. This process is called a Major Change Proposal (MCP). MCP is a @@ -80,12 +77,12 @@ Example of things that might require MCPs include major refactorings, changes to important types, or important changes to how the compiler does something, or smaller user-facing changes. -**When in doubt, ask on [zulip][z]. It would be a shame to put a lot of work +**When in doubt, ask on [zulip]. It would be a shame to put a lot of work into a PR that ends up not getting merged!** [See this document][mcpinfo] for more info on MCPs. [mcpinfo]: https://forge.rust-lang.org/compiler/mcp.html -[z]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler +[zulip]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler ### Performance @@ -95,19 +92,19 @@ few years into [gradually improving it][perfdash]. [perfdash]: https://perf.rust-lang.org/dashboard.html If you suspect that your change may cause a performance regression (or -improvement), you can request a "perf run" (your reviewer may also request one +improvement), you can request a "perf run" (and your reviewer may also request one before approving). This is yet another bot that will compile a collection of benchmarks on a compiler with your changes. The numbers are reported [here][perf], and you can see a comparison of your changes against the latest master. -For an introduction to the performance of Rust code in general -which would also be useful in rustc development, see [The Rust Performance Book]. +> For an introduction to the performance of Rust code in general +> which would also be useful in rustc development, see [The Rust Performance Book]. [perf]: https://perf.rust-lang.org [The Rust Performance Book]: https://nnethercote.github.io/perf-book/ -## Pull Requests +## Pull requests Pull requests (or PRs for short) are the primary mechanism we use to change Rust. GitHub itself has some [great documentation][about-pull-requests] on using the @@ -135,15 +132,15 @@ to the end of the pull request description, and [@rustbot] will assign them instead of a random person. This is entirely optional. You can also assign a random reviewer from a specific team by writing `r? rust-lang/groupname`. -So if you were making a diagnostics change, then you could get a reviewer from the diagnostics -team by adding: +As an example, +if you were making a diagnostics change, +then you could get a reviewer from the diagnostics team by adding: r? rust-lang/diagnostics -For a full list of possible `groupname` check the `adhoc_groups` section at the -[triagebot.toml config file](https://github.com/rust-lang/rust/blob/master/triagebot.toml) -or the list of teams in the [rust-lang teams -database](https://github.com/rust-lang/team/tree/master/teams). +For a full list of possible `groupname`s, +check the `adhoc_groups` section at the [triagebot.toml config file], +or the list of teams in the [rust-lang teams database]. ### Waiting for reviews @@ -175,22 +172,21 @@ Zulip ([#t-release/triage]). They have knowledge of when to ping, who might be on vacation, etc. The reviewer may request some changes using the GitHub code review interface. -They may also request special procedures (such as a [crater] run; [see -below][break]) for some PRs. +They may also request special procedures for some PRs. +See [Crater] and [Breaking Changes] chapters for some examples of such procedures. [r?]: https://github.com/rust-lang/rust/pull/78133#issuecomment-712692371 [#t-release/triage]: https://rust-lang.zulipchat.com/#narrow/stream/242269-t-release.2Ftriage -[break]: #breaking-changes +[Crater]: tests/crater.md + ### CI -In addition to being reviewed by a human, pull requests are automatically tested +In addition to being reviewed by a human, pull requests are automatically tested, thanks to continuous integration (CI). Basically, every time you open and update a pull request, CI builds the compiler and tests it against the -[compiler test suite][rctd], and also performs other tests such as checking that +[compiler test suite], and also performs other tests such as checking that your pull request is in compliance with Rust's style guidelines. -[rctd]: tests/intro.md - Running continuous integration tests allows PR authors to catch mistakes early without going through a first review cycle, and also helps reviewers stay aware of the status of a particular pull request. @@ -198,7 +194,7 @@ of the status of a particular pull request. Rust has plenty of CI capacity, and you should never have to worry about wasting computational resources each time you push a change. It is also perfectly fine (and even encouraged!) to use the CI to test your changes if it can help your -productivity. In particular, we don't recommend running the full `./x.py test` suite locally, +productivity. In particular, we don't recommend running the full `./x test` suite locally, since it takes a very long time to execute. ### r+ @@ -209,7 +205,7 @@ on the pull request with an `r+`. It will look something like this: @bors r+ This tells [@bors], our lovable integration bot, that your pull request has -been approved. The PR then enters the [merge queue][merge-queue], where [@bors] +been approved. The PR then enters the [merge queue], where [@bors] will run *all* the tests on *every* platform we support. If it all works out, [@bors] will merge your code into `master` and close the pull request. @@ -226,25 +222,23 @@ Be patient; this can take a while and the queue can sometimes be long. PRs are n [@rustbot]: https://github.com/rustbot [@bors]: https://github.com/bors -[merge-queue]: https://bors.rust-lang.org/queue/rust ### Opening a PR You are now ready to file a pull request? Great! Here are a few points you should be aware of. -All pull requests should be filed against the `master` branch, except in very -particular scenarios. Unless you know for sure that you should target another -branch, `master` will be the right choice (it's also the default). +All pull requests should be filed against the `master` branch, +unless you know for sure that you should target a different branch. Make sure your pull request is in compliance with Rust's style guidelines by running - $ ./x.py test tidy --bless + $ ./x test tidy --bless We recommend to make this check before every pull request (and every new commit -in a pull request); you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) -before every push to make sure you never forget to make this check. The -CI will also run tidy and will fail if tidy fails. +in a pull request); you can add [git hooks] +before every push to make sure you never forget to make this check. +The CI will also run tidy and will fail if tidy fails. Rust follows a _no merge-commit policy_, meaning, when you encounter merge conflicts you are expected to always rebase instead of merging. E.g. always use @@ -268,11 +262,11 @@ the issue in question. [labeling]: ./rustbot.md#issue-relabeling [closing-keywords]: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue -## External Dependencies +## External dependencies This section has moved to ["Using External Repositories"](./external-repos.md). -## Writing Documentation +## Writing documentation Documentation improvements are very welcome. The source of `doc.rust-lang.org` is located in [`src/doc`] in the tree, and standard API documentation is generated @@ -282,13 +276,9 @@ function in the same way as other pull requests. [`src/doc`]: https://github.com/rust-lang/rust/tree/master/src/doc [std-root]: https://github.com/rust-lang/rust/blob/master/library/std/src/lib.rs#L1 -To find documentation-related issues, sort by the [A-docs label][adocs]. - -[adocs]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AA-docs - -You can find documentation style guidelines in [RFC 1574][rfc1574]. +To find documentation-related issues, sort by the [A-docs label]. -[rfc1574]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text +You can find documentation style guidelines in [RFC 1574]. To build the standard library documentation, use `x doc --stage 0 library --open`. To build the documentation for a book (e.g. the unstable book), use `x doc src/doc/unstable-book.` @@ -302,22 +292,23 @@ The CSS might be messed up, but you can verify that the HTML is right. ### Contributing to rustc-dev-guide -Contributions to the [rustc-dev-guide][rdg] are always welcome, and can be made directly at +Contributions to the [rustc-dev-guide] are always welcome, and can be made directly at [the rust-lang/rustc-dev-guide repo][rdgrepo]. The issue tracker in that repo is also a great way to find things that need doing. There are issues for beginners and advanced compiler devs alike! Just a few things to keep in mind: -- Please limit line length to 100 characters. This is enforced by CI, and you can run the checks - locally with `ci/lengthcheck.sh`. +- Please limit line length to 100 characters. + This is enforced by CI, + and you can run the checks locally with `ci/lengthcheck.sh`. - When contributing text to the guide, please contextualize the information with some time period and/or a reason so that the reader knows how much to trust or mistrust the information. Aim to provide a reasonable amount of context, possibly including but not limited to: - - A reason for why the data may be out of date other than "change", as change is a constant across - the project. + - A reason for why the data may be out of date other than "change", + as change is a constant across the project. - The date the comment was added, e.g. instead of writing _"Currently, ..."_ or _"As of now, ..."_, @@ -358,19 +349,15 @@ Just a few things to keep in mind: subsections) it might benefit from having a Table of Contents at the beginning, which you can auto-generate by including the `<!-- toc -->` marker. -[rdg]: https://rustc-dev-guide.rust-lang.org/ -[rdgrepo]: https://github.com/rust-lang/rustc-dev-guide - -## Issue Triage +## Issue triage -Sometimes, an issue will stay open, even though the bug has been fixed. And -sometimes, the original bug may go stale because something has changed in the -meantime. +Sometimes, an issue will stay open, even though the bug has been fixed. +And sometimes, the original bug may go stale because something has changed in the meantime. -It can be helpful to go through older bug reports and make sure that they are -still valid. Load up an older issue, double check that it's still true, and -leave a comment letting us know if it is or is not. The [least recently -updated sort][lru] is good for finding issues like this. +It can be helpful to go through older bug reports and make sure that they are still valid. +Load up an older issue, double check that it's still true, +and leave a comment letting us know if it is or is not. +The [least recently updated sort][lru] is good for finding issues like this. [Thanks to `@rustbot`][rustbot], anyone can help triage issues by adding appropriate labels to issues that haven't been triaged yet: @@ -466,8 +453,19 @@ This is used for [RFCs], issues, and pull requests. [rfcbot]: https://github.com/anp/rfcbot-rs/ [RFCs]: https://github.com/rust-lang/rfcs -## Helpful Links and Information - -This section has moved to the ["About this guide"][more-links] chapter. - -[more-links]: ./about-this-guide.md#other-places-to-find-information +## Helpful links and information + +This section has moved to the ["About this guide"] chapter. + +["About this guide"]: about-this-guide.md#other-places-to-find-information +[search existing issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue +[Breaking Changes]: bug-fix-procedure.md +[triagebot.toml config file]: https://github.com/rust-lang/rust/blob/HEAD/triagebot.toml +[rust-lang teams database]: https://github.com/rust-lang/team/tree/HEAD/teams +[compiler test suite]: tests/intro.md +[merge queue]: https://bors.rust-lang.org/queue/rust +[git hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks +[A-docs label]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AA-docs +[RFC 1574]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text +[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ +[rdgrepo]: https://github.com/rust-lang/rustc-dev-guide diff --git a/src/doc/rustc-dev-guide/src/conventions.md b/src/doc/rustc-dev-guide/src/conventions.md index 521aeb4a5..1c963c669 100644 --- a/src/doc/rustc-dev-guide/src/conventions.md +++ b/src/doc/rustc-dev-guide/src/conventions.md @@ -13,11 +13,11 @@ However, for now we don't use stable `rustfmt`; we use a pinned version with a special config, so this may result in different style from normal [`rustfmt`]. Therefore, formatting this repository using `cargo fmt` is not recommended. -Instead, formatting should be done using `./x.py fmt`. It's a good habit to run -`./x.py fmt` before every commit, as this reduces conflicts later. +Instead, formatting should be done using `./x fmt`. It's a good habit to run +`./x fmt` before every commit, as this reduces conflicts later. Formatting is checked by the `tidy` script. It runs automatically when you do -`./x.py test` and can be run in isolation with `./x.py fmt --check`. +`./x test` and can be run in isolation with `./x fmt --check`. If you want to use format-on-save in your editor, the pinned version of `rustfmt` is built under `build/<target>/stage0/bin/rustfmt`. You'll have to @@ -126,7 +126,7 @@ dramatically (versus adding to it) in a later commit, that **Format liberally.** While only the final commit of a PR must be correctly formatted, it is both easier to review and less noisy to format each commit -individually using `./x.py fmt`. +individually using `./x fmt`. **No merges.** We do not allow merge commits into our history, other than those by bors. If you get a merge conflict, rebase instead via a diff --git a/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md b/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md index 932b23b92..ac629934e 100644 --- a/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md +++ b/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md @@ -133,8 +133,7 @@ or `symbols`. Rust has support for embedding Natvis files for crates outside of the standard libraries by using the `#[debugger_visualizer]` attribute. For more details on how to embed debugger visualizers, -please refer to the `#[debugger_visualizer]` attribute in -[the unstable book](https://doc.rust-lang.org/unstable-book/language-features/debugger-visualizer.html). +please refer to the section on the [`debugger_visualizer` attribute]. ## DWARF and `rustc` @@ -352,3 +351,4 @@ but may have to add some mode to let the compiler understand some extensions. [symbol records]: https://llvm.org/docs/PDB/CodeViewSymbols.html [type records]: https://llvm.org/docs/PDB/CodeViewTypes.html [Windows Debugging Tools]: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/ +[`debugger_visualizer` attribute]: https://doc.rust-lang.org/nightly/reference/attributes/debugger.html#the-debugger_visualizer-attribute diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index daaffba7b..9f4245f28 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -507,6 +507,83 @@ module. [rlint]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/index.html +### When do lints run? + +Different lints will run at different times based on what information the lint +needs to do its job. Some lints get grouped into *passes* where the lints +within a pass are processed together via a single visitor. Some of the passes +are: + +- Pre-expansion pass: Works on [AST nodes] before [macro expansion]. This + should generally be avoided. + - Example: [`keyword_idents`] checks for identifiers that will become + keywords in future editions, but is sensitive to identifiers used in + macros. + +- Early lint pass: Works on [AST nodes] after [macro expansion] and name + resolution, just before [HIR lowering]. These lints are for purely + syntactical lints. + - Example: The [`unsued_parens`] lint checks for parenthesized-expressions + in situations where they are not needed, like an `if` condition. + +- Late lint pass: Works on [HIR nodes], towards the end of [analysis] (after + borrow checking, etc.). These lints have full type information available. + Most lints are late. + - Example: The [`invalid_value`] lint (which checks for obviously invalid + uninitialized values) is a late lint because it needs type information to + figure out whether a type allows being left uninitialized. + +- MIR pass: Works on [MIR nodes]. This isn't quite the same as other passes; + lints that work on MIR nodes have their own methods for running. + - Example: The [`arithmetic_overflow`] lint is emitted when it detects a + constant value that may overflow. + +Most lints work well via the pass systems, and they have a fairly +straightforward interface and easy way to integrate (mostly just implementing +a specific `check` function). However, some lints are easier to write when +they live on a specific code path anywhere in the compiler. For example, the +[`unused_mut`] lint is implemented in the borrow checker as it requires some +information and state in the borrow checker. + +Some of these inline lints fire before the linting system is ready. Those +lints will be *buffered* where they are held until later phases of the +compiler when the linting system is ready. See [Linting early in the +compiler](#linting-early-in-the-compiler). + + +[AST nodes]: the-parser.md +[HIR lowering]: lowering.md +[HIR nodes]: hir.md +[MIR nodes]: mir/index.md +[macro expansion]: macro-expansion.md +[analysis]: part-4-intro.md +[`keyword_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#keyword-idents +[`unsued_parens`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unused-parens +[`invalid_value`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#invalid-value +[`arithmetic_overflow`]: https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#arithmetic-overflow +[`unused_mut`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unused-mut + +### Lint definition terms + +Lints are managed via the [`LintStore`][LintStore] and get registered in +various ways. The following terms refer to the different classes of lints +generally based on how they are registered. + +- *Built-in* lints are defined inside the compiler source. +- *Driver-registered* lints are registered when the compiler driver is created + by an external driver. This is the mechanism used by Clippy, for example. +- *Plugin* lints are registered by the [deprecated plugin system]. +- *Tool* lints are lints with a path prefix like `clippy::` or `rustdoc::`. +- *Internal* lints are the `rustc::` scoped tool lints that only run on the + rustc source tree itself and are defined in the compiler source like a + regular built-in lint. + +More information about lint registration can be found in the [LintStore] +chapter. + +[deprecated plugin system]: https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html +[LintStore]: diagnostics/lintstore.md + ### Declaring a lint The built-in compiler lints are defined in the [`rustc_lint`][builtin] diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md index 790d74dcf..6d698e3f3 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -70,7 +70,7 @@ Diagnostics are more than just their primary message, they often include labels, notes, help messages and suggestions, all of which can also be specified on a `Diagnostic`. -`#[label]`, `#[help]` and `#[note]` can all be applied to fields which have the +`#[label]`, `#[help]`, `#[warning]` and `#[note]` can all be applied to fields which have the type `Span`. Applying any of these attributes will create the corresponding subdiagnostic with that `Span`. These attributes will look for their diagnostic message in a Fluent attribute attached to the primary Fluent @@ -87,11 +87,11 @@ Other types have special behavior when used in a `Diagnostic` derive: - Any attribute applied to a `Vec<T>` will be repeated for each element of the vector. -`#[help]` and `#[note]` can also be applied to the struct itself, in which case +`#[help]`, `#[warning]` and `#[note]` can also be applied to the struct itself, in which case they work exactly like when applied to fields except the subdiagnostic won't have a `Span`. These attributes can also be applied to fields of type `()` for the same effect, which when combined with the `Option` type can be used to -represent optional `#[note]`/`#[help]` subdiagnostics. +represent optional `#[note]`/`#[help]`/`#[warning]` subdiagnostics. Suggestions can be emitted using one of four field attributes: @@ -161,14 +161,14 @@ following attributes: - `code = "..."` (_Optional_) - Specifies the error code. - `#[note]` or `#[note(slug)]` (_Optional_) - - _Applied to struct or `Span`/`()` fields._ + - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a note subdiagnostic. - Value is a path to an item in `rustc_errors::fluent` for the note's message. - Defaults to equivalent of `.note`. - If applied to a `Span` field, creates a spanned note. - `#[help]` or `#[help(slug)]` (_Optional_) - - _Applied to struct or `Span`/`()` fields._ + - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a help subdiagnostic. - Value is a path to an item in `rustc_errors::fluent` for the note's message. @@ -180,8 +180,8 @@ following attributes: - Value is a path to an item in `rustc_errors::fluent` for the note's message. - Defaults to equivalent of `.label`. -- `#[warn_]` or `#[warn_(slug)]` (_Optional_) - - _Applied to `Span` fields._ +- `#[warning]` or `#[warning(slug)]` (_Optional_) + - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a warning subdiagnostic. - Value is a path to an item in `rustc_errors::fluent` for the note's message. @@ -253,6 +253,7 @@ attribute applied to the struct or each variant, one of: - `#[label(..)]` for defining a label - `#[note(..)]` for defining a note - `#[help(..)]` for defining a help +- `#[warning(..)]` for defining a warning - `#[suggestion{,_hidden,_short,_verbose}(..)]` for defining a suggestion All of the above must provide a slug as the first positional argument (a path @@ -333,7 +334,7 @@ diagnostic struct. ### Reference `#[derive(Subdiagnostic)]` supports the following attributes: -- `#[label(slug)]`, `#[help(slug)]` or `#[note(slug)]` +- `#[label(slug)]`, `#[help(slug)]`, `#[warning(slug)]` or `#[note(slug)]` - _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._ - _Mandatory_ - Defines the type to be representing a label, help or note. diff --git a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md index 2dbdb53fe..7cdf5ebca 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md @@ -37,7 +37,7 @@ To create a new error, you first need to find the next available code. You can find it with `tidy`: ``` -./x.py test tidy +./x test tidy ``` This will invoke the tidy script, which generally checks that your code obeys diff --git a/src/doc/rustc-dev-guide/src/diagnostics/translation.md b/src/doc/rustc-dev-guide/src/diagnostics/translation.md index e3ccec7d7..a42a15484 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/translation.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/translation.md @@ -86,10 +86,10 @@ excellent examples of translating messages into different locales and the information that needs to be provided by the code to do so. ### Compile-time validation and typed identifiers -rustc's Fluent resources for the default locale (`en-US`) are in the -[`compiler/rustc_error_messages/locales/en-US`] directory. Currently, each crate -which defines translatable diagnostics has its own Fluent resource, such as -`parser.ftl` or `typeck.ftl`. +Currently, each crate which defines translatable diagnostics has its own +Fluent resource in a file named `messages.ftl`, such as +[`compiler/rustc_borrowck/messages.ftl`] and +[`compiler/rustc_parse/messages.ftl`]. rustc's `fluent_messages` macro performs compile-time validation of Fluent resources and generates code to make it easier to refer to Fluent messages in @@ -240,5 +240,6 @@ won't fail. Bundle loading can fail if a requested locale is missing, Fluent files are malformed, or a message is duplicated in multiple resources. [Fluent]: https://projectfluent.org -[`compiler/rustc_error_messages/locales/en-US`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_error_messages/locales/en-US +[`compiler/rustc_borrowck/messages.ftl`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_borrowck/messages.ftl +[`compiler/rustc_parse/messages.ftl`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_parse/messages.ftl [`rustc_error_messages::DiagnosticMessage`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_error_messages/enum.DiagnosticMessage.html diff --git a/src/doc/rustc-dev-guide/src/early-late-bound.md b/src/doc/rustc-dev-guide/src/early-late-bound.md index 29b2136b4..8fb856742 100644 --- a/src/doc/rustc-dev-guide/src/early-late-bound.md +++ b/src/doc/rustc-dev-guide/src/early-late-bound.md @@ -1,107 +1,199 @@ -# Early and Late Bound Variables +# Early and Late Bound Parameter Definitions -In Rust, item definitions (like `fn`) can often have generic parameters, which -are always [_universally_ quantified][quant]. That is, if you have a function -like +Understanding this page likely requires a rudimentary understanding of higher ranked +trait bounds/`for<'a>`and also what types such as `dyn for<'a> Trait<'a>` and +`for<'a> fn(&'a u32)` mean. Reading [the nomincon chapter](https://doc.rust-lang.org/nomicon/hrtb.html) +on HRTB may be useful for understanding this syntax. The meaning of `for<'a> fn(&'a u32)` +is incredibly similar to the meaning of `T: for<'a> Trait<'a>`. +If you are looking for information on the `RegionKind` variants `ReLateBound` and `ReEarlyBound` +you should look at the section on [bound vars and params](./bound-vars-and-params.md). This section +discusses what makes generic parameters on functions and closures late/early bound. Not the general +concept of bound vars and generic parameters which `RegionKind` has named somewhat confusingly +with this topic. + +## What does it mean for parameters to be early or late bound + +All function definitions conceptually have a ZST (this is represented by `TyKind::FnDef` in rustc). +The only generics on this ZST are the early bound parameters of the function definition. e.g. ```rust -fn foo<T>(x: T) { } +fn foo<'a>(_: &'a u32) {} + +fn main() { + let b = foo; + // ^ `b` has type `FnDef(foo, [])` (no substs because `'a` is late bound) + assert!(std::mem::size_of_val(&b) == 0); +} ``` -this function is defined "for all T" (not "for some specific T", which would be -[_existentially_ quantified][quant]). +In order to call `b` the late bound parameters do need to be provided, these are inferred at the +call site instead of when we refer to `foo`. +```rust +fn main() { + let b = foo; + let a: &'static u32 = &10; + foo(a); + // the lifetime argument for `'a` on `foo` is inferred at the callsite + // the generic parameter `'a` on `foo` is inferred to `'static` here +} +``` + +Because late bound parameters are not part of the `FnDef`'s substs this allows us to prove trait +bounds such as `F: for<'a> Fn(&'a u32)` where `F` is `foo`'s `FnDef`. e.g. +```rust +fn foo_early<'a, T: Trait<'a>>(_: &'a u32, _: T) {} +fn foo_late<'a, T>(_: &'a u32, _: T) {} + +fn accepts_hr_func<F: for<'a> Fn(&'a u32, u32)>(_: F) {} + +fn main() { + // doesnt work, the substituted bound is `for<'a> FnDef<'?0>: Fn(&'a u32, u32)` + // `foo_early` only implements `for<'a> FnDef<'a>: Fn(&'a u32, u32)`- the lifetime + // of the borrow in the function argument must be the same as the lifetime + // on the `FnDef`. + accepts_hr_func(foo_early); + + // works, the substituted bound is `for<'a> FnDef: Fn(&'a u32, u32)` + accepts_hr_func(foo_late); +} + +// the builtin `Fn` impls for `foo_early` and `foo_late` look something like: +// `foo_early` +impl<'a, T: Trait<'a>> Fn(&'a u32, T) for FooEarlyFnDef<'a, T> { ... } +// `foo_late` +impl<'a, T> Fn(&'a u32, T) for FooLateFnDef<T> { ... } + +``` + +Early bound parameters are present on the `FnDef`. Late bound generic parameters are not present +on the `FnDef` but are instead constrained by the builtin `Fn*` impl. + +The same distinction applies to closures. Instead of `FnDef` we are talking about the anonymous +closure type. Closures are [currently unsound](https://github.com/rust-lang/rust/issues/84366) in +ways that are closely related to the distinction between early/late bound +parameters (more on this later) + +The early/late boundness of generic parameters is only relevent for the desugaring of +functions/closures into types with builtin `Fn*` impls. It does not make sense to talk about +in other contexts. + +The `generics_of` query in rustc only contains early bound parameters. In this way it acts more +like `generics_of(my_func)` is the generics for the FnDef than the generics provided to the function +body although it's not clear to the author of this section if this was the actual justification for +making `generics_of` behave this way. -[quant]: ./appendix/background.md#quantified +## What parameters are currently late bound -While Rust *items* can be quantified over types, lifetimes, and constants, the -types of values in Rust are only ever quantified over lifetimes. So you can -have a type like `for<'a> fn(&'a u32)`, which represents a function pointer -that takes a reference with any lifetime, or `for<'a> dyn Trait<'a>`, which is -a `dyn` trait for a trait implemented for any lifetime; but we have no type -like `for<T> fn(T)`, which would be a function that takes a value of *any type* -as a parameter. This is a consequence of monomorphization -- to support a value -of type `for<T> fn(T)`, we would need a single function pointer that can be -used for a parameter of any type, but in Rust we generate customized code for -each parameter type. +Below are the current requirements for determining if a generic parameter is late bound. It is worth +keeping in mind that these are not necessarily set in stone and it is almost certainly possible to +be more flexible. -One consequence of this asymmetry is a weird split in how we represent some -generic types: _early-_ and _late-_ bound parameters. -Basically, if we cannot represent a type (e.g. a universally quantified type), -we have to bind it _early_ so that the unrepresentable type is never around. +### Must be a lifetime parameter -Consider the following example: +Rust can't support types such as `for<T> dyn Trait<T>` or `for<T> fn(T)`, this is a +fundamental limitation of the language as we are required to monomorphize type/const +parameters and cannot do so behind dynamic dispatch. (technically we could probably +support `for<T> dyn MarkerTrait<T>` as there is nothing to monomorphize) -```rust,ignore -fn foo<'a, 'b, T>(x: &'a u32, y: &'b T) where T: 'b { ... } +Not being able to support `for<T> dyn Trait<T>` resulted in making all type and const +parameters early bound. Only lifetime parameters can be late bound. + +### Must not appear in the where clauses + +In order for a generic parameter to be late bound it must not appear in any where clauses. +This is currently an incredibly simplistic check that causes lifetimes to be early bound even +if the where clause they appear in are always true, or implied by well formedness of function +arguments. e.g. +```rust +fn foo1<'a: 'a>(_: &'a u32) {} +// ^^ early bound parameter because it's in a `'a: 'a` clause +// even though the bound obviously holds all the time +fn foo2<'a, T: Trait<'a>(a: T, b: &'a u32) {} +// ^^ early bound parameter because it's used in the `T: Trait<'a>` clause +fn foo3<'a, T: 'a>(_: &'a T) {} +// ^^ early bound parameter because it's used in the `T: 'a` clause +// even though that bound is implied by wellformedness of `&'a T` +fn foo4<'a, 'b: 'a>(_: Inv<&'a ()>, _: Inv<&'b ()>) {} +// ^^ ^^ ^^^ note: +// ^^ ^^ `Inv` stands for `Invariant` and is used to +// ^^ ^^ make the the type parameter invariant. This +// ^^ ^^ is necessary for demonstration purposes as +// ^^ ^^ `for<'a, 'b> fn(&'a (), &'b ())` and +// ^^ ^^ `for<'a> fn(&'a u32, &'a u32)` are subtypes- +// ^^ ^^ of eachother which makes the bound trivially +// ^^ ^^ satisfiable when making the fnptr. `Inv` +// ^^ ^^ disables this subtyping. +// ^^ ^^ +// ^^^^^^ both early bound parameters because they are present in the +// `'b: 'a` clause ``` -We cannot treat `'a`, `'b`, and `T` in the same way. Types in Rust can't have -`for<T> { .. }`, only `for<'a> {...}`, so whenever you reference `foo` the type -you get back can't be `for<'a, 'b, T> fn(&'a u32, y: &'b T)`. Instead, the `T` -must be substituted early. In particular, you have: +The reason for this requirement is that we cannot represent the `T: Trait<'a>` or `'a: 'b` clauses +on a function pointer. `for<'a, 'b> fn(Inv<&'a ()>, Inv<&'b ()>)` is not a valid function pointer to +represent`foo4` as it would allow calling the function without `'b: 'a` holding. -```rust,ignore -let x = foo; // T, 'b have to be substituted here -x(...); // 'a substituted here, at the point of call -x(...); // 'a substituted here with a different value +### Must be constrained by where clauses or function argument types + +The builtin impls of the `Fn*` traits for closures and `FnDef`s cannot not have any unconstrained +parameters. For example the following impl is illegal: +```rust +impl<'a> Trait for u32 { type Assoc = &'a u32; } +``` +We must not end up with a similar impl for the `Fn*` traits e.g. +```rust +impl<'a> Fn<()> for FnDef { type Assoc = &'a u32 } ``` -## Early-bound parameters +Violating this rule can trivially lead to unsoundness as seen in [#84366](https://github.com/rust-lang/rust/issues/84366). +Additionally if we ever support late bound type params then an impl like: +```rust +impl<T> Fn<()> for FnDef { type Assoc = T; } +``` +would break the compiler in various ways. -Early-bound parameters in rustc are identified by an index, stored in the -[`ParamTy`] struct for types or the [`EarlyBoundRegion`] struct for lifetimes. -The index counts from the outermost declaration in scope. This means that as you -add more binders inside, the index doesn't change. +In order to ensure that everything functions correctly, we do not allow generic parameters to +be late bound if it would result in a builtin impl that does not constrain all of the generic +parameters on the builtin impl. Making a generic parameter be early bound trivially makes it be +constrained by the builtin impl as it ends up on the self type. -For example, +Because of the requirement that late bound parameters must not appear in where clauses, checking +this is simpler than the rules for checking impl headers constrain all the parameters on the impl. +We only have to ensure that all late bound parameters appear at least once in the function argument +types outside of an alias (e.g. an associated type). -```rust,ignore -trait Foo<T> { - type Bar<U> = (Self, T, U); -} +The requirement that they not indirectly be in the substs of an alias for it to count is the +same as why the follow code is forbidden: +```rust +impl<T: Trait> OtherTrait for <T as Trait>::Assoc { type Assoc = T } ``` +There is no guarantee that `<T as Trait>::Assoc` will normalize to different types for every +instantiation of `T`. If we were to allow this impl we could get overlapping impls and the +same is true of the builtin `Fn*` impls. + +## Making more generic parameters late bound + +It is generally considered desirable for more parameters to be late bound as it makes +the builtin `Fn*` impls more flexible. Right now many of the requirements for making +a parameter late bound are overly restrictive as they are tied to what we can currently +(or can ever) do with fn ptrs. + +It would be theoretically possible to support late bound params in `where`-clauses in the +language by introducing implication types which would allow us to express types such as: +`for<'a, 'b: 'a> fn(Inv<&'a u32>, Inv<&'b u32>)` which would ensure `'b: 'a` is upheld when +calling the function pointer. + +It would also be theoretically possible to support it by making the coercion to a fn ptr +instantiate the parameter with an infer var while still allowing the FnDef to not have the +generic parameter present as trait impls are perfectly capable of representing the where clauses +on the function on the impl itself. This would also allow us to support late bound type/const +vars allowing bounds like `F: for<T> Fn(T)` to hold. + +It is almost somewhat unclear if we can change the `Fn` traits to be structured differently +so that we never have to make a parameter early bound just to make the builtin impl have all +generics be constrained. Of all the possible causes of a generic parameter being early bound +this seems the most difficult to remove. + +Whether these would be good ideas to implement is a separate question- they are only brought +up to illustrate that the current rules are not necessarily set in stone and a result of +"its the only way of doing this". -Here, the type `(Self, T, U)` would be `($0, $1, $2)`, where `$N` means a -[`ParamTy`] with the index of `N`. - -In rustc, the [`Generics`] structure carries this information. So the -[`Generics`] for `Bar` above would be just like for `U` and would indicate the -'parent' generics of `Foo`, which declares `Self` and `T`. You can read more -in [this chapter](./generics.md). - -[`ParamTy`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamTy.html -[`EarlyBoundRegion`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.EarlyBoundRegion.html -[`Generics`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html - -## Late-bound parameters - -Late-bound parameters in `rustc` are handled quite differently (they are also -specialized to lifetimes since, right now, only late-bound lifetimes are -supported, though with GATs that has to change). We indicate their potential -presence by a [`Binder`] type. The [`Binder`] doesn't know how many variables -there are at that binding level. This can only be determined by walking the -type itself and collecting them. So a type like `for<'a, 'b> ('a, 'b)` would be -`for (^0.a, ^0.b)`. Here, we just write `for` because we don't know the names -of the things bound within. - -Moreover, a reference to a late-bound lifetime is written `^0.a`: - -- The `0` is the index; it identifies that this lifetime is bound in the - innermost binder (the `for`). -- The `a` is the "name"; late-bound lifetimes in rustc are identified by a - "name" -- the [`BoundRegionKind`] enum. This enum can contain a - [`DefId`][defid] or it might have various "anonymous" numbered names. The - latter arise from types like `fn(&u32, &u32)`, which are equivalent to - something like `for<'a, 'b> fn(&'a u32, &'b u32)`, but the names of those - lifetimes must be generated. - -This setup of not knowing the full set of variables at a binding level has some -advantages and some disadvantages. The disadvantage is that you must walk the -type to find out what is bound at the given level and so forth. The advantage -is primarily that, when constructing types from Rust syntax, if we encounter -anonymous regions like in `fn(&u32)`, we just create a fresh index and don't have -to update the binder. - -[`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html -[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html -[defid]: ./hir.html#identifiers-in-the-hir diff --git a/src/doc/rustc-dev-guide/src/feature-gates.md b/src/doc/rustc-dev-guide/src/feature-gates.md index 9e9a83ea6..8ad4fea1f 100644 --- a/src/doc/rustc-dev-guide/src/feature-gates.md +++ b/src/doc/rustc-dev-guide/src/feature-gates.md @@ -3,44 +3,16 @@ This chapter is intended to provide basic help for adding, removing, and modifying feature gates. +Note that this is specific to *language* feature gates; *library* feature gates use [a different +mechanism][libs-gate]. -## Adding a feature gate - -See ["Stability in code"] for help with adding a new feature; this section just -covers how to add the feature gate *declaration*. - -First, add the feature name to `rustc_span/src/symbol.rs` in the `Symbols {...}` block. - -Then, add a feature gate declaration to `rustc_feature/src/active.rs` in the active -`declare_features` block: - -```rust,ignore -/// description of feature -(active, $feature_name, "$current_nightly_version", Some($tracking_issue_number), $edition) -``` +[libs-gate]: ./stability.md -where `$edition` has the type `Option<Edition>`, and is typically -just `None`. - -For example: - -```rust,ignore -/// Allows defining identifiers beyond ASCII. -(active, non_ascii_idents, "1.0.0", Some(55467), None), -``` - -Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features` lint] -by setting their type to `incomplete`: - -```rust,ignore -/// Allows unsized rvalues at arguments and parameters. -(incomplete, unsized_locals, "1.30.0", Some(48055), None), -``` +## Adding a feature gate -When added, the current version should be the one for the current nightly. -Once the feature is moved to `accepted.rs`, the version is changed to that -nightly version. +See ["Stability in code"][adding] in the "Implementing new features" section for instructions. +[adding]: ./implementing_new_features.md#stability-in-code ## Removing a feature gate @@ -109,5 +81,4 @@ updating the declaration! ["Stability in code"]: ./implementing_new_features.md#stability-in-code -[`incomplete_features` lint]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#incomplete-features ["Updating the feature-gate listing"]: ./stabilization_guide.md#updating-the-feature-gate-listing diff --git a/src/doc/rustc-dev-guide/src/fuzzing.md b/src/doc/rustc-dev-guide/src/fuzzing.md index 3fb1add01..869fc2f71 100644 --- a/src/doc/rustc-dev-guide/src/fuzzing.md +++ b/src/doc/rustc-dev-guide/src/fuzzing.md @@ -36,7 +36,7 @@ project, please read this guide before reporting fuzzer-generated bugs! If you're not sure whether or not an ICE is a duplicate of one that's already been reported, please go ahead and report it and link to issues you think might be related. In general, ICEs on the same line but with different *query stacks* -are usually distinct bugs. For example, [#109020][#109202] and [#109129][#109129] +are usually distinct bugs. For example, [#109020][#109020] and [#109129][#109129] had similar error messages: ``` @@ -100,7 +100,7 @@ to avoid introducing syntax, type-, and borrow-checking errors while using these tools, post both the complete and minimized test cases. Generally, *syntax-aware* tools give the best results in the least amount of time. [`treereduce-rust`][treereduce] and [picireny][picireny] are syntax-aware. -`halfempty` is not, but is generally a high-quality tool. +[`halfempty`][halfempty] is not, but is generally a high-quality tool. [halfempty]: https://github.com/googleprojectzero/halfempty [picireny]: https://github.com/renatahodovan/picireny @@ -146,4 +146,4 @@ ICEs that require debug assertions to reproduce should be tagged [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/
\ No newline at end of file +[tree-splicer]: https://github.com/langston-barrett/tree-splicer/ diff --git a/src/doc/rustc-dev-guide/src/generic_arguments.md b/src/doc/rustc-dev-guide/src/generic_arguments.md index c9911acf5..6e09e8620 100644 --- a/src/doc/rustc-dev-guide/src/generic_arguments.md +++ b/src/doc/rustc-dev-guide/src/generic_arguments.md @@ -1,28 +1,28 @@ # Generic arguments -A `ty::subst::GenericArg<'tcx>` represents some entity in the type system: a type +A `ty::GenericArg<'tcx>` represents some entity in the type system: a type (`Ty<'tcx>`), lifetime (`ty::Region<'tcx>`) or constant (`ty::Const<'tcx>`). -`GenericArg` is used to perform substitutions of generic parameters for concrete +`GenericArg` is used to perform instantiation of generic parameters to concrete arguments, such as when calling a function with generic parameters explicitly -with type arguments. Substitutions are represented using the -[`Subst` type](#subst) as described below. +with type arguments. Instantiations are represented using the +[`GenericArgs` type](#genericargs) as described below. -## `Subst` -`ty::subst::Subst<'tcx>` is intuitively simply a slice of `GenericArg<'tcx>`s, -acting as an ordered list of substitutions from generic parameters to +## `GenericArgs` +`ty::GenericArgs<'tcx>` is intuitively simply a slice of `GenericArg<'tcx>`s, +acting as an ordered list of generic parameters instantiated to concrete arguments (such as types, lifetimes and consts). For example, given a `HashMap<K, V>` with two type parameters, `K` and `V`, an instantiation of the parameters, for example `HashMap<i32, u32>`, would be -represented by the substitution `&'tcx [tcx.types.i32, tcx.types.u32]`. +represented by `&'tcx [tcx.types.i32, tcx.types.u32]`. -`Subst` provides various convenience methods to instantiate substitutions +`GenericArgs` provides various convenience methods to instantiate generic arguments given item definitions, which should generally be used rather than explicitly -constructing such substitution slices. +instantiating such slices. ## `GenericArg` The actual `GenericArg` struct is optimised for space, storing the type, lifetime or const as an interned pointer containing a tag identifying its kind (in the -lowest 2 bits). Unless you are working with the `Subst` implementation +lowest 2 bits). Unless you are working with the `GenericArgs` implementation specifically, you should generally not have to deal with `GenericArg` and instead make use of the safe [`GenericArgKind`](#genericargkind) abstraction. @@ -30,7 +30,7 @@ make use of the safe [`GenericArgKind`](#genericargkind) abstraction. As `GenericArg` itself is not type-safe, the `GenericArgKind` enum provides a more convenient and safe interface for dealing with generic arguments. An `GenericArgKind` can be converted to a raw `GenericArg` using `GenericArg::from()` -(or simply `.into()` when the context is clear). As mentioned earlier, substitution +(or simply `.into()` when the context is clear). As mentioned earlier, instantiation lists store raw `GenericArg`s, so before dealing with them, it is preferable to convert them to `GenericArgKind`s first. This is done by calling the `.unpack()` method. @@ -44,7 +44,7 @@ fn deal_with_generic_arg<'tcx>(generic_arg: GenericArg<'tcx>) -> GenericArg<'tcx GenericArgKind::Lifetime(lt) => { /* ... */ } GenericArgKind::Const(ct) => { /* ... */ } }; - // Pack the `GenericArgKind` to store it in a substitution list. + // Pack the `GenericArgKind` to store it in a generic args list. new_generic_arg.into() } ``` diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index 297873d98..80c3d3793 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -57,7 +57,7 @@ even if you can't figure out who to ping. Another way to find experts for a given part of the compiler is to see who has made recent commits. For example, to find people who have recently worked on name resolution since the 1.68.2 release, you could run `git shortlog -n 1.68.2.. compiler/rustc_resolve/`. Ignore any commits starting with -"Rollup merge" or commits by `@bors` (see [CI contribution prodcedures](./contributing.md#ci) for +"Rollup merge" or commits by `@bors` (see [CI contribution procedures](./contributing.md#ci) for more information about these commits). [map]: https://github.com/rust-lang/compiler-team/blob/master/content/experts/map.toml @@ -90,7 +90,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%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+ [Triage]: ./contributing.md#issue-triage ### Recurring work diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index 34f2f101e..6c5c64685 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -10,7 +10,7 @@ can be incorporated into the compiler. The goal of this page is to cover some of the more common questions and problems new contributors face. Although some Git basics will be covered here, -if you find that this is still a little too fast for you, it might make sense +if you find that this is still a little too fast for you, it might make sense to first read some introductions to Git, such as the Beginner and Getting started sections of [this tutorial from Atlassian][atlassian-git]. GitHub also provides [documentation] and [guides] for beginners, or you can consult the @@ -139,7 +139,7 @@ You might also notice conflicts in the web UI: ![conflict in src/tools/cargo](./img/submodule-conflicts.png) The most common cause is that you rebased after a change and ran `git add .` without first running -`x.py` to update the submodules. Alternatively, you might have run `cargo fmt` instead of `x fmt` +`x` to update the submodules. Alternatively, you might have run `cargo fmt` instead of `x fmt` and modified files in a submodule, then committed the changes. To fix it, do the following things: @@ -167,7 +167,7 @@ error: cannot rebase: You have unstaged changes. error: Please commit or stash them. ``` -(See https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F#_the_three_states for the difference between the two.) +(See <https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F#_the_three_states> for the difference between the two.) This means you have made changes since the last time you made a commit. To be able to rebase, either commit your changes, or make a temporary commit called a "stash" to have them still not be commited @@ -178,7 +178,7 @@ will prevent the "cannot rebase" error in nearly all cases: git config --global rebase.autostash true ``` -See https://git-scm.com/book/en/v2/Git-Tools-Stashing-and-Cleaning for more info about stashing. +See <https://git-scm.com/book/en/v2/Git-Tools-Stashing-and-Cleaning> for more info about stashing. ### I see 'Untracked Files: src/stdarch'? @@ -239,31 +239,13 @@ no changes added to commit (use "git add" and/or "git commit -a") ``` These changes are not changes to files: they are changes to submodules (more on this -[later](#git-submodules)). To get rid of those, run `./x.py --help`, which will automatically update +[later](#git-submodules)). To get rid of those, run `./x --help`, which will automatically update the submodules. Some submodules are not actually needed; for example, `src/llvm-project` doesn't need to be checked out if you're using `download-ci-llvm`. To avoid having to keep fetching its history, you can use `git submodule deinit -f src/llvm-project`, which will also avoid it showing as modified again. -Note that, as of <!-- date-check --> Aug 2022, -there is a [bug][#77620] if you use worktrees, -submodules, and `x.py` in a commit hook. -If you run into an error like the following, -it's not anything you did wrong: - -``` -error: failed to read `/home/jyn/rustc-worktree/src/tools/cargo/Cargo.toml` - -Caused by: - No such file or directory (os error 2) -``` - -There is a workaround in [the issue][#77620-workaround]. - -[#77620]: https://github.com/rust-lang/rust/issues/77620 -[#77620-workaround]: https://github.com/rust-lang/rust/issues/77620#issuecomment-705228229 - ## Rebasing and Conflicts When you edit your code locally, you are making changes to the version of @@ -314,7 +296,7 @@ Generally, resolving the conflict consists of two steps: First, fix the particular conflict. Edit the file to make the changes you want and remove the `<<<<<<<`, `=======` and `>>>>>>>` lines in the process. Second, check the surrounding code. If there was a conflict, its likely there are some logical -errors lying around too! It's a good idea to run `x.py check` here to make sure +errors lying around too! It's a good idea to run `x check` here to make sure there are no glaring errors. Once you're all done fixing the conflicts, you need to stage the files that had @@ -461,7 +443,7 @@ that merge commits in PRs are not accepted. As a result, if you are running course, this is not always true; if your merge will just be a fast-forward, like the merges that `git pull` usually performs, then no merge commit is created and you have nothing to worry about. Running `git config merge.ff only` -(this will apply the config to the local repo). +(this will apply the config to the local repo) once will ensure that all the merges you perform are of this type, so that you cannot make a mistake. @@ -558,7 +540,7 @@ commit, which doesn't change unless modified manually. If you use `git checkout in the `llvm-project` directory and go back to the `rust` directory, you can stage this change like any other, e.g. by running `git add src/llvm-project`. (Note that if you *don't* stage the change to commit, then you run the risk that running -`x.py` will just undo your change by switching back to the previous commit when +`x` will just undo your change by switching back to the previous commit when it automatically "updates" the submodules.) This version selection is usually done by the maintainers of the project, and diff --git a/src/doc/rustc-dev-guide/src/identifiers.md b/src/doc/rustc-dev-guide/src/identifiers.md index 09e85c019..c7e32d04c 100644 --- a/src/doc/rustc-dev-guide/src/identifiers.md +++ b/src/doc/rustc-dev-guide/src/identifiers.md @@ -70,7 +70,7 @@ See the [HIR chapter][hir-map] for more detailed information. - [`Local`] identifies a local variable in a function. Its associated data is in [`LocalDecl`], which can be retrieved by indexing into [`Body.local_decls`]. -- [`Field`] identifies a struct's, union's, or enum variant's field. It is used +- [`FieldIdx`] identifies a struct's, union's, or enum variant's field. It is used as a "projection" in [`Place`]. - [`SourceScope`] identifies a name scope in the original source code. Used for @@ -96,7 +96,7 @@ See the [HIR chapter][hir-map] for more detailed information. [`Local`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Local.html [`LocalDecl`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.LocalDecl.html [`Body.local_decls`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Body.html#structfield.local_decls -[`Field`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Field.html +[`FieldIdx`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_abi/struct.FieldIdx.html [`Place`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Place.html [`SourceScope`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.SourceScope.html [`SourceScopeData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.SourceScopeData.html diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing_new_features.md index 946637d29..01508889f 100644 --- a/src/doc/rustc-dev-guide/src/implementing_new_features.md +++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md @@ -1,4 +1,4 @@ -# Implementing new features +# Implementing new language features <!-- toc --> @@ -6,6 +6,11 @@ When you want to implement a new significant feature in the compiler, you need to go through this process to make sure everything goes smoothly. +**NOTE: this section is for *language* features, not *library* features, +which use [a different process].** + +[a different process]: ./stability.md + ## The @rfcbot FCP process When the change is small and uncontroversial, then it can be done @@ -91,31 +96,16 @@ by being unstable and unchanged for a year. To keep track of the status of an unstable feature, the experience we get while using it on nightly, and of the concerns that block its stabilization, every feature-gate -needs a tracking issue. - -General discussions about the feature should be done on -the tracking issue. +needs a tracking issue. General discussions about the feature should be done on the tracking issue. For features that have an RFC, you should use the RFC's tracking issue for the feature. For other features, you'll have to make a tracking issue for that feature. The issue title should be "Tracking issue -for YOUR FEATURE". - -For tracking issues for features (as opposed to future-compat -warnings), I don't think the description has to contain -anything specific. Generally we put the list of items required -for stabilization in a checklist, e.g., +for YOUR FEATURE". Use the ["Tracking Issue" issue template][template]. -```txt -**Steps:** - -- [ ] Implement the RFC. (CC @rust-lang/compiler -- can anyone write - up mentoring instructions?) -- [ ] Adjust the documentation. ([See instructions on rustc-dev-guide.](stabilization_guide.md#documentation-prs)) -- [ ] Stabilize the feature. ([See instructions on rustc-dev-guide.](stabilization_guide.md#stabilization-pr)) -``` +[template]: https://github.com/rust-lang/rust/issues/new?template=tracking_issue.md ## Stability in code @@ -128,14 +118,48 @@ a new unstable feature: The tracking issue should be labeled with at least `C-tracking-issue`. For a language feature, a label `F-feature_name` should be added as well. -2. Pick a name for the feature gate (for RFCs, use the name +1. Pick a name for the feature gate (for RFCs, use the name in the RFC). -3. Add a feature gate declaration to `rustc_feature/src/active.rs` in the active - `declare_features` block, and add the feature gate keyword to - `rustc_span/src/symbol.rs`. See [here][add-feature-gate] for detailed instructions. +1. Add the feature name to `rustc_span/src/symbol.rs` in the `Symbols {...}` block. + +1. Add a feature gate declaration to `rustc_feature/src/active.rs` in the active + `declare_features` block. + + ```rust ignore + /// description of feature + (active, $feature_name, "CURRENT_RUSTC_VERSION", Some($tracking_issue_number), $edition) + ``` + + where `$edition` has the type `Option<Edition>`, and is typically just `None`. If you haven't yet + opened a tracking issue (e.g. because you want initial feedback on whether the feature is likely + to be accepted), you can temporarily use `None` - but make sure to update it before the PR is + merged! + + For example: + + ```rust ignore + /// Allows defining identifiers beyond ASCII. + (active, non_ascii_idents, "CURRENT_RUSTC_VERSION", Some(55467), None), + ``` + + Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features` + lint] + by setting their type to `incomplete`: + + [`incomplete_features` lint]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#incomplete-features + + ```rust ignore + /// Allows unsized rvalues at arguments and parameters. + (incomplete, unsized_locals, "CURRENT_RUSTC_VERSION", Some(48055), None), + ``` + + To avoid [semantic merge conflicts], please use `CURRENT_RUSTC_VERSION` instead of `1.70` or + another explicit version number. + + [semantic merge conflicts]: https://bors.tech/essay/2017/02/02/pitch/ -4. Prevent usage of the new feature unless the feature gate is set. +1. Prevent usage of the new feature unless the feature gate is set. You can check it in most places in the compiler using the expression `tcx.features().$feature_name` (or `sess.features_untracked().$feature_name` if the @@ -151,18 +175,18 @@ a new unstable feature: and then finally feature-gate all the spans in [`rustc_ast_passes::feature_gate::check_crate`]. -5. Add a test to ensure the feature cannot be used without - a feature gate, by creating `feature-gate-$feature_name.rs` - and `feature-gate-$feature_name.stderr` files under the - directory where the other tests for your feature reside. +1. Add a test to ensure the feature cannot be used without + a feature gate, by creating `tests/ui/feature-gates/feature-gate-$feature_name.rs`. + You can generate the corresponding `.stderr` file by running `./x test +tests/ui/feature-gates/ --bless`. -6. Add a section to the unstable book, in +1. Add a section to the unstable book, in `src/doc/unstable-book/src/language-features/$feature_name.md`. -7. Write a lot of tests for the new feature. +1. Write a lot of tests for the new feature, preferably in `tests/ui/$feature_name/`. PRs without tests will not be accepted! -8. Get your PR reviewed and land it. You have now successfully +1. Get your PR reviewed and land it. You have now successfully implemented a feature in Rust! [`GatedSpans`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/parse/struct.GatedSpans.html @@ -172,5 +196,5 @@ a new unstable feature: [value the stability of Rust]: https://github.com/rust-lang/rfcs/blob/master/text/1122-language-semver.md [stability in code]: #stability-in-code [here]: ./stabilization_guide.md -[tracking issue]: #tracking-issue +[tracking issue]: #tracking-issues [add-feature-gate]: ./feature-gates.md#adding-a-feature-gate diff --git a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md index 8cd765011..2b1677ef4 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -199,7 +199,7 @@ statements is only implemented for LLVM, at this time. [backend-lowering-mir]: backend/lowering-mir.md [codegen-statement]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.codegen_statement [codegen-coverage]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.codegen_coverage -[function-coverage]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/coverageinfo/map/struct.FunctionCoverage.html +[function-coverage]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/map_data/struct.FunctionCoverage.html [instrprof-increment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/traits/trait.BuilderMethods.html#tymethod.instrprof_increment ### Coverage Map Generation @@ -279,8 +279,8 @@ Coverage instrumentation in the MIR is validated by a `mir-opt` test: More complete testing of end-to-end coverage instrumentation and reports are done in the `run-make-fulldeps` tests, with sample Rust programs (to be -instrumented) in the [`coverage`][coverage-test-samples] directory, and the -actual tests and expected results in [`coverage-reports`]. +instrumented) in the [`tests/run-coverage`] directory, +together with the actual tests and expected results. Finally, the [`coverage-llvmir`] test compares compiles a simple Rust program with `-C instrument-coverage` and compares the compiled program's LLVM IR to @@ -292,13 +292,12 @@ Expected results for both the `mir-opt` tests and the `coverage*` tests under `run-make-fulldeps` can be refreshed by running: ```shell -$ ./x.py test mir-opt --bless -$ ./x.py test tests/run-make-fulldeps/coverage --bless +$ ./x test mir-opt --bless +$ ./x test tests/run-make-fulldeps/coverage --bless ``` [mir-opt-test]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/instrument_coverage.rs -[coverage-test-samples]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage -[`coverage-reports`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-reports +[`tests/run-coverage`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage [spanview-debugging]: compiler-debugging.md#viewing-spanview-output [`coverage-llvmir`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-llvmir @@ -466,7 +465,7 @@ function--[`bcb_from_bb()`][bcb-from-bb]--to look up a `BasicCoverageBlock` from [graph-traits]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/index.html#traits [mir-dev-guide]: mir/index.md [compute-basic-coverage-blocks]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.compute_basic_coverage_blocks -[simplify-cfg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/simplify/struct.SimplifyCfg.html +[simplify-cfg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/simplify/enum.SimplifyCfg.html [rust-lang/rust#78544]: https://github.com/rust-lang/rust/issues/78544 [mir-debugging]: mir/debugging.md [bcb-from-bb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.bcb_from_bb diff --git a/src/doc/rustc-dev-guide/src/macro-expansion.md b/src/doc/rustc-dev-guide/src/macro-expansion.md index 7f50f7f89..f3883223d 100644 --- a/src/doc/rustc-dev-guide/src/macro-expansion.md +++ b/src/doc/rustc-dev-guide/src/macro-expansion.md @@ -48,7 +48,7 @@ iteration, this represents a compile error. Here is the [algorithm][original]: [fef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/expand/struct.MacroExpander.html#method.fully_expand_fragment [original]: https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049 -1. Initialize an `queue` of unresolved macros. +1. Initialize a `queue` of unresolved macros. 2. Repeat until `queue` is empty (or we make no progress, which is an error): 1. [Resolve](./name-resolution.md) imports in our partially built crate as much as possible. diff --git a/src/doc/rustc-dev-guide/src/mir/optimizations.md b/src/doc/rustc-dev-guide/src/mir/optimizations.md index 293d2fe91..16cf2035b 100644 --- a/src/doc/rustc-dev-guide/src/mir/optimizations.md +++ b/src/doc/rustc-dev-guide/src/mir/optimizations.md @@ -34,7 +34,7 @@ optimizes it, and returns the improved MIR. `println!`, `format!`, etc. generate a lot of MIR that can make it harder to understand what the optimization does to the test. -2. Run `./x.py test --bless tests/mir-opt/<your-test>.rs` to generate a MIR +2. Run `./x test --bless tests/mir-opt/<your-test>.rs` to generate a MIR dump. Read [this README][mir-opt-test-readme] for instructions on how to dump things. @@ -45,16 +45,16 @@ optimizes it, and returns the improved MIR. 4. Implement a new optimization in [`compiler/rustc_mir_transform/src`]. The fastest and easiest way to do this is to - 1. pick a small optimization (such as [`no_landing_pads`]) and copy it + 1. pick a small optimization (such as [`remove_storage_markers`]) and copy it to a new file, 2. add your optimization to one of the lists in the [`run_optimization_passes()`] function, 3. and then start modifying the copied optimization. -5. Rerun `./x.py test --bless tests/mir-opt/<your-test>.rs` to regenerate the +5. Rerun `./x test --bless tests/mir-opt/<your-test>.rs` to regenerate the MIR dumps. Look at the diffs to see if they are what you expect. -6. Run `./x.py test tests/ui` to see if your optimization broke anything. +6. Run `./x test tests/ui` to see if your optimization broke anything. 7. If there are issues with your optimization, experiment with it a bit and repeat steps 5 and 6. @@ -72,8 +72,7 @@ If you have any questions along the way, feel free to ask in [mir-opt-test-readme]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/README.md [`compiler/rustc_mir_transform/src`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_mir_transform/src -<!--- TODO: Change NoLandingPads. [#1232](https://github.com/rust-lang/rustc-dev-guide/issues/1232) --> -[`no_landing_pads`]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir_transform/src/no_landing_pads.rs +[`remove_storage_markers`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_mir_transform/src/remove_storage_markers.rs [`run_optimization_passes()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/fn.run_optimization_passes.html ## Defining optimization passes diff --git a/src/doc/rustc-dev-guide/src/mir/visitor.md b/src/doc/rustc-dev-guide/src/mir/visitor.md index 17186fe75..c0c703a6b 100644 --- a/src/doc/rustc-dev-guide/src/mir/visitor.md +++ b/src/doc/rustc-dev-guide/src/mir/visitor.md @@ -23,7 +23,7 @@ struct MyVisitor<...> { and you then implement the `Visitor` or `MutVisitor` trait for that type: ```rust,ignore -impl<'tcx> MutVisitor<'tcx> for NoLandingPads { +impl<'tcx> MutVisitor<'tcx> for MyVisitor { fn visit_foo(&mut self, ...) { ... self.super_foo(...); diff --git a/src/doc/rustc-dev-guide/src/name-resolution.md b/src/doc/rustc-dev-guide/src/name-resolution.md index 93c2a3eb7..fbeef19ff 100644 --- a/src/doc/rustc-dev-guide/src/name-resolution.md +++ b/src/doc/rustc-dev-guide/src/name-resolution.md @@ -117,7 +117,7 @@ fn do_something<T: Default>(val: T) { // <- New rib in both types and values (1) }; // End of (3) // `val` is accessible, `helper` variable shadows `helper` function fn helper() { // <- New rib in both types and values (4) - // `val` is not accessible here, (4) is not transparent for locals) + // `val` is not accessible here, (4) is not transparent for locals // `T` is not accessible here } // End of (4) let val = T::default(); // New rib (5) diff --git a/src/doc/rustc-dev-guide/src/notification-groups/about.md b/src/doc/rustc-dev-guide/src/notification-groups/about.md index a85c4a505..1307a50fc 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/about.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/about.md @@ -42,7 +42,7 @@ particularly those of **middle priority**: ## Joining a notification group -To join an notification group, you just have to open a PR adding your +To join a notification group, you just have to open a PR adding your Github username to the appropriate file in the Rust team repository. See the "example PRs" below to get a precise idea and to identify the file to edit. diff --git a/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md b/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md index 2e7b1766c..707334304 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md @@ -39,9 +39,9 @@ are a few: * The [rust-reduce](https://github.com/jethrogb/rust-reduce) tool can try to reduce code automatically. - * The [C-reduce](https://embed.cs.utah.edu/creduce/) tool also works + * The [C-reduce](https://github.com/csmith-project/creduce) tool also works on Rust code, though it requires that you start from a single - file. (XXX link to some post explaining how to do it?) + file. (A post explaining how to do it can be found [here](https://insaneinside.net/2017/09/12/whole-crate-bug-reduction-with-creduce.html).) * pnkfelix's [Rust Bug Minimization Patterns] blog post * This post focuses on "heavy bore" techniques, where you are starting with a large, complex cargo project that you wish to diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md index de06c742b..797f4d8e2 100644 --- a/src/doc/rustc-dev-guide/src/overview.md +++ b/src/doc/rustc-dev-guide/src/overview.md @@ -286,7 +286,7 @@ of a crate.][passes] Then the codegen backend invokes the for that function and then creates codegen units. This kind of split will need to remain to ensure that unreachable functions still have their errors emitted. -[passes]: https://github.com/rust-lang/rust/blob/45ebd5808afd3df7ba842797c0fcd4447ddf30fb/src/librustc_interface/passes.rs#L824 +[passes]: https://github.com/rust-lang/rust/blob/e69c7306e2be08939d95f14229e3f96566fb206c/compiler/rustc_interface/src/passes.rs#L791 Moreover, the compiler wasn't originally built to use a query system; the query system has been retrofitted into the compiler, so parts of it are not query-fied diff --git a/src/doc/rustc-dev-guide/src/parallel-rustc.md b/src/doc/rustc-dev-guide/src/parallel-rustc.md index e7cbbd7ee..9942f751a 100644 --- a/src/doc/rustc-dev-guide/src/parallel-rustc.md +++ b/src/doc/rustc-dev-guide/src/parallel-rustc.md @@ -44,7 +44,6 @@ are implemented differently depending on whether `parallel-compiler` is true. | MappedWriteGuard | parking_lot::MappedRwLockWriteGuard | std::cell::RefMut | | LockGuard | parking_lot::MutexGuard | std::cell::RefMut | | MappedLockGuard | parking_lot::MappedMutexGuard | std::cell::RefMut | -| MetadataRef | [`OwningRef<Box<dyn Erased + Send + Sync>, [u8]>`][OwningRef] | [`OwningRef<Box<dyn Erased>, [u8]>`][OwningRef] | - These thread-safe data structures interspersed during compilation can cause a lot of lock contention, which actually degrades performance as the @@ -164,4 +163,3 @@ are a bit out of date): [parallel-rustdoc]: https://github.com/rust-lang/rust/issues/82741 [Arc]: https://doc.rust-lang.org/std/sync/struct.Arc.html [Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html -[OwningRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/owning_ref/index.html diff --git a/src/doc/rustc-dev-guide/src/part-2-intro.md b/src/doc/rustc-dev-guide/src/part-2-intro.md index 5ea4d7b6b..aecab562b 100644 --- a/src/doc/rustc-dev-guide/src/part-2-intro.md +++ b/src/doc/rustc-dev-guide/src/part-2-intro.md @@ -1,4 +1,4 @@ -# Part 2: High-Level Compiler Architecture +# High-Level Compiler Architecture The remaining parts of this guide discuss how the compiler works. They go through everything from high-level structure of the compiler to how each stage diff --git a/src/doc/rustc-dev-guide/src/part-3-intro.md b/src/doc/rustc-dev-guide/src/part-3-intro.md index c10080632..59a1eeba7 100644 --- a/src/doc/rustc-dev-guide/src/part-3-intro.md +++ b/src/doc/rustc-dev-guide/src/part-3-intro.md @@ -1,4 +1,4 @@ -# Part 3: Source Code Representation +# Source Code Representation This part describes the process of taking raw source code from the user and transforming it into various forms that the compiler can work with easily. diff --git a/src/doc/rustc-dev-guide/src/part-4-intro.md b/src/doc/rustc-dev-guide/src/part-4-intro.md index 00a74f308..6a8433164 100644 --- a/src/doc/rustc-dev-guide/src/part-4-intro.md +++ b/src/doc/rustc-dev-guide/src/part-4-intro.md @@ -1,4 +1,4 @@ -# Part 4: Analysis +# Analysis This part discusses the many analyses that the compiler uses to check various properties of the code and to inform later stages. Typically, this is what people diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index e1666e237..df987e00a 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -19,7 +19,7 @@ Depending on what you're trying to measure, there are several different approach - If you want a nice visual representation of the compile times of your crate graph, you can use [cargo's `--timings` flag](https://doc.rust-lang.org/nightly/cargo/reference/timings.html), e.g. `cargo build --timings`. - You can use this flag on the compiler itself with `CARGOFLAGS="--timings" ./x.py build` + You can use this flag on the compiler itself with `CARGOFLAGS="--timings" ./x build` - If you want to profile memory usage, you can use various tools depending on what operating system you are using. @@ -41,11 +41,11 @@ extension in LLVM bitcode format. Example usage: ``` cargo install cargo-llvm-lines -# On a normal crate you could now run `cargo llvm-lines`, but `x.py` isn't normal :P +# On a normal crate you could now run `cargo llvm-lines`, but `x` isn't normal :P # Do a clean before every run, to not mix in the results from previous runs. -./x.py clean -env RUSTFLAGS=-Csave-temps ./x.py build --stage 0 compiler/rustc +./x clean +env RUSTFLAGS=-Csave-temps ./x build --stage 0 compiler/rustc # Single crate, e.g., rustc_middle. (Relies on the glob support of your shell.) # Convert unoptimized LLVM bitcode into a human readable LLVM assembly accepted by cargo-llvm-lines. @@ -85,7 +85,7 @@ Example output for the compiler: 326903 (0.7%) 642 (0.0%) rustc_query_system::query::plumbing::try_execute_query ``` -Since this doesn't seem to work with incremental compilation or `./x.py check`, +Since this doesn't seem to work with incremental compilation or `./x check`, you will be compiling rustc _a lot_. I recommend changing a few settings in `config.toml` to make it bearable: ``` diff --git a/src/doc/rustc-dev-guide/src/profiling/with_perf.md b/src/doc/rustc-dev-guide/src/profiling/with_perf.md index c9bd88ecd..469e237b9 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with_perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with_perf.md @@ -10,7 +10,7 @@ This is a guide for how to profile rustc with [perf](https://perf.wiki.kernel.or - `debuginfo-level = 1` - enables line debuginfo - `jemalloc = false` - lets you do memory use profiling with valgrind - leave everything else the defaults -- Run `./x.py build` to get a full build +- Run `./x build` to get a full build - Make a rustup toolchain pointing to that result - see [the "build and run" section for instructions][b-a-r] @@ -282,7 +282,7 @@ Tree What happens with `--tree-callees` is that - we find each sample matching the regular expression -- we look at the code that is occurs *after* the regex match and try +- we look at the code that occurs *after* the regex match and try to build up a call tree The `--tree-min-percent 3` option says "only show me things that take diff --git a/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md b/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md index e7cf9418c..a800c5717 100644 --- a/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md @@ -47,11 +47,11 @@ we'll need to build a stage 1 compiler and then a stage 2 compiler ourselves. To do this, make sure you have set `debuginfo-level = 1` in your `config.toml` file. This tells rustc to generate debug information which includes stack frames when bootstrapping. -Now you can build the stage 1 compiler: `python x.py build --stage 1 -i library` or however +Now you can build the stage 1 compiler: `x build --stage 1 -i library` or however else you want to build the stage 1 compiler. Now that the stage 1 compiler is built, we can record the stage 2 build. Go back to WPR, click the -"start" button and build the stage 2 compiler (e.g., `python x build --stage=2 -i library`). +"start" button and build the stage 2 compiler (e.g., `x build --stage=2 -i library`). When this process finishes, stop the recording. Click the Save button and once that process is complete, click the "Open in WPA" button which diff --git a/src/doc/rustc-dev-guide/src/query.md b/src/doc/rustc-dev-guide/src/query.md index 5dbffac8d..782c5b4b3 100644 --- a/src/doc/rustc-dev-guide/src/query.md +++ b/src/doc/rustc-dev-guide/src/query.md @@ -103,7 +103,7 @@ When the tcx is created, it is given the providers by its creator using the [`Providers`][providers_struct] struct. This struct is generated by the macros here, but it is basically a big list of function pointers: -[providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/query/struct.Providers.html +[providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/struct.Providers.html ```rust,ignore struct Providers { diff --git a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md new file mode 100644 index 000000000..2ad9494e8 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md @@ -0,0 +1,419 @@ +# Return Position Impl Trait In Trait + +Return-position impl trait in trait (RPITIT) is conceptually (and as of +[#112988], literally) sugar that turns RPITs in trait methods into +generic associated types (GATs) without the user having to define that +GAT either on the trait side or impl side. + +RPITIT was originally implemented in [#101224], which added support for +async fn in trait (AFIT), since the implementation for RPITIT came for +free as a part of implementing AFIT which had been RFC'd previously. It +was then RFC'd independently in [RFC 3425], which was recently approved +by T-lang. + +## How does it work? + +This doc is ordered mostly via the compilation pipeline. AST -> HIR -> +astconv -> typeck. + +### AST and HIR + +AST -> HIR lowering for RPITITs is almost the same as lowering RPITs. We +still lower them as +[`hir::ItemKind::OpaqueTy`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.OpaqueTy.html). +The two differences are that: + +We record `in_trait` for the opaque. This will signify that the opaque +is an RPITIT for astconv, diagnostics that deal with HIR, etc. + +We record `lifetime_mapping`s for the opaque type, described below. + +#### Aside: Opaque lifetime duplication + +*All opaques* (not just RPITITs) end up duplicating their captured +lifetimes into new lifetime parameters local to the opaque. The main +reason we do this is because RPITs need to be able to "reify"[^1] any +captured late-bound arguments, or make them into early-bound ones. This +is so they can be used as substs for the opaque, and later to +instantiate hidden types. Since we don't know which lifetimes are early- +or late-bound during AST lowering, we just do this for all lifetimes. + +[^1]: This is compiler-errors terminology, I'm not claiming it's accurate :^) + +The main addition for RPITITs is that during lowering we track the +relationship between the captured lifetimes and the corresponding +duplicated lifetimes in an additional field, +[`OpaqueTy::lifetime_mapping`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.OpaqueTy.html#structfield.lifetime_mapping). +We use this lifetime mapping later on in `predicates_of` to install +bounds that enforce equality between these duplicated lifetimes and +their source lifetimes in order to properly typecheck these GATs, which +will be discussed below. + +##### note: + +It may be better if we were able to lower without duplicates and for +that I think we would need to stop distinguishing between early and late +bound lifetimes. So we would need a solution like [Account for +late-bound lifetimes in generics +#103448](https://github.com/rust-lang/rust/pull/103448) and then also a +PR similar to [Inherit function lifetimes for impl-trait +#103449](https://github.com/rust-lang/rust/pull/103449). + +### Astconv + +The main change to astconv is that we lower `hir::TyKind::OpaqueDef` for +an RPITIT to a projection instead of an opaque, using a newly +synthesized def-id for a new associated type in the trait. We'll +describe how exactly we get this def-id in the next section. + +This means that any time we call `ast_ty_to_ty` on the RPITIT, we end up +getting a projection back instead of an opaque. This projection can then +be normalized to the right value -- either the original opaque if we're +in the trait, or the inferred type of the RPITIT if we're in an impl. + +#### Lowering to synthetic associated types + +Using query feeding, we synthesize new associated types on both the +trait side and impl side for RPITITs that show up in methods. + +##### Lowering RPITITs in traits + +When `tcx.associated_item_def_ids(trait_def_id)` is called on a trait to +gather all of the trait's associated types, the query previously just +returned the def-ids of the HIR items that are children of the trait. +After [#112988], additionally, for each method in the trait, we add the +def-ids returned by +`tcx.associated_types_for_impl_traits_in_associated_fn(trait_method_def_id)`, +which walks through each trait method, gathers any RPITITs that show up +in the signature, and then calls +`associated_type_for_impl_trait_in_trait` for each RPITIT, which +synthesizes a new associated type. + +##### Lowering RPITITs in impls + +Similarly, along with the impl's HIR items, for each impl method, we +additionally add all of the +`associated_types_for_impl_traits_in_associated_fn` for the impl method. +This calls `associated_type_for_impl_trait_in_impl`, which will +synthesize an associated type definition for each RPITIT that comes from +the corresponding trait method. + +#### Synthesizing new associated types + +We use query feeding +([`TyCtxtAt::create_def`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/plumbing/struct.TyCtxtAt.html#method.create_def)) +to synthesize a new def-id for the synthetic GATs for each RPITIT. + +Locally, most of rustc's queries match on the HIR of an item to compute +their values. Since the RPITIT doesn't really have HIR associated with +it, or at least not HIR that corresponds to an associated type, we must +compute many queries eagerly and +[feed](https://github.com/rust-lang/rust/pull/104940) them, like +`opt_def_kind`, `associated_item`, `visibility`, and`defaultness`. + +The values for most of these queries is obvious, since the RPITIT +conceptually inherits most of its information from the parent function +(e.g. `visibility`), or because it's trivially knowable because it's an +associated type (`opt_def_kind`). + +Some other queries are more involved, or cannot be feeded, and we +document the interesting ones of those below: + +##### `generics_of` for the trait + +The GAT for an RPITIT conceptually inherits the same generics as the +RPIT it comes from. However, instead of having the method as the +generics' parent, the trait is the parent. + +Currently we get away with taking the RPIT's generics and method +generics and flattening them both into a new generics list, preserving +the def-id of each of the parameters. (This may cause issues with +def-ids having the wrong parents, but in the worst case this will cause +diagnostics issues. If this ends up being an issue, we can synthesize +new def-ids for generic params whose parent is the GAT.) + +<details> +<summary> <b>An illustrated example</b> </summary> + +```rust +trait Foo { + fn method<'early: 'early, 'late, T>() -> impl Sized + Captures<'early, 'late>; +} +``` + +Would desugar to... +```rust +trait Foo { + // vvvvvvvvv method's generics + // vvvvvvvvvvvvvvvvvvvvvvvv opaque's generics + type Gat<'early, T, 'early_duplicated, 'late>: Sized + Captures<'early_duplicated, 'late>; + + fn method<'early: 'early, 'late, T>() -> Self::Gat<'early, T, 'early, 'late>; +} +``` +</details> + +##### `generics_of` for the impl + +The generics for an impl's GAT are a bit more interesting. They are +composed of RPITIT's own generics (from the trait definition), appended +onto the impl's methods generics. This has the same issue as above, +where the generics for the GAT have parameters whose def-ids have the +wrong parent, but this should only cause issues in diagnostics. + +We could fix this similarly if we were to synthesize new generics +def-ids, but this can be done later in a forwards-compatible way, +perhaps by a interested new contributor. + +##### `opt_rpitit_info` + +Some queries rely on computing information that would result in cycles +if we were to feed them eagerly, like `explicit_predicates_of`. +Therefore we defer to the `predicates_of` provider to return the right +value for our RPITIT's GAT. We do this by detecting early on in the +query if the associated type is synthetic by using +[`opt_rpitit_info`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.opt_rpitit_info), +which returns `Some` if the associated type is synthetic. + +Then, during a query like `explicit_predicates_of`, we can detect if an +associated type is synthetic like: + +```rust +fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ... { + if let Some(rpitit_info) = tcx.opt_rpitit_info(def_id) { + // Do something special for RPITITs... + return ...; + } + + // The regular computation which relies on access to the HIR of `def_id`. +} +``` + +##### `explicit_predicates_of` + +RPITITs begin by copying the predicates of the method that defined it, +both on the trait and impl side. + +Additionally, we install "bidirectional outlives" predicates. +Specifically, we add region-outlives predicates in both directions for +each captured early-bound lifetime that constrains it to be equal to the +duplicated early-bound lifetime that results from lowering. This is best +illustrated in an example: + +```rust +trait Foo<'a> { + fn bar() -> impl Sized + 'a; +} + +// Desugars into... + +trait Foo<'a> { + type Gat<'a_duplicated>: Sized + 'a + where + 'a: 'a_duplicated, + 'a_duplicated: 'a; + //~^ Specifically, we should be able to assume that the + // duplicated `'a_duplicated` lifetime always stays in + // sync with the `'a` lifetime. + + fn bar() -> Self::Gat<'a>; +} +``` + +##### `assumed_wf_types` + +The GATs in both the trait and impl inherit the `assumed_wf_types` of +the trait method that defines the RPITIT. This is to make sure that the +following code is well formed when lowered. + +```rust +trait Foo { + fn iter<'a, T>(x: &'a [T]) -> impl Iterator<Item = &'a T>; +} + +// which is lowered to... + +trait FooDesugared { + type Iter<'a, T>: Iterator<Item = &'a T>; + //~^ assumed wf: `&'a [T]` + // Without assumed wf types, the GAT would not be well-formed on its own. + + fn iter<'a, T>(x: &'a [T]) -> Self::Iter<'a, T>; +} +``` + +Because `assumed_wf_types` is only defined for local def ids, in order +to properly implement `assumed_wf_types` for impls of foreign traits +with RPITs, we need to encode the assumed wf types of RPITITs in an +extern query +[`assumed_wf_types_for_rpitit`](https://github.com/rust-lang/rust/blob/a17c7968b727d8413801961fc4e89869b6ab00d3/compiler/rustc_ty_utils/src/implied_bounds.rs#L14). + +### Typechecking + +#### The RPITIT inference algorithm + +The RPITIT inference algorithm is implemented in +[`collect_return_position_impl_trait_in_trait_tys`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.collect_return_position_impl_trait_in_trait_tys.html). + +**High-level:** Given a impl method and a trait method, we take the +trait method and instantiate each RPITIT in the signature with an infer +var. We then equate this trait method signature with the impl method +signature, and process all obligations that fall out in order to infer +the type of all of the RPITITs in the method. + +The method is also responsible for making sure that the hidden types for +each RPITIT actually satisfy the bounds of the `impl Trait`, i.e. that +if we infer `impl Trait = Foo`, that `Foo: Trait` holds. + +<details> + <summary><b>An example...</b></summary> + +```rust +#![feature(return_position_impl_trait_in_trait)] + +use std::ops::Deref; + +trait Foo { + fn bar() -> impl Deref<Target = impl Sized>; + // ^- RPITIT ?0 ^- RPITIT ?1 +} + +impl Foo for () { + fn bar() -> Box<String> { Box::new(String::new()) } +} +``` + +We end up with the trait signature that looks like `fn() -> ?0`, and +nested obligations `?0: Deref<Target = ?1>`, `?1: Sized`. The impl +signature is `fn() -> Box<String>`. + +Equating these signatures gives us `?0 = Box<String>`, which then after +processing the obligation `Box<String>: Deref<Target = ?1>` gives us `?1 += String`, and the other obligation `String: Sized` evaluates to true. + +By the end of the algorithm, we end up with a mapping between associated +type def-ids to concrete types inferred from the signature. We can then +use this mapping to implement `type_of` for the synthetic associated +types in the impl, since this mapping describes the type that should +come after the `=` in `type Assoc = ...` for each RPITIT. +</details> + +#### Default trait body + +Type-checking a default trait body, like: + +```rust +trait Foo { + fn bar() -> impl Sized { + 1i32 + } +} +``` + +requires one interesting hack. We need to install a projection predicate +into the param-env of `Foo::bar` allowing us to assume that the RPITIT's +GAT normalizes to the RPITIT's opaque type. This relies on the +observation that a trait method and RPITIT's GAT will always be "in +sync". That is, one will only ever be overridden if the other one is as +well. + +Compare this to a similar desugaring of the code above, which would fail +because we cannot rely on this same assumption: + +```rust +#![feature(impl_trait_in_assoc_type)] +#![feature(associated_type_defaults)] + +trait Foo { + type RPITIT = impl Sized; + + fn bar() -> Self::RPITIT { + 01i32 + } +} +``` + +Failing because a down-stream impl could theoretically provide an +implementation for `RPITIT` without providing an implementation of +`foo`: + +```text +error[E0308]: mismatched types +--> src/lib.rs:8:9 + | +5 | type RPITIT = impl Sized; + | ------------------------- associated type defaults can't be assumed inside the trait defining them +6 | +7 | fn bar() -> Self::RPITIT { + | ------------ expected `<Self as Foo>::RPITIT` because of return type +8 | 01i32 + | ^^^^^ expected associated type, found `i32` + | + = note: expected associated type `<Self as Foo>::RPITIT` + found type `i32` +``` + +#### Well-formedness checking + +We check well-formedness of RPITITs just like regular associated types. + +Since we added lifetime bounds in `predicates_of` that link the +duplicated early-bound lifetimes to their original lifetimes, and we +implemented `assumed_wf_types` which inherits the WF types of the method +from which the RPITIT originates ([#113704]), we have no issues +WF-checking the GAT as if it were a regular GAT. + +### What's broken, what's weird, etc. + +##### Specialization is super busted + +The "default trait methods" described above does not interact well with +specialization, because we only install those projection bounds in trait +default methods, and not in impl methods. Given that specialization is +already pretty busted, I won't go into detail, but it's currently a bug +tracked in: + * `tests/ui/impl-trait/in-trait/specialization-broken.rs` + +##### Projections don't have variances + +This code fails because projections don't have variances: +```rust +#![feature(return_position_impl_trait_in_trait)] + +trait Foo { + // Note that the RPITIT below does *not* capture `'lt`. + fn bar<'lt: 'lt>() -> impl Eq; +} + +fn test<'a, 'b, T: Foo>() -> bool { + <T as Foo>::bar::<'a>() == <T as Foo>::bar::<'b>() + //~^ ERROR + // (requires that `'a == 'b`) +} +``` + +This is because we can't relate `<T as Foo>::Rpitit<'a>` and `<T as +Foo>::Rpitit<'b>`, even if they don't capture their lifetime. If we were +using regular opaque types, this would work, because they would be +bivariant in that lifetime parameter: +```rust +#![feature(return_position_impl_trait_in_trait)] + +fn bar<'lt: 'lt>() -> impl Eq { + () +} + +fn test<'a, 'b>() -> bool { + bar::<'a>() == bar::<'b>() +} +``` + +This is probably okay though, since RPITITs will likely have their +captures behavior changed to capture all in-scope lifetimes anyways. +This could also be relaxed later in a forwards-compatible way if we were +to consider variances of RPITITs when relating projections. + +[#112988]: https://github.com/rust-lang/rust/pull/112988 +[RFC 3425]: https://github.com/rust-lang/rfcs/pull/3425 +[#101224]: https://github.com/rust-lang/rust/pull/101224 +[#113704]: https://github.com/rust-lang/rust/pull/113704 diff --git a/src/doc/rustc-dev-guide/src/rustc-driver.md b/src/doc/rustc-dev-guide/src/rustc-driver.md index 192811da1..bae98c746 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver.md @@ -32,7 +32,7 @@ as well as allowing some custom code run after different phases of the compilati [cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html -[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html +[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver_impl/fn.run_compiler.html [i_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/fn.run_compiler.html [example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-example.rs [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index d58c2d280..e78c4bb25 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -173,6 +173,8 @@ running the Markdown parser. There's also a function in here (`find_testable_code`) that specifically scans for Rust code blocks so the test-runner code can find all the doctests in the crate. +[Askama]: https://docs.rs/askama/latest/askama/ + ### From soup to nuts (alternate title: ["An unbroken thread that stretches from those first `Cell`s @@ -279,7 +281,7 @@ server. To test these features locally, you can run a local HTTP server, like this: ```bash -$ ./x.py doc library +$ ./x doc library # The documentation has been generated into `build/[YOUR ARCH]/doc`. $ python3 -m http.server -d build/[YOUR ARCH]/doc ``` diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index cbe5e8b1f..02da8be81 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -41,24 +41,24 @@ does is call the `main()` that's in this crate's `lib.rs`, though.) ## Cheat sheet -* Run `./x.py setup tools` before getting started. This will configure `x.py` +* Run `./x setup tools` before getting started. This will configure `x` with nice settings for developing rustdoc and other tools, including downloading a copy of rustc rather than building it. -* Use `./x.py check src/tools/rustdoc` to quickly check for compile errors. -* Use `./x.py build` to make a usable +* Use `./x check src/tools/rustdoc` to quickly check for compile errors. +* Use `./x build` to make a usable rustdoc you can run on other projects. * Add `library/test` to be able to use `rustdoc --test`. * Run `rustup toolchain link stage2 build/host/stage2` to add a custom toolchain called `stage2` to your rustup environment. After running that, `cargo +stage2 doc` in any directory will build with your locally-compiled rustdoc. -* Use `./x.py doc library` to use this rustdoc to generate the +* Use `./x doc library` to use this rustdoc to generate the standard library docs. * The completed docs will be available in `build/host/doc` (under `core`, `alloc`, and `std`). * If you want to copy those docs to a webserver, copy all of `build/host/doc`, since that's where the CSS, JS, fonts, and landing page are. -* Use `./x.py test tests/rustdoc*` to run the tests using a stage1 +* Use `./x test tests/rustdoc*` to run the tests using a stage1 rustdoc. * See [Rustdoc internals] for more information about tests. diff --git a/src/doc/rustc-dev-guide/src/salsa.md b/src/doc/rustc-dev-guide/src/salsa.md index 66f9d7479..47442ae14 100644 --- a/src/doc/rustc-dev-guide/src/salsa.md +++ b/src/doc/rustc-dev-guide/src/salsa.md @@ -148,9 +148,9 @@ this one depends on by specifying them as supertraits, as seen in the following example: ```rust,ignore -/// This query group is going to contain queries that depend on derived values a +/// This query group is going to contain queries that depend on derived values. A /// query group can access another query group's queries by specifying the -/// dependency as a super trait query groups can be stacked as much as needed using +/// dependency as a super trait. Query groups can be stacked as much as needed using /// that pattern. #[salsa::query_group(ParserStorage)] pub trait Parser: Inputs { @@ -168,7 +168,7 @@ belongs to, in addition to the other keys. ```rust,ignore ///This is going to be the definition of the `ast` query in the `Parser` trait. ///So, when the query `ast` is invoked, and it needs to be recomputed, Salsa is going to call this function -///and it's is going to give it the database as `impl Parser`. +///and it's going to give it the database as `impl Parser`. ///The function doesn't need to be aware of all the queries of all the query groups fn ast(db: &impl Parser, name: String) -> String { //! Note, `impl Parser` is used here but `dyn Parser` works just as well diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index 21b07ec99..27d40a11a 100644 --- a/src/doc/rustc-dev-guide/src/sanitizers.md +++ b/src/doc/rustc-dev-guide/src/sanitizers.md @@ -98,7 +98,7 @@ To enable a sanitizer on a new target which is already supported by LLVM: 2. [Build the runtime for the target and include it in the libdir.][sanitizer-targets] 3. [Teach compiletest that your target now supports the sanitizer.][compiletest-definition] Tests marked with `needs-sanitizer-*` should now run on the target. -4. Run tests `./x.py test --force-rerun tests/ui/sanitize/` to verify. +4. Run tests `./x test --force-rerun tests/ui/sanitize/` to verify. 5. [--enable-sanitizers in the CI configuration][ci-configuration] to build and distribute the sanitizer runtime as part of the release process. diff --git a/src/doc/rustc-dev-guide/src/serialization.md b/src/doc/rustc-dev-guide/src/serialization.md index 691d21bc2..78b065311 100644 --- a/src/doc/rustc-dev-guide/src/serialization.md +++ b/src/doc/rustc-dev-guide/src/serialization.md @@ -109,7 +109,7 @@ and `Encodable`. only allow decoding by [`rustc_metadata::rmeta::encoder::EncodeContext`] and [`rustc_metadata::rmeta::decoder::DecodeContext`]. These are used for types that contain `rustc_metadata::rmeta::Lazy`. -- `TyEncodable` and `TyDecoder` generate implementation that apply to any +- `TyEncodable` and `TyDecodable` generate implementation that apply to any `TyEncoder` or `TyDecoder`. These should be used for types that are only serialized in crate metadata and/or the incremental cache, which is most serializable types in `rustc_middle`. @@ -130,7 +130,7 @@ some deserialization needs to be deferred from the initial loading of metadata. The [`LazyValue<T>`] type wraps the (relative) offset in the crate metadata where a `T` has been serialized. There are also some variants, [`LazyArray<T>`] and [`LazyTable<I, T>`]. -The `Lazy<[T]>` and `LazyTable<I, T>` type provide some functionality over +The `Lazy<[T]>` and `LazyTable<I, T>` types provide some functionality over `Lazy<Vec<T>>` and `Lazy<HashMap<I, T>>`: - It's possible to encode a `LazyArray<T>` directly from an iterator, without diff --git a/src/doc/rustc-dev-guide/src/solve/normalization.md b/src/doc/rustc-dev-guide/src/solve/normalization.md new file mode 100644 index 000000000..653c976a4 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/solve/normalization.md @@ -0,0 +1,80 @@ +# Normalization in the new solver + +With the new solver we've made some fairly significant changes to normalization when compared +to the existing implementation. + +We now differentiate between "shallow normalization" and "deep normalization". +"Shallow normalization" normalizes a type until it is no-longer a potentially normalizeable alias; +it does not recurse into the type. "deep normalization" replaces all normalizeable aliases in a +type with its underlying type. + +The old trait solver currently always deeply normalizes via `Projection` obligations. +This is the only way to normalize in the old solver. By replacing projections with a new +inference variable and then emitting `Projection(<T as Trait>::Assoc, ?new_infer)` the old +solver successfully deeply normalizes even in the case of ambiguity. This approach does not +work for projections referencing bound variables. + +## Inside of the trait solver + +Normalization in the new solver exclusively happens via `Projection`[^0] goals. +This only succeeds by first normalizing the alias by one level and then equating +it with the expected type. This differs from [the behavior of projection clauses] +which can also be proven by successfully equating the projection without normalizating. +This means that `Projection`[^0] goals must only be used in places where we +*have to normalize* to make progress. To normalize `<T as Trait>::Assoc`, we first create +a fresh inference variable `?normalized` and then prove +`Projection(<T as Trait>::Assoc, ?normalized)`[^0]. `?normalized` is then constrained to +the underlying type. + +Inside of the trait solver we never deeply normalize. we only apply shallow normalization +in [`assemble_candidates_after_normalizing_self_ty`] and inside for [`AliasRelate`] +goals for the [`normalizes-to` candidates]. + +## Outside of the trait solver + +The core type system - relating types and trait solving - will not need deep +normalization with the new solver. There are still some areas which depend on it. +For these areas there is the function `At::deeply_normalize`. Without additional +trait solver support deep normalization does not always work in case of ambiguity. +Luckily deep normalization is currently only necessary in places where there is no ambiguity. +`At::deeply_normalize` immediately fails if there's ambiguity. + +If we only care about the outermost layer of types, we instead use +`At::structurally_normalize` or `FnCtxt::(try_)structurally_resolve_type`. +Unlike `At::deeply_normalize`, shallow normalization is also used in cases where we +have to handle ambiguity. `At::structurally_normalize` normalizes until the self type +is either rigid or an inference variable and we're stuck with ambiguity. This means +that the self type may not be fully normalized after `At::structurally_normalize` was called. + +Because this may result in behavior changes depending on how the trait solver handles +ambiguity, it is safer to also require full normalization there. This happens in +`FnCtxt::structurally_resolve_type` which always emits a hard error if the self type ends +up as an inference variable. There are some existing places which have a fallback for +inference variables instead. These places use `try_structurally_resolve_type` instead. + +## Why deep normalization with ambiguity is hard + +Fully correct deep normalization is very challenging, especially with the new solver +given that we do not want to deeply normalize inside of the solver. Mostly deeply normalizing +but sometimes failing to do so is bound to cause very hard to minimize and understand bugs. +If possible, avoiding any reliance on deep normalization entirely therefore feels preferable. + +If the solver itself does not deeply normalize, any inference constraints returned by the +solver would require normalization. Handling this correctly is ugly. This also means that +we change goals we provide to the trait solver by "normalizing away" some projections. + +The way we (mostly) guarantee deep normalization with the old solver is by eagerly replacing +the projection with an inference variable and emitting a nested `Projection` goal. This works +as `Projection` goals in the old solver deeply normalize. Unless we add another `PredicateKind` +for deep normalization to the new solver we cannot emulate this behavior. This does not work +for projections with bound variables, sometimes leaving them unnormalized. An approach which +also supports projections with bound variables will be even more involved. + + +[`assemble_candidates_after_normalizing_self_ty`]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/assembly/mod.rs#L330-L378 +[`AliasRelate`]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/alias_relate.rs#L16-L102 +[`normalizes-to` candidates]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/alias_relate.rs#L105-L151 +[the behavior of projection clauses]: https://github.com/rust-lang/trait-system-refactor-initiative/issues/1 +[normalize-via-infer]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/assembly/mod.rs#L350-L358 + +[^0]: TODO: currently refactoring this to use `NormalizesTo` predicates instead.
\ No newline at end of file diff --git a/src/doc/rustc-dev-guide/src/solve/trait-solving.md b/src/doc/rustc-dev-guide/src/solve/trait-solving.md index b0cd9af6c..c3089f4a8 100644 --- a/src/doc/rustc-dev-guide/src/solve/trait-solving.md +++ b/src/doc/rustc-dev-guide/src/solve/trait-solving.md @@ -97,7 +97,7 @@ all free regions during codegen we must not rely on them during typeck. A notewo is special behavior for `'static`. We also have to be careful with relying on equality of regions in the trait solver. -This is fine for codegen, as we treat all erased regions are equal. We can however +This is fine for codegen, as we treat all erased regions as equal. We can however lose equality information from HIR to MIR typeck. ### 7. Removing ambiguity makes strictly more things compile @@ -111,8 +111,8 @@ Two types being equal in the type system must mean that they have the same `Type [solve]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/index.html -[`Goal`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/struct.Goal.html +[`Goal`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/solve/struct.Goal.html [`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html [`Candidate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/assembly/struct.Candidate.html [`CandidateSource`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/assembly/enum.CandidateSource.html -[`CanonicalResponse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/type.CanonicalResponse.html +[`CanonicalResponse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/solve/type.CanonicalResponse.html diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md index 85c75fadb..bf82d8517 100644 --- a/src/doc/rustc-dev-guide/src/stability.md +++ b/src/doc/rustc-dev-guide/src/stability.md @@ -1,12 +1,12 @@ # Stability attributes -<!-- toc --> - This section is about the stability attributes and schemes that allow stable APIs to use unstable APIs internally in the rustc standard library. -For instructions on stabilizing a language feature see [Stabilizing -Features](./stabilization_guide.md). +**NOTE**: this section is for *library* features, not *language* features. For instructions on +stabilizing a language feature see [Stabilizing Features](./stabilization_guide.md). + +<!-- toc --> ## unstable diff --git a/src/doc/rustc-dev-guide/src/stabilization_guide.md b/src/doc/rustc-dev-guide/src/stabilization_guide.md index 0ac19293b..001ed25a5 100644 --- a/src/doc/rustc-dev-guide/src/stabilization_guide.md +++ b/src/doc/rustc-dev-guide/src/stabilization_guide.md @@ -1,6 +1,6 @@ # Request for stabilization -**NOTE**: this page is about stabilizing language features. +**NOTE**: this page is about stabilizing *language* features. For stabilizing *library* features, see [Stabilizing a library feature]. [Stabilizing a library feature]: ./stability.md#stabilizing-a-library-feature diff --git a/src/doc/rustc-dev-guide/src/tests/adding.md b/src/doc/rustc-dev-guide/src/tests/adding.md index 632614539..fc0c4937e 100644 --- a/src/doc/rustc-dev-guide/src/tests/adding.md +++ b/src/doc/rustc-dev-guide/src/tests/adding.md @@ -84,7 +84,7 @@ The next step is to create the expected output from the compiler. This can be done with the `--bless` option: ```sh -./x.py test tests/ui/async-await/await-without-async.rs --bless +./x test tests/ui/async-await/await-without-async.rs --bless ``` This will build the compiler (if it hasn't already been built), compile the @@ -118,7 +118,7 @@ annotations](ui.md#error-annotations) section). Save that, and run the test again: ```sh -./x.py test tests/ui/async-await/await-without-async.rs +./x test tests/ui/async-await/await-without-async.rs ``` It should now pass, yay! @@ -166,7 +166,7 @@ The final step before posting a PR is to check if you have affected anything els Running the UI suite is usually a good start: ```sh -./x.py test tests/ui +./x test tests/ui ``` If other tests start failing, you may need to investigate what has changed diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index cca4973cb..bfdc2a45a 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -6,7 +6,7 @@ When a Pull Request is opened on GitHub, [GitHub Actions] will automatically launch a build that will run all tests on some configurations (x86_64-gnu-llvm-13 linux, x86_64-gnu-tools linux, and mingw-check linux). -In essence, each runs `./x.py test` with various different options. +In essence, each runs `./x test` with various different options. The integration bot [bors] is used for coordinating merges to the master branch. When a PR is approved, it goes into a [queue] where merges are tested one at a @@ -54,8 +54,8 @@ the other jobs. The comment at the top of `ci.yml` will tell you to run this command: ```sh -./x.py run src/tools/expand-yaml-anchors -```` +./x run src/tools/expand-yaml-anchors +``` This will generate the true [`.github/workflows/ci.yml`] which is what GitHub Actions uses. diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index d4730c5b4..86ebe3a49 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -330,7 +330,7 @@ set a baseline for optimizations: The test should be annotated with `// EMIT_MIR` comments that specify files that will contain the expected MIR output. -You can use `x.py test --bless` to create the initial expected files. +You can use `x test --bless` to create the initial expected files. There are several forms the `EMIT_MIR` comment can take: @@ -380,7 +380,7 @@ There is a [`tools.mk`] Makefile which you can include which provides a bunch of utilities to make it easier to run commands and compare outputs. Take a look at some of the other tests for some examples on how to get started. -[`tools.mk`]: https://github.com/rust-lang/rust/blob/master/tests/run-make-fulldeps/tools.mk +[`tools.mk`]: https://github.com/rust-lang/rust/blob/master/tests/run-make/tools.mk [`tests/run-make`]: https://github.com/rust-lang/rust/tree/master/tests/run-make @@ -452,7 +452,7 @@ compiler, and `no-prefer-dynamic` is needed to tell compiletest to not use `prefer-dynamic` which is not compatible with proc-macros. The `#![crate_type]` attribute is needed to specify the correct crate-type. -Then in your test, you can build with with `aux-build`: +Then in your test, you can build with `aux-build`: ```rust,ignore // aux-build: my-proc-macro.rs @@ -503,10 +503,9 @@ currently only apply to the test as a whole, not to particular revisions. The only headers that are intended to really work when customized to a revision are error patterns and compiler flags. - ## Compare modes -Compiletest can be run in different modes, called *compare modes*, which can +Compiletest can be run in different modes, called _compare modes_, which can be used to compare the behavior of all tests with different compiler flags enabled. This can help highlight what differences might appear with certain flags, and @@ -516,7 +515,7 @@ To run the tests in a different mode, you need to pass the `--compare-mode` CLI flag: ```bash -./x.py test tests/ui --compare-mode=chalk +./x test tests/ui --compare-mode=chalk ``` The possible compare modes are: @@ -537,5 +536,5 @@ following settings: enabling split-DWARF. Note that compare modes are separate to [revisions](#revisions). -All revisions are tested when running `./x.py test tests/ui`, however +All revisions are tested when running `./x test tests/ui`, however compare-modes must be manually run individually via the `--compare-mode` flag. diff --git a/src/doc/rustc-dev-guide/src/tests/docker.md b/src/doc/rustc-dev-guide/src/tests/docker.md index 0d9e0a492..31e3825f5 100644 --- a/src/doc/rustc-dev-guide/src/tests/docker.md +++ b/src/doc/rustc-dev-guide/src/tests/docker.md @@ -21,7 +21,7 @@ directory. From there, you can run `../src/ci/run.sh` which will run the build as defined by the image. Alternatively, you can run individual commands to do specific tasks. For -example, you can run `python3 ../x.py test tests/ui` to just run UI tests. +example, you can run `../x test tests/ui` to just run UI tests. Note that there is some configuration in the [`src/ci/run.sh`] script that you may need to recreate. Particularly, set `submodules = false` in your `config.toml` so that it doesn't attempt to modify the read-only directory. diff --git a/src/doc/rustc-dev-guide/src/tests/headers.md b/src/doc/rustc-dev-guide/src/tests/headers.md index 682c96b44..f066dbbb5 100644 --- a/src/doc/rustc-dev-guide/src/tests/headers.md +++ b/src/doc/rustc-dev-guide/src/tests/headers.md @@ -28,7 +28,7 @@ Header commands can be standalone (like `// run-pass`) or take a value (like ## Header commands The following is a list of header commands. -Commands are linked to sections the describe the command in more detail if available. +Commands are linked to sections that describe the command in more detail if available. This list may not be exhaustive. Header commands can generally be found by browsing the `TestProps` structure found in [`header.rs`] from the compiletest source. @@ -70,7 +70,6 @@ found in [`header.rs`] from the compiletest source. * `min-llvm-versionX` * `min-system-llvm-version` * `ignore-llvm-version` - * `ignore-llvm-version` * [Environment variable headers](#environment-variable-headers) * `rustc-env` * `exec-env` @@ -145,7 +144,7 @@ The following header commands will check rustc build settings and target setting (AddressSanitizer, hardware-assisted AddressSanitizer, LeakSanitizer, MemorySanitizer or ThreadSanitizer respectively) * `needs-run-enabled` — ignores if it is a test that gets executed, and - running has been disabled. Running tests can be disabled with the `x.py test + running has been disabled. Running tests can be disabled with the `x test --run=never` flag, or running on fuchsia. * `needs-unwind` — ignores if the target does not support unwinding * `needs-rust-lld` — ignores if the rust lld support is not enabled diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md index adc5d58ec..647d1fbea 100644 --- a/src/doc/rustc-dev-guide/src/tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/intro.md @@ -3,14 +3,14 @@ <!-- toc --> The Rust project runs a wide variety of different tests, orchestrated by -the build system (`./x.py test`). +the build system (`./x test`). This section gives a brief overview of the different testing tools. Subsequent chapters dive into [running tests](running.md) and [adding new tests](adding.md). ## Kinds of tests There are several kinds of tests to exercise things in the Rust distribution. -Almost all of them are driven by `./x.py test`, with some exceptions noted below. +Almost all of them are driven by `./x test`, with some exceptions noted below. ### Compiletest @@ -19,7 +19,7 @@ It supports running different styles of tests, called *test suites*. The tests are all located in the [`tests`] directory. The [Compiletest chapter][compiletest] goes into detail on how to use this tool. -> Example: `./x.py test tests/ui` +> Example: `./x test tests/ui` [compiletest]: compiletest.md [`tests`]: https://github.com/rust-lang/rust/tree/master/tests @@ -29,23 +29,23 @@ The [Compiletest chapter][compiletest] goes into detail on how to use this tool. The standard library and many of the compiler packages include typical Rust `#[test]` unit tests, integration tests, and documentation tests. You can pass a path to `x.py` to almost any package in the `library` or `compiler` directory, -and `x.py` will essentially run `cargo test` on that package. +and `x` will essentially run `cargo test` on that package. Examples: -| Command | Description | -|---------|-------------| -| `./x.py test library/std` | Runs tests on `std` only | -| `./x.py test library/core` | Runs tests on `core` only | -| `./x.py test compiler/rustc_data_structures` | Runs tests on `rustc_data_structures` | +| Command | Description | +| ----------------------------------------- | ------------------------------------- | +| `./x test library/std` | Runs tests on `std` only | +| `./x test library/core` | Runs tests on `core` only | +| `./x test compiler/rustc_data_structures` | Runs tests on `rustc_data_structures` | The standard library relies very heavily on documentation tests to cover its functionality. However, unit tests and integration tests can also be used as needed. Almost all of the compiler packages have doctests disabled. -The standard library and compiler always place all unit tests in a separate `tests` file -(this is enforced in [tidy][tidy-unit-tests]). -This approach ensures that when the test file is changed, the crate does not need to be recompiled. +All standard library and compiler unit tests are placed in separate `tests` file +(which is enforced in [tidy][tidy-unit-tests]). +This ensures that when the test file is changed, the crate does not need to be recompiled. For example: ```rust,ignore @@ -53,12 +53,11 @@ For example: mod tests; ``` -If it wasn't done this way, and the tests were placed in the same file as the source, -then changing or adding a test would cause the crate you are working on to be recompiled. -If you were working on something like `core`, -then that would require recompiling the entire standard library, and the entirety of `rustc`. +If it wasn't done this way, +and you were working on something like `core`, +that would require recompiling the entire standard library, and the entirety of `rustc`. -`./x.py test` includes some CLI options for controlling the behavior with these tests: +`./x test` includes some CLI options for controlling the behavior with these tests: * `--doc` — Only runs documentation tests in the package. * `--no-doc` — Run all tests *except* documentation tests. @@ -71,7 +70,7 @@ Tidy is a custom tool used for validating source code style and formatting conve such as rejecting long lines. There is more information in the [section on coding conventions](../conventions.md#formatting). -> Example: `./x.py test tidy` +> Example: `./x test tidy` ### Formatting @@ -80,28 +79,28 @@ The formatting check is automatically run by the Tidy tool mentioned above. Examples: -| Command | Description | -|---------|-------------| -| `./x.py fmt --check` | Checks formatting and exits with an error if formatting is needed. | -| `./x.py fmt` | Runs rustfmt across the entire codebase. | -| `./x.py test tidy --bless` | First runs rustfmt to format the codebase, then runs tidy checks. | +| Command | Description | +| ----------------------- | ------------------------------------------------------------------ | +| `./x fmt --check` | Checks formatting and exits with an error if formatting is needed. | +| `./x fmt` | Runs rustfmt across the entire codebase. | +| `./x test tidy --bless` | First runs rustfmt to format the codebase, then runs tidy checks. | ### Book documentation tests All of the books that are published have their own tests, primarily for validating that the Rust code examples pass. Under the hood, these are essentially using `rustdoc --test` on the markdown files. -The tests can be run by passing a path to a book to `./x.py test`. +The tests can be run by passing a path to a book to `./x test`. -> Example: `./x.py test src/doc/book` +> Example: `./x test src/doc/book` ### Documentation link checker Links across all documentation is validated with a link checker tool. -> Example: `./x.py test src/tools/linkchecker` +> Example: `./x test src/tools/linkchecker` -> Example: `./x.py test linkchecker` +> Example: `./x test linkchecker` This requires building all of the documentation, which might take a while. @@ -110,7 +109,7 @@ This requires building all of the documentation, which might take a while. `distcheck` verifies that the source distribution tarball created by the build system will unpack, build, and run all tests. -> Example: `./x.py test distcheck` +> Example: `./x test distcheck` ### Tool tests @@ -119,9 +118,9 @@ This includes things such as cargo, clippy, rustfmt, miri, bootstrap (testing the Rust build system itself), etc. Most of the tools are located in the [`src/tools`] directory. -To run the tool's tests, just pass its path to `./x.py test`. +To run the tool's tests, just pass its path to `./x test`. -> Example: `./x.py test src/tools/cargo` +> Example: `./x test src/tools/cargo` Usually these tools involve running `cargo test` within the tool's directory. @@ -139,7 +138,7 @@ More information can be found in the [toolstate documentation]. (such as `servo`, `ripgrep`, `tokei`, etc.). This ensures there aren't any significant regressions. -> Example: `./x.py test src/tools/cargotest` +> Example: `./x test src/tools/cargotest` ### Crater diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md index 0a3de6f8b..71fb82b68 100644 --- a/src/doc/rustc-dev-guide/src/tests/running.md +++ b/src/doc/rustc-dev-guide/src/tests/running.md @@ -2,11 +2,11 @@ <!-- toc --> -You can run the tests using `x.py`. The most basic command – which +You can run the tests using `x`. The most basic command – which you will almost never want to use! – is as follows: ```bash -./x.py test +./x test ``` This will build the stage 1 compiler and then run the whole test @@ -37,7 +37,7 @@ modifying rustc to see if things are generally working correctly would be the following: ```bash -./x.py test tests/ui +./x test tests/ui ``` This will run the `ui` test suite. Of course, the choice @@ -46,32 +46,32 @@ doing. For example, if you are hacking on debuginfo, you may be better off with the debuginfo test suite: ```bash -./x.py test tests/debuginfo +./x test tests/debuginfo ``` If you only need to test a specific subdirectory of tests for any -given test suite, you can pass that directory to `./x.py test`: +given test suite, you can pass that directory to `./x test`: ```bash -./x.py test tests/ui/const-generics +./x test tests/ui/const-generics ``` Likewise, you can test a single file by passing its path: ```bash -./x.py test tests/ui/const-generics/const-test.rs +./x test tests/ui/const-generics/const-test.rs ``` ### Run only the tidy script ```bash -./x.py test tidy +./x test tidy ``` ### Run tests on the standard library ```bash -./x.py test --stage 0 library/std +./x test --stage 0 library/std ``` Note that this only runs tests on `std`; if you want to test `core` or other crates, @@ -80,13 +80,13 @@ you have to specify those explicitly. ### Run the tidy script and tests on the standard library ```bash -./x.py test --stage 0 tidy library/std +./x test --stage 0 tidy library/std ``` ### Run tests on the standard library using a stage 1 compiler ```bash -./x.py test --stage 1 library/std +./x test --stage 1 library/std ``` By listing which test suites you want to run you avoid having to run @@ -99,7 +99,7 @@ there are some limitations. ### Run all tests using a stage 2 compiler ```bash -./x.py test --stage 2 +./x test --stage 2 ``` You almost never need to do this; CI will run these tests for you. @@ -108,13 +108,13 @@ You almost never need to do this; CI will run these tests for you. You may want to run unit tests on a specific file with following: ```bash -./x.py test compiler/rustc_data_structures/src/thin_vec/tests.rs +./x test compiler/rustc_data_structures/src/thin_vec/tests.rs ``` But unfortunately, it's impossible. You should invoke following instead: ```bash -./x.py test compiler/rustc_data_structures/ --test-args thin_vec +./x test compiler/rustc_data_structures/ --test-args thin_vec ``` ## Running an individual test @@ -122,10 +122,10 @@ But unfortunately, it's impossible. You should invoke following instead: Another common thing that people want to do is to run an **individual test**, often the test they are trying to fix. As mentioned earlier, you may pass the full file path to achieve this, or alternatively one -may invoke `x.py` with the `--test-args` option: +may invoke `x` with the `--test-args` option: ```bash -./x.py test tests/ui --test-args issue-1234 +./x test tests/ui --test-args issue-1234 ``` Under the hood, the test runner invokes the standard Rust test runner @@ -133,6 +133,15 @@ Under the hood, the test runner invokes the standard Rust test runner filtering for tests that include "issue-1234" in the name. (Thus `--test-args` is a good way to run a collection of related tests.) +## Passing arguments to `rustc` when running tests + +It can sometimes be useful to run some tests with specific compiler arguments, +without using `RUSTFLAGS` (during development of unstable features, with `-Z` +flags, for example). + +This can be done with `./x test`'s `--rustc-args` option, to pass additional +arguments to the compiler when building the tests. + ## Editing and updating the reference files If you have changed the compiler's output intentionally, or you are @@ -140,7 +149,7 @@ making a new test, you can pass `--bless` to the test subcommand. E.g. if some tests in `tests/ui` are failing, you can run ```text -./x.py test tests/ui --bless +./x test tests/ui --bless ``` to automatically adjust the `.stderr`, `.stdout` or `.fixed` files of @@ -168,7 +177,7 @@ exists in the test file. For example, you can run all the tests in `tests/ui` as `check-pass`: ```bash -./x.py test tests/ui --pass check +./x test tests/ui --pass check ``` By passing `--pass $mode`, you can reduce the testing time. For each @@ -184,7 +193,7 @@ mode, a test `foo.rs` will first look for expected output in The following will run the UI test suite in Polonius mode: ```bash -./x.py test tests/ui --compare-mode=polonius +./x test tests/ui --compare-mode=polonius ``` See [Compare modes](compiletest.md#compare-modes) for more details. @@ -217,7 +226,7 @@ execution* so be careful where it is used. To do this, first build `remote-test-server` for the remote machine, e.g. for RISC-V ```sh -./x.py build src/tools/remote-test-server --target riscv64gc-unknown-linux-gnu +./x build src/tools/remote-test-server --target riscv64gc-unknown-linux-gnu ``` The binary will be created at @@ -247,11 +256,11 @@ pong ``` To run tests using the remote runner, set the `TEST_DEVICE_ADDR` environment -variable then use `x.py` as usual. For example, to run `ui` tests for a RISC-V +variable then use `x` as usual. For example, to run `ui` tests for a RISC-V machine with the IP address `1.2.3.4` use ```sh export TEST_DEVICE_ADDR="1.2.3.4:12345" -./x.py test tests/ui --target riscv64gc-unknown-linux-gnu +./x test tests/ui --target riscv64gc-unknown-linux-gnu ``` If `remote-test-server` was run with the verbose flag, output on the test machine @@ -273,7 +282,7 @@ run "/tmp/work/test1018/a" [...] ``` -Tests are built on the machine running `x.py` not on the remote machine. Tests +Tests are built on the machine running `x` not on the remote machine. Tests which fail to build unexpectedly (or `ui` tests producing incorrect build output) may fail without ever running on the remote machine. diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index d94d8cc4e..1f899f586 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -88,7 +88,7 @@ check for output files: contents of the stored output files by lines opposed to checking for strict equality. -UI tests run with with `-Zdeduplicate-diagnostics=no` flag which disables +UI tests run with `-Zdeduplicate-diagnostics=no` flag which disables rustc's built-in diagnostic deduplication mechanism. This means you may see some duplicate messages in the output. This helps illuminate situations where duplicate diagnostics are being @@ -390,7 +390,7 @@ Tests with the `*-pass` headers can be overridden with the `--pass` command-line option: ```sh -./x.py test tests/ui --pass check +./x test tests/ui --pass check ``` The `--pass` option only affects UI tests. @@ -485,7 +485,7 @@ Then, it applies the suggestion and compares against `.fixed` (they must match). Finally, the fixed source is compiled, and this compilation is required to succeed. Usually when creating a rustfix test you will generate the `.fixed` file -automatically with the `x.py test --bless` option. +automatically with the `x test --bless` option. The `run-rustfix` header will cause *all* suggestions to be applied, even if they are not [`MachineApplicable`](../diagnostics.md#suggestions). @@ -515,7 +515,7 @@ If in the rare case you encounter a test that has different behavior, you can run something like the following to generate the alternate stderr file: ```sh -./x.py test tests/ui --compare-mode=polonius --bless +./x test tests/ui --compare-mode=polonius --bless ``` Currently none of the compare modes are checked in CI for UI tests. diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index 84cb1296f..5e22f10e4 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -163,7 +163,7 @@ Depending on the feature/change/bug fix/improvement, implementation may be relatively-straightforward or it may be a major undertaking. You can always ask for help or mentorship from more experienced compiler devs. Also, you don't have to be the one to implement your feature; but keep in mind that if you -don't it might be a while before someone else does. +don't, it might be a while before someone else does. For the `?` macro feature, I needed to go understand the relevant parts of macro expansion in the compiler. Personally, I find that [improving the |