summaryrefslogtreecommitdiffstats
path: root/src/doc/rustc-dev-guide
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
commitc23a457e72abe608715ac76f076f47dc42af07a5 (patch)
tree2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /src/doc/rustc-dev-guide
parentReleasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz
rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/doc/rustc-dev-guide')
-rw-r--r--src/doc/rustc-dev-guide/.editorconfig1
-rw-r--r--src/doc/rustc-dev-guide/src/SUMMARY.md6
-rw-r--r--src/doc/rustc-dev-guide/src/appendix/glossary.md6
-rw-r--r--src/doc/rustc-dev-guide/src/backend/updating-llvm.md5
-rw-r--r--src/doc/rustc-dev-guide/src/borrow_check/drop_check.md154
-rw-r--r--src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md4
-rw-r--r--src/doc/rustc-dev-guide/src/building/optimized-build.md129
-rw-r--r--src/doc/rustc-dev-guide/src/building/suggested.md13
-rw-r--r--src/doc/rustc-dev-guide/src/const-eval.md49
-rw-r--r--src/doc/rustc-dev-guide/src/early-late-bound-summary.md10
-rw-r--r--src/doc/rustc-dev-guide/src/generics.md51
-rw-r--r--src/doc/rustc-dev-guide/src/getting-started.md4
-rw-r--r--src/doc/rustc-dev-guide/src/git.md36
-rw-r--r--src/doc/rustc-dev-guide/src/img/coverage-graphviz-01.pngbin340404 -> 0 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/img/coverage-spanview-01.pngbin320657 -> 0 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/licenses.md42
-rw-r--r--src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md162
-rw-r--r--src/doc/rustc-dev-guide/src/memory.md10
-rw-r--r--src/doc/rustc-dev-guide/src/mir/index.md78
-rw-r--r--src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md4
-rw-r--r--src/doc/rustc-dev-guide/src/rustdoc-internals.md4
-rw-r--r--src/doc/rustc-dev-guide/src/serialization.md4
-rw-r--r--src/doc/rustc-dev-guide/src/tests/compiletest.md67
-rw-r--r--src/doc/rustc-dev-guide/src/turbofishing-and-early-late-bound.md120
-rw-r--r--src/doc/rustc-dev-guide/src/ty.md32
-rw-r--r--src/doc/rustc-dev-guide/src/what-does-early-late-bound-mean.md (renamed from src/doc/rustc-dev-guide/src/early-late-bound.md)22
26 files changed, 750 insertions, 263 deletions
diff --git a/src/doc/rustc-dev-guide/.editorconfig b/src/doc/rustc-dev-guide/.editorconfig
index cb3312517..443c4c284 100644
--- a/src/doc/rustc-dev-guide/.editorconfig
+++ b/src/doc/rustc-dev-guide/.editorconfig
@@ -3,6 +3,7 @@ root = true
[src/*]
end_of_line = lf
insert_final_newline = true
+max_line_length = 100
[ci/*.sh]
indent_style = space
diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md
index 97f3503ae..41e16c5e6 100644
--- a/src/doc/rustc-dev-guide/src/SUMMARY.md
+++ b/src/doc/rustc-dev-guide/src/SUMMARY.md
@@ -14,6 +14,7 @@
- [Building Documentation](./building/compiler-documenting.md)
- [Rustdoc overview](./rustdoc.md)
- [Adding a new target](./building/new-target.md)
+ - [Optimized build](./building/optimized-build.md)
- [Testing the compiler](./tests/intro.md)
- [Running tests](./tests/running.md)
- [Testing with Docker](./tests/docker.md)
@@ -112,7 +113,9 @@
- [Bound vars and Parameters](./bound-vars-and-params.md)
- [Type inference](./type-inference.md)
- [Trait solving](./traits/resolution.md)
- - [Early and Late Bound Parameter Definitions](./early-late-bound.md)
+ - [Early and Late Bound Parameter Definitions](./early-late-bound-summary.md)
+ - [What are early and late bound parameters](./what-does-early-late-bound-mean.md)
+ - [Interactions with turbofishing](./turbofishing-and-early-late-bound.md)
- [Higher-ranked trait bounds](./traits/hrtb.md)
- [Caching subtleties](./traits/caching.md)
- [Specialization](./traits/specialization.md)
@@ -139,6 +142,7 @@
- [Tracking moves and initialization](./borrow_check/moves_and_initialization.md)
- [Move paths](./borrow_check/moves_and_initialization/move_paths.md)
- [MIR type checker](./borrow_check/type_check.md)
+ - [Drop check](./borrow_check/drop_check.md)
- [Region inference](./borrow_check/region_inference.md)
- [Constraint propagation](./borrow_check/region_inference/constraint_propagation.md)
- [Lifetime parameters](./borrow_check/region_inference/lifetime_parameters.md)
diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md
index 019d31138..27b6cddf2 100644
--- a/src/doc/rustc-dev-guide/src/appendix/glossary.md
+++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md
@@ -5,6 +5,7 @@ Term | Meaning
------------------------------------------------------|--------
<span id="arena">arena/arena allocation</span> &nbsp; | An _arena_ is a large memory buffer from which other memory allocations are made. This style of allocation is called _arena allocation_. See [this chapter](../memory.md) for more info.
<span id="ast">AST</span> &nbsp; | The abstract syntax tree produced by the `rustc_ast` crate; reflects user syntax very closely.
+<span id="APIT">APIT</span> &nbsp; | An argument-position `impl Trait`. Also known as an anonymous type parameter. ([see the reference](https://doc.rust-lang.org/reference/types/impl-trait.html#anonymous-type-parameters)).
<span id="binder">binder</span> &nbsp; | A "binder" is a place where a variable or type is declared; for example, the `<T>` is a binder for the generic type parameter `T` in `fn foo<T>(..)`, and \|`a`\|` ...` is a binder for the parameter `a`. See [the background chapter for more](./background.md#free-vs-bound).
<span id="body-id">BodyId</span> &nbsp; | An identifier that refers to a specific body (definition of a function or constant) in the crate. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir).
<span id="bound-var">bound variable</span> &nbsp; | A "bound variable" is one that is declared within an expression/term. For example, the variable `a` is bound within the closure expression \|`a`\|` a * 2`. See [the background chapter for more](./background.md#free-vs-bound)
@@ -23,7 +24,7 @@ Term | Meaning
<span id="double-ptr">double pointer</span> &nbsp; | A pointer with additional metadata. See "fat pointer" for more.
<span id="drop-glue">drop glue</span> &nbsp; | (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types.
<span id="dst">DST</span> &nbsp; | Short for Dynamically-Sized Type, this is a type for which the compiler cannot statically know the size in memory (e.g. `str` or `[u8]`). Such types don't implement `Sized` and cannot be allocated on the stack. They can only occur as the last field in a struct. They can only be used behind a pointer (e.g. `&str` or `&[u8]`).
-<span id="ebl">early-bound lifetime</span> &nbsp; | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `Substs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#bound-regions))
+<span id="ebl">early-bound lifetime</span> &nbsp; | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `GenericArgs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#bound-regions))
<span id="empty-type">empty type</span> &nbsp; | see "uninhabited type".
<span id="fat-ptr">fat pointer</span> &nbsp; | A two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of "fat pointers": references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers".
<span id="free-var">free variable</span> &nbsp; | A "free variable" is one that is not bound within an expression or term; see [the background chapter for more](./background.md#free-vs-bound)
@@ -67,6 +68,8 @@ Term | Meaning
<span id="recovery">recovery</span> &nbsp; | Recovery refers to handling invalid syntax during parsing (e.g. a missing comma) and continuing to parse the AST. This avoid showing spurious errors to the user (e.g. showing 'missing field' errors when the struct definition contains errors).
<span id="region">region</span> &nbsp; | Another term for "lifetime" often used in the literature and in the borrow checker.
<span id="rib">rib</span> &nbsp; | A data structure in the name resolver that keeps track of a single scope for names. ([see more](../name-resolution.md))
+<span id="rpit">RPIT</span> &nbsp; | A return-position `impl Trait`. ([see the reference](https://doc.rust-lang.org/reference/types/impl-trait.html#abstract-return-types)).
+<span id="rpitit">RPITIT</span> &nbsp; | A return-position `impl Trait` *in trait*. Unlike RPIT, this is desugared to a generic associated type (GAT). Introduced in [RFC 3425](https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html). ([see more](../return-position-impl-trait-in-trait.md))
<span id="scrutinee">scrutinee</div> &nbsp; | A scrutinee is the expression that is matched on in `match` expressions and similar pattern matching constructs. For example, in `match x { A => 1, B => 2 }`, the expression `x` is the scrutinee.
<span id="sess">sess</span> &nbsp; | The compiler session, which stores global data used throughout compilation
<span id="side-tables">side tables</span> &nbsp; | Because the AST and HIR are immutable once created, we often carry extra information about them in the form of hashtables, indexed by the id of a particular node.
@@ -76,6 +79,7 @@ Term | Meaning
<span id="substs">substs</span> &nbsp; | The substitutions for a given generic type or item (e.g. the `i32`, `u32` in `HashMap<i32, u32>`).
<span id="sysroot">sysroot</span> &nbsp; | The directory for build artifacts that are loaded by the compiler at runtime. ([see more](../building/bootstrapping.html#what-is-a-sysroot))
<span id="tag">tag</span> &nbsp; | The "tag" of an enum/generator encodes the [discriminant](#discriminant) of the active variant/state. Tags can either be "direct" (simply storing the discriminant in a field) or use a ["niche"](#niche).
+<span id="tait">TAIT</span> &nbsp; | A type-alias `impl Trait`. Introduced in [RFC 2515](https://rust-lang.github.io/rfcs/2515-type_alias_impl_trait.html).
<span id="tcx">`tcx`</span> &nbsp; | Standard variable name for the "typing context" (`TyCtxt`), main data structure of the compiler. ([see more](../ty.md))
<span id="lifetime-tcx">`'tcx`</span> &nbsp; | The lifetime of the allocation arenas used by `TyCtxt`. Most data interned during a compilation session will use this lifetime with the exception of HIR data which uses the `'hir` lifetime. ([see more](../ty.md))
<span id="token">token</span> &nbsp; | The smallest unit of parsing. Tokens are produced after lexing ([see more](../the-parser.md)).
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 08af10f89..dd16b1e28 100644
--- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md
+++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md
@@ -2,7 +2,7 @@
<!-- toc -->
-<!-- date-check: Feb 2023 -->
+<!-- date-check: Jul 2023 -->
There is no formal policy about when to update LLVM or what it can be updated to,
but a few guidelines are applied:
@@ -52,7 +52,7 @@ An example PR:
## New LLVM Release Updates
-<!-- date-check: Aug 2022 -->
+<!-- date-check: Jul 2023 -->
Unlike bugfixes,
updating to a new release of LLVM typically requires a lot more work.
@@ -139,6 +139,7 @@ so let's go through each in detail.
> - [LLVM 13](https://github.com/rust-lang/rust/pull/87570)
> - [LLVM 14](https://github.com/rust-lang/rust/pull/93577)
> - [LLVM 15](https://github.com/rust-lang/rust/pull/99464)
+ > - [LLVM 16](https://github.com/rust-lang/rust/pull/109474)
Note that sometimes it's easiest to land [`llvm-wrapper`] compatibility as a PR
before actually updating `src/llvm-project`.
diff --git a/src/doc/rustc-dev-guide/src/borrow_check/drop_check.md b/src/doc/rustc-dev-guide/src/borrow_check/drop_check.md
new file mode 100644
index 000000000..51d1ddd83
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/borrow_check/drop_check.md
@@ -0,0 +1,154 @@
+# Drop Check
+
+We generally require the type of locals to be well-formed whenever the
+local is used. This includes proving the where-bounds of the local and
+also requires all regions used by it to be live.
+
+The only exception to this is when implicitly dropping values when they
+go out of scope. This does not necessarily require the value to be live:
+
+```rust
+fn main() {
+ let x = vec![];
+ {
+ let y = String::from("I am temporary");
+ x.push(&y);
+ }
+ // `x` goes out of scope here, after the reference to `y`
+ // is invalidated. This means that while dropping `x` its type
+ // is not well-formed as it contain regions which are not live.
+}
+```
+
+This is only sound if dropping the value does not try to access any dead
+region. We check this by requiring the type of the value to be
+drop-live.
+The requirements for which are computed in `fn dropck_outlives`.
+
+The rest of this section uses the following type definition for a type
+which requires its region parameter to be live:
+
+```rust
+struct PrintOnDrop<'a>(&'a str);
+impl<'a> Drop for PrintOnDrop<'_> {
+ fn drop(&mut self) {
+ println!("{}", self.0);
+ }
+}
+```
+
+## How values are dropped
+
+At its core, a value of type `T` is dropped by executing its "drop
+glue". Drop glue is compiler generated and first calls `<T as
+Drop>::drop` and then recursively calls the drop glue of any recursively
+owned values.
+
+- If `T` has an explicit `Drop` impl, call `<T as Drop>::drop`.
+- Regardless of whether `T` implements `Drop`, recurse into all values
+ *owned* by `T`:
+ - references, raw pointers, function pointers, function items, trait
+ objects[^traitobj], and scalars do not own anything.
+ - tuples, slices, and arrays consider their elements to be owned.
+ For arrays of length zero we do not own any value of the element
+ type.
+ - all fields (of all variants) of ADTs are considered owned. We
+ consider all variants for enums. The exception here is
+ `ManuallyDrop<U>` which is not considered to own `U`.
+ `PhantomData<U>` also does not own anything.
+ closures and generators own their captured upvars.
+
+Whether a type has drop glue is returned by [`fn
+Ty::needs_drop`](https://github.com/rust-lang/rust/blob/320b412f9c55bf480d26276ff0ab480e4ecb29c0/compiler/rustc_middle/src/ty/util.rs#L1086-L1108).
+
+### Partially dropping a local
+
+For types which do not implement `Drop` themselves, we can also
+partially move parts of the value before dropping the rest. In this case
+only the drop glue for the not-yet moved values is called, e.g.
+
+```rust
+fn main() {
+ let mut x = (PrintOnDrop("third"), PrintOnDrop("first"));
+ drop(x.1);
+ println!("second")
+}
+```
+
+During MIR building we assume that a local may get dropped whenever it
+goes out of scope *as long as its type needs drop*. Computing the exact
+drop glue for a variable happens **after** borrowck in the
+`ElaborateDrops` pass. This means that even if some part of the local
+have been dropped previously, dropck still requires this value to be
+live. This is the case even if we completely moved a local.
+
+```rust
+fn main() {
+ let mut x;
+ {
+ let temp = String::from("I am temporary");
+ x = PrintOnDrop(&temp);
+ drop(x);
+ }
+} //~ ERROR `temp` does not live long enough.
+```
+
+It should be possible to add some amount of drop elaboration before
+borrowck, allowing this example to compile. There is an unstable feature
+to move drop elaboration before const checking:
+[#73255](https://github.com/rust-lang/rust/issues/73255). Such a feature
+gate does not exist for doing some drop elaboration before borrowck,
+although there's a [relevant
+MCP](https://github.com/rust-lang/compiler-team/issues/558).
+
+[^traitobj]: you can consider trait objects to have a builtin `Drop`
+implementation which directly uses the `drop_in_place` provided by the
+vtable. This `Drop` implementation requires all its generic parameters
+to be live.
+
+### `dropck_outlives`
+
+There are two distinct "liveness" computations that we perform:
+
+* a value `v` is *use-live* at location `L` if it may be "used" later; a
+ *use* here is basically anything that is not a *drop*
+* a value `v` is *drop-live* at location `L` if it maybe dropped later
+
+When things are *use-live*, their entire type must be valid at `L`. When
+they are *drop-live*, all regions that are required by dropck must be
+valid at `L`. The values dropped in the MIR are *places*.
+
+The constraints computed by `dropck_outlives` for a type closely match
+the generated drop glue for that type. Unlike drop glue,
+`dropck_outlives` cares about the types of owned values, not the values
+itself. For a value of type `T`
+
+- if `T` has an explicit `Drop`, require all generic arguments to be
+ live, unless they are marked with `#[may_dangle]` in which case they
+ are fully ignored
+- regardless of whether `T` has an explicit `Drop`, recurse into all
+ types *owned* by `T`
+ - references, raw pointers, function pointers, function items, trait
+ objects[^traitobj], and scalars do not own anything.
+ - tuples, slices and arrays consider their element type to be owned.
+ **For arrays we currently do not check whether their length is
+ zero**.
+ - all fields (of all variants) of ADTs are considered owned. The
+ exception here is `ManuallyDrop<U>` which is not considered to own
+ `U`. **We consider `PhantomData<U>` to own `U`**.
+ - closures and generators own their captured upvars.
+
+The sections marked in bold are cases where `dropck_outlives` considers
+types to be owned which are ignored by `Ty::needs_drop`. We only rely on
+`dropck_outlives` if `Ty::needs_drop` for the containing local returned
+`true`.This means liveness requirements can change depending on whether
+a type is contained in a larger local. **This is inconsistent, and
+should be fixed: an example [for
+arrays](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8b5f5f005a03971b22edb1c20c5e6cbe)
+and [for
+`PhantomData`](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=44c6e2b1fae826329fd54c347603b6c8).**[^core]
+
+One possible way these inconsistencies can be fixed is by MIR building
+to be more pessimistic, probably by making `Ty::needs_drop` weaker, or
+alternatively, changing `dropck_outlives` to be more precise, requiring
+fewer regions to be live.
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 0865f1955..1012e94fd 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
@@ -65,8 +65,8 @@ Also, using `x` rather than `x.py` is recommended as:
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:
+In the rest of this guide, we use `x` rather than `x.py` directly. The following
+command:
```bash
./x check
diff --git a/src/doc/rustc-dev-guide/src/building/optimized-build.md b/src/doc/rustc-dev-guide/src/building/optimized-build.md
new file mode 100644
index 000000000..1e1136b91
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/building/optimized-build.md
@@ -0,0 +1,129 @@
+# Optimized build of the compiler
+
+<!-- toc -->
+
+There are multiple additional build configuration options and techniques that can used to compile a
+build of `rustc` that is as optimized as possible (for example when building `rustc` for a Linux
+distribution). The status of these configuration options for various Rust targets is tracked [here].
+This page describes how you can use these approaches when building `rustc` yourself.
+
+[here]: https://github.com/rust-lang/rust/issues/103595
+
+## Link-time optimization
+
+Link-time optimization is a powerful compiler technique that can increase program performance. To
+enable (Thin-)LTO when building `rustc`, set the `rust.lto` config option to `"thin"`
+in `config.toml`:
+
+```toml
+[rust]
+lto = "thin"
+```
+
+> Note that LTO for `rustc` is currently supported and tested only for
+> the `x86_64-unknown-linux-gnu` target. Other targets *may* work, but no guarantees are provided.
+> Notably, LTO-optimized `rustc` currently produces [miscompilations] on Windows.
+
+[miscompilations]: https://github.com/rust-lang/rust/issues/109114
+
+Enabling LTO on Linux has [produced] speed-ups by up to 10%.
+
+[produced]: https://github.com/rust-lang/rust/pull/101403#issuecomment-1288190019
+
+## Memory allocator
+
+Using a different memory allocator for `rustc` can provide significant performance benefits. If you
+want to enable the `jemalloc` allocator, you can set the `rust.jemalloc` option to `true`
+in `config.toml`:
+
+```toml
+[rust]
+jemalloc = true
+```
+
+> Note that this option is currently only supported for Linux and macOS targets.
+
+## Codegen units
+
+Reducing the amount of codegen units per `rustc` crate can produce a faster build of the compiler.
+You can modify the number of codegen units for `rustc` and `libstd` in `config.toml` with the
+following options:
+
+```toml
+[rust]
+codegen-units = 1
+codegen-units-std = 1
+```
+
+## Instruction set
+
+By default, `rustc` is compiled for a generic (and conservative) instruction set architecture
+(depending on the selected target), to make it support as many CPUs as possible. If you want to
+compile `rustc` for a specific instruction set architecture, you can set the `target_cpu` compiler
+option in `RUSTFLAGS`:
+
+```bash
+RUSTFLAGS="-C target_cpu=x86-64-v3" ./x build ...
+```
+
+If you also want to compile LLVM for a specific instruction set, you can set `llvm` flags
+in `config.toml`:
+
+```toml
+[llvm]
+cxxflags = "-march=x86-64-v3"
+cflags = "-march=x86-64-v3"
+```
+
+## Profile-guided optimization
+
+Applying profile-guided optimizations (or more generally, feedback-directed optimizations) can
+produce a large increase to `rustc` performance, by up to 15% ([1], [2]). However, these techniques
+are not simply enabled by a configuration option, but rather they require a complex build workflow
+that compiles `rustc` multiple times and profiles it on selected benchmarks.
+
+There is a tool called `opt-dist` that is used to optimize `rustc` with [PGO] (profile-guided
+optimizations) and [BOLT] (a post-link binary optimizer) for builds distributed to end users. You
+can examine the tool, which is located in `src/tools/opt-dist`, and build a custom PGO build
+workflow based on it, or try to use it directly. Note that the tool is currently quite hardcoded to
+the way we use it in Rust's continuous integration workflows, and it might require some custom
+changes to make it work in a different environment.
+
+[1]: https://blog.rust-lang.org/inside-rust/2020/11/11/exploring-pgo-for-the-rust-compiler.html#final-numbers-and-a-benchmarking-plot-twist
+[2]: https://github.com/rust-lang/rust/pull/96978
+
+[PGO]: https://doc.rust-lang.org/rustc/profile-guided-optimization.html
+
+[BOLT]: https://github.com/llvm/llvm-project/blob/main/bolt/README.md
+
+To use the tool, you will need to provide some external dependencies:
+
+- A Python3 interpreter (for executing `x.py`).
+- Compiled LLVM toolchain, with the `llvm-profdata` binary. Optionally, if you want to use BOLT,
+ the `llvm-bolt` and
+ `merge-fdata` binaries have to be available in the toolchain.
+
+These dependencies are provided to `opt-dist` by an implementation of the [`Environment`] struct.
+It specifies directories where will the PGO/BOLT pipeline take place, and also external dependencies
+like Python or LLVM.
+
+Here is an example of how can `opt-dist` be used locally (outside of CI):
+
+1. Build the tool with the following command:
+ ```bash
+ ./x build tools/opt-dist
+ ```
+2. Run the tool with the `local` mode and provide necessary parameters:
+ ```bash
+ ./build/host/stage0-tools-bin/opt-dist local \
+ --target-triple <target> \ # select target, e.g. "x86_64-unknown-linux-gnu"
+ --checkout-dir <path> \ # path to rust checkout, e.g. "."
+ --llvm-dir <path> \ # path to built LLVM toolchain, e.g. "/foo/bar/llvm/install"
+ -- python3 x.py dist # pass the actual build command
+ ```
+ You can run `--help` to see further parameters that you can modify.
+
+[`Environment`]: https://github.com/rust-lang/rust/blob/ee451f8faccf3050c76cdcd82543c917b40c7962/src/tools/opt-dist/src/environment.rs#L5
+
+> Note: if you want to run the actual CI pipeline, instead of running `opt-dist` locally,
+> you can execute `DEPLOY=1 src/ci/docker/run.sh dist-x86_64-linux`.
diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md
index 0da3f60cf..cb722696e 100644
--- a/src/doc/rustc-dev-guide/src/building/suggested.md
+++ b/src/doc/rustc-dev-guide/src/building/suggested.md
@@ -36,8 +36,6 @@ If you have enough free disk space and you would like to be able to run `x` comm
rust-analyzer runs in the background, you can also add `--build-dir build-rust-analyzer` to the
`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 check` on save is inconvenient, in VS Code you can use a [Build
Task] instead:
@@ -74,9 +72,9 @@ Rust-Analyzer to already be configured with Neovim. Steps for this can be
`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/rust_analyzer_settings.json).
+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`].
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
@@ -155,7 +153,7 @@ lets you use `cargo fmt`.
Sometimes just checking
whether the compiler builds is not enough. A common example is that
you need to add a `debug!` statement to inspect the value of some
-state or better understand the problem. In that case, you really need
+state or better understand the problem. In that case, you don't really need
a full build. By bypassing bootstrap's cache invalidation, you can often get
these builds to complete very fast (e.g., around 30 seconds). The only
catch is this requires a bit of fudging and may produce compilers that
@@ -282,6 +280,7 @@ let
changelog-seen = 2
[build]
+ patch-binaries-for-nix = true
# The path to (or name of) the GDB executable to use. This is only used for
# executing the debuginfo test suite.
gdb = "${pkgs.gdb}/bin/gdb"
@@ -346,3 +345,5 @@ 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.
+
+[`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json
diff --git a/src/doc/rustc-dev-guide/src/const-eval.md b/src/doc/rustc-dev-guide/src/const-eval.md
index 6d301823b..736405326 100644
--- a/src/doc/rustc-dev-guide/src/const-eval.md
+++ b/src/doc/rustc-dev-guide/src/const-eval.md
@@ -40,52 +40,11 @@ in which the constant is evaluated (e.g. the function within which the constant
and a [`GlobalId`]. The `GlobalId` is made up of an `Instance` referring to a constant
or static or of an `Instance` of a function and an index into the function's `Promoted` table.
-Constant evaluation returns an [`EvalToValTreeResult`] for type system constants or
-[`EvalToConstValueResult`] with either the error, or a representation of the constant.
-
-Constants for the type system are encoded in "valtree representation". The `ValTree` datastructure
-allows us to represent
-
-* arrays,
-* many structs,
-* tuples,
-* enums and,
-* most primitives.
-
-The basic rule for
-being permitted in the type system is that every value must be uniquely represented. In other
-words: a specific value must only be representable in one specific way. For example: there is only
-one way to represent an array of two integers as a `ValTree`:
-`ValTree::Branch(&[ValTree::Leaf(first_int), ValTree::Leaf(second_int)])`.
-Even though theoretically a `[u32; 2]` could be encoded in a `u64` and thus just be a
-`ValTree::Leaf(bits_of_two_u32)`, that is not a legal construction of `ValTree`
-(and is very complex to do, so it is unlikely anyone is tempted to do so).
-
-These rules also mean that some values are not representable. There can be no `union`s in type
-level constants, as it is not clear how they should be represented, because their active variant
-is unknown. Similarly there is no way to represent raw pointers, as addresses are unknown at
-compile-time and thus we cannot make any assumptions about them. References on the other hand
-*can* be represented, as equality for references is defined as equality on their value, so we
-ignore their address and just look at the backing value. We must make sure that the pointer values
-of the references are not observable at compile time. We thus encode `&42` exactly like `42`.
-Any conversion from
-valtree back to codegen constants must reintroduce an actual indirection. At codegen time the
-addresses may be deduplicated between multiple uses or not, entirely depending on arbitrary
-optimization choices.
-
-As a consequence, all decoding of `ValTree` must happen by matching on the type first and making
-decisions depending on that. The value itself gives no useful information without the type that
-belongs to it.
-
-Other constants get represented as [`ConstValue::Scalar`] or
-[`ConstValue::Slice`] if possible. These values are only useful outside the
-compile-time interpreter. If you need the value of a constant during
-interpretation, you need to directly work with [`const_to_op`].
+Constant evaluation returns an [`EvalToValTreeResult`] for type system constants
+or [`EvalToConstValueResult`] with either the error, or a representation of the
+evaluated constant: a [valtree](mir/index.md#valtrees) or a [MIR constant
+value](mir/index.md#mir-constant-values), respectively.
[`GlobalId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/struct.GlobalId.html
-[`ConstValue::Scalar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.Scalar
-[`ConstValue::Slice`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.Slice
-[`ConstValue::ByRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.ByRef
[`EvalToConstValueResult`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToConstValueResult.html
[`EvalToValTreeResult`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToValTreeResult.html
-[`const_to_op`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/struct.InterpCx.html#method.const_to_op
diff --git a/src/doc/rustc-dev-guide/src/early-late-bound-summary.md b/src/doc/rustc-dev-guide/src/early-late-bound-summary.md
new file mode 100644
index 000000000..223e2251d
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/early-late-bound-summary.md
@@ -0,0 +1,10 @@
+# Early/Late bound parameters
+
+This section discusses what it means for generic parameters to be early or late bound.
+
+```rust
+fn foo<'a, T>(b: &'a u32) -> &'a u32 { a }
+// ^^ ^early bound
+// ^^
+// ^^late bound
+``` \ No newline at end of file
diff --git a/src/doc/rustc-dev-guide/src/generics.md b/src/doc/rustc-dev-guide/src/generics.md
index 7512b3b47..6c61ab87f 100644
--- a/src/doc/rustc-dev-guide/src/generics.md
+++ b/src/doc/rustc-dev-guide/src/generics.md
@@ -1,4 +1,4 @@
-# Generics and substitutions
+# Generics and GenericArgs
Given a generic type `MyType<A, B, …>`, we may want to swap out the generics `A, B, …` for some
other types (possibly other generics or concrete types). We do this a lot while doing type
@@ -6,19 +6,20 @@ inference, type checking, and trait solving. Conceptually, during these routines
that one type is equal to another type and want to swap one out for the other and then swap that out
for another type and so on until we eventually get some concrete types (or an error).
-In rustc this is done using [SubstsRef] (“substs” = “substitutions”).
-Conceptually, you can think of `SubstsRef` as a list of types that are to be substituted for the
-generic type parameters of the ADT.
+In rustc this is done using [GenericArgsRef].
+Conceptually, you can think of `GenericArgsRef` as a list of types that are to be substituted for
+ the generic type parameters of the ADT.
-`SubstsRef` is a type alias of `&'tcx List<GenericArg<'tcx>>` (see [`List` rustdocs][list]).
+`GenericArgsRef` is a type alias of `&'tcx List<GenericArg<'tcx>>` (see [`List` rustdocs][list]).
[`GenericArg`] is essentially a space-efficient wrapper around [`GenericArgKind`], which is an enum
-indicating what kind of generic the type parameter is (type, lifetime, or const). Thus, `SubstsRef`
-is conceptually like a `&'tcx [GenericArgKind<'tcx>]` slice (but it is actually a `List`).
+indicating what kind of generic the type parameter is (type, lifetime, or const).
+Thus, `GenericArgsRef` is conceptually like a `&'tcx [GenericArgKind<'tcx>]` slice (but it is
+actually a `List`).
[list]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.List.html
-[`GenericArg`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/struct.GenericArg.html
-[`GenericArgKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/enum.GenericArgKind.html
-[SubstsRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/type.SubstsRef.html
+[`GenericArg`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.GenericArg.html
+[`GenericArgKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.GenericArgKind.html
+[GenericArgsRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.GenericArgsRef.html
So why do we use this `List` type instead of making it really a slice? It has the length "inline",
so `&List` is only 32 bits. As a consequence, it cannot be "subsliced" (that only works if the
@@ -36,10 +37,10 @@ struct MyStruct<T>
- There would be an `AdtDef` (and corresponding `DefId`) for `MyStruct`.
- There would be a `TyKind::Param` (and corresponding `DefId`) for `T` (more later).
-- There would be a `SubstsRef` containing the list `[GenericArgKind::Type(Ty(T))]`
+- There would be a `GenericArgsRef` containing the list `[GenericArgKind::Type(Ty(T))]`
- The `Ty(T)` here is my shorthand for entire other `ty::Ty` that has `TyKind::Param`, which we
mentioned in the previous point.
-- This is one `TyKind::Adt` containing the `AdtDef` of `MyStruct` with the `SubstsRef` above.
+- This is one `TyKind::Adt` containing the `AdtDef` of `MyStruct` with the `GenericArgsRef` above.
Finally, we will quickly mention the
[`Generics`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html) type. It
@@ -113,33 +114,31 @@ This example has a few different substitutions:
Let’s look a bit more closely at that last substitution to see why we use indexes. If we want to
find the type of `foo.x`, we can get generic type of `x`, which is `Vec<Param(0)>`. Now we can take
-the index `0` and use it to find the right type substitution: looking at `Foo`'s `SubstsRef`, we
-have the list `[u32, f32]` , since we want to replace index `0`, we take the 0-th index of this
+the index `0` and use it to find the right type substitution: looking at `Foo`'s `GenericArgsRef`,
+we have the list `[u32, f32]` , since we want to replace index `0`, we take the 0-th index of this
list, which is `u32`. Voila!
You may have a couple of followup questions…
- **`type_of`** How do we get the “generic type of `x`"? You can get the type of pretty much anything
+ **`type_of`** How do we get the "generic type of `x`"? You can get the type of pretty much anything
with the `tcx.type_of(def_id)` query. In this case, we would pass the `DefId` of the field `x`.
The `type_of` query always returns the definition with the generics that are in scope of the
definition. For example, `tcx.type_of(def_id_of_my_struct)` would return the “self-view” of
`MyStruct`: `Adt(Foo, &[Param(0), Param(1)])`.
-**`subst`** How do we actually do the substitutions? There is a function for that too! You use
-[`subst`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/struct.EarlyBinder.html#method.subst) to
-replace a `SubstsRef` with another list of types.
+How do we actually do the substitutions? There is a function for that too! You
+use [`instantiate`] to replace a `GenericArgsRef` with another list of types.
-[Here is an example of actually using `subst` in the compiler][substex]. The exact details are not
-too important, but in this piece of code, we happen to be converting from the `rustc_hir::Ty` to
-a real `ty::Ty`. You can see that we first get some substitutions (`substs`). Then we call
-`type_of` to get a type and call `ty.subst(substs)` to get a new version of `ty` with
-the substitutions made.
+[Here is an example of actually using `instantiate` in the compiler][instantiatex].
+The exact details are not too important, but in this piece of code, we happen to be
+converting from the `rustc_hir::Ty` to a real `ty::Ty`. You can see that we first get some args
+(`args`). Then we call `type_of` to get a type and call `ty.instantiate(tcx, args)` to get a new
+version of `ty` with the args made.
-[substex]: https://github.com/rust-lang/rust/blob/0940040c0486a536be4f8685c7dd9a078f9e87c2/compiler/rustc_hir_analysis/src/astconv/mod.rs#L1231-L1242
+[`instantiate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/generic_args/struct.EarlyBinder.html#method.instantiate
+[instantiatex]: https://github.com/rust-lang/rust/blob/8a562f9671e36cf29c9c794c2646bcf252d55535/compiler/rustc_hir_analysis/src/astconv/mod.rs#L905-L927
**Note on indices:** It is possible for the indices in `Param` to not match with what we expect. For
example, the index could be out of bounds or it could be the index of a lifetime when we were
expecting a type. These sorts of errors would be caught earlier in the compiler when translating
from a `rustc_hir::Ty` to a `ty::Ty`. If they occur later, that is a compiler bug.
-
-
diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md
index 80c3d3793..a12cb068c 100644
--- a/src/doc/rustc-dev-guide/src/getting-started.md
+++ b/src/doc/rustc-dev-guide/src/getting-started.md
@@ -123,6 +123,10 @@ compiler. You can see a list of diagnostic issues [here][diagnostic-issues].
[diagnostic-issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AA-diagnostics+no%3Aassignee
+### Contributing to std (standard library)
+
+See [std-dev-guide](https://std-dev-guide.rust-lang.org/).
+
### Contributing code to other Rust projects
There are a bunch of other projects that you can contribute to outside of the
diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md
index 6c5c64685..4208305a9 100644
--- a/src/doc/rustc-dev-guide/src/git.md
+++ b/src/doc/rustc-dev-guide/src/git.md
@@ -201,6 +201,24 @@ and just want to get a clean copy of the repository back, you can use `git reset
git reset --hard master
```
+### failed to push some refs
+
+`git push` will not work properly and say something like this:
+
+```
+ ! [rejected] issue-xxxxx -> issue-xxxxx (non-fast-forward)
+error: failed to push some refs to 'https://github.com/username/rust.git'
+hint: Updates were rejected because the tip of your current branch is behind
+hint: its remote counterpart. Integrate the remote changes (e.g.
+hint: 'git pull ...') before pushing again.
+hint: See the 'Note about fast-forwards' in 'git push --help' for details.
+```
+
+The advice this gives is incorrect! Because of Rust's
+["no-merge" policy](#no-merge-policy) the merge commit created by `git pull`
+will not be allowed in the final PR, in addition to defeating the point of the
+rebase! Use `git push --force-with-lease` instead.
+
### Git is trying to rebase commits I didn't write?
If you see many commits in your rebase list, or merge commits, or commits by other people that you
@@ -306,22 +324,6 @@ Git know that you've resolved the conflicts and it should finish the rebase.
Once the rebase has succeeded, you'll want to update the associated branch on
your fork with `git push --force-with-lease`.
-Note that `git push` will not work properly and say something like this:
-
-```
- ! [rejected] issue-xxxxx -> issue-xxxxx (non-fast-forward)
-error: failed to push some refs to 'https://github.com/username/rust.git'
-hint: Updates were rejected because the tip of your current branch is behind
-hint: its remote counterpart. Integrate the remote changes (e.g.
-hint: 'git pull ...') before pushing again.
-hint: See the 'Note about fast-forwards' in 'git push --help' for details.
-```
-
-The advice this gives is incorrect! Because of Rust's
-["no-merge" policy](#no-merge-policy) the merge commit created by `git pull`
-will not be allowed in the final PR, in addition to defeating the point of the
-rebase! Use `git push --force-with-lease` instead.
-
### Keeping things up to date
The above section on [Rebasing](#rebasing) is a specific
@@ -351,6 +353,8 @@ upstream.
## Advanced Rebasing
+### Squash your commits
+
If your branch contains multiple consecutive rewrites of the same code, or if
the rebase conflicts are extremely severe, you can use
`git rebase --interactive master` to gain more control over the process. This
diff --git a/src/doc/rustc-dev-guide/src/img/coverage-graphviz-01.png b/src/doc/rustc-dev-guide/src/img/coverage-graphviz-01.png
deleted file mode 100644
index cf7e1e76b..000000000
--- a/src/doc/rustc-dev-guide/src/img/coverage-graphviz-01.png
+++ /dev/null
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/img/coverage-spanview-01.png b/src/doc/rustc-dev-guide/src/img/coverage-spanview-01.png
deleted file mode 100644
index f3e4b3535..000000000
--- a/src/doc/rustc-dev-guide/src/img/coverage-spanview-01.png
+++ /dev/null
Binary files differ
diff --git a/src/doc/rustc-dev-guide/src/licenses.md b/src/doc/rustc-dev-guide/src/licenses.md
index 06cd8ae6b..aa8286714 100644
--- a/src/doc/rustc-dev-guide/src/licenses.md
+++ b/src/doc/rustc-dev-guide/src/licenses.md
@@ -3,3 +3,45 @@
The `rustc` compiler source and standard library are dual licensed under the [Apache License v2.0](https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE) and the [MIT License](https://github.com/rust-lang/rust/blob/master/LICENSE-MIT) unless otherwise specified.
Detailed licensing information is available in the [COPYRIGHT document](https://github.com/rust-lang/rust/blob/master/COPYRIGHT) of the `rust-lang/rust` repository.
+
+## Guidelines for reviewers
+
+In general, reviewers need to be looking not only for the code quality of contributions but also
+that they are properly licensed.
+We have some tips below for things to look out for when reviewing, but if you ever feel uncertain
+as to whether some code might be properly licensed, err on the safe side — reach out to the Council
+or Compiler Team Leads for feedback!
+
+Things to watch out for:
+
+- The PR author states that they copied, ported, or adapted the code from some other source.
+- There is a comment in the code pointing to a webpage or describing where the algorithm was taken
+from.
+- The algorithm or code pattern seems like it was likely copied from somewhere else.
+- When adding new dependencies, double check the dependency's license.
+
+In all of these cases, we will want to check that source to make sure it it is licensed in a way
+that is compatible with Rust’s license.
+
+Examples
+
+- Porting C code from a GPL project, like GNU binutils, is not allowed. That would require Rust
+itself to be licensed under the GPL.
+- Copying code from an algorithms text book may be allowed, but some algorithms are patented.
+
+## Porting
+
+Contributions to rustc, especially around platform and compiler intrinsics, often include porting
+over work from other projects, mainly LLVM and GCC.
+
+Some general rules apply:
+
+- Copying work needs to adhere to the original license
+ - This applies to direct copy & paste
+ - This also applies to code you looked at and ported
+
+In general, taking inspiration from other codebases is fine, but please exercise caution when
+porting code.
+
+Ports of full libraries (e.g. C libraries shipped with LLVM) must keep the license of the original
+library.
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 2b1677ef4..9379a57f6 100644
--- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md
+++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md
@@ -28,7 +28,7 @@ them), and generate various reports for analysis, for example:
<br/>
Detailed instructions and examples are documented in the
-[Rustc Book][rustc-book-instrument-coverage].
+[rustc book][rustc-book-instrument-coverage].
[llvm-instrprof-increment]: https://llvm.org/docs/LangRef.html#llvm-instrprof-increment-intrinsic
[coverage map]: https://llvm.org/docs/CoverageMappingFormat.html
@@ -56,14 +56,14 @@ statically links coverage-instrumented binaries with LLVM runtime code
([compiler-rt][compiler-rt-profile]) that implements program hooks
(such as an `exit` hook) to write the counter values to the `.profraw` file.
-In the `rustc` source tree, `library/profiler_builtins` bundles the LLVM
-`compiler-rt` code into a Rust library crate. (When building `rustc`, the
-`profiler_builtins` library is only included when `profiler = true` is set
-in `rustc`'s `config.toml`.)
+In the `rustc` source tree,
+`library/profiler_builtins` bundles the LLVM `compiler-rt` code into a Rust library crate.
+Note that when building `rustc`,
+`profiler_builtins` is only included when `build.profiler = true` is set in `config.toml`.
When compiling with `-C instrument-coverage`,
-[`CrateLoader::postprocess()`][crate-loader-postprocess] dynamically loads the
-`profiler_builtins` library by calling `inject_profiler_runtime()`.
+[`CrateLoader::postprocess()`][crate-loader-postprocess] dynamically loads
+`profiler_builtins` by calling `inject_profiler_runtime()`.
[compiler-rt-profile]: https://github.com/llvm/llvm-project/tree/main/compiler-rt/lib/profile
[crate-loader-postprocess]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/creader/struct.CrateLoader.html#method.postprocess
@@ -84,10 +84,10 @@ the Rust source code.
Note that many of these `Coverage` statements will _not_ be converted into
physical counters (or any other executable instructions) in the final binary.
-Some of them will be (see `CoverageKind::`[`Counter`][counter-coverage-kind]),
+Some of them will be (see [`CoverageKind::Counter`]),
but other counters can be computed on the fly, when generating a coverage
report, by mapping a `CodeRegion` to a
-`CoverageKind`::[`Expression`][expression-coverage-kind].
+[`CoverageKind::Expression`].
As an example:
@@ -131,8 +131,8 @@ The `InstrumentCoverage` MIR pass is documented in
[mir-passes]: mir/passes.md
[mir-instrument-coverage]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_mir_transform/src/coverage
[code-region]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/struct.CodeRegion.html
-[counter-coverage-kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Counter
-[expression-coverage-kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Expression
+[`CoverageKind::Counter`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Counter
+[`CoverageKind::Expression`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Expression
[coverage-statement]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.StatementKind.html#variant.Coverage
[instrument-coverage-pass-details]: #implementation-details-of-the-instrumentcoverage-mir-pass
@@ -223,7 +223,7 @@ details of the [_LLVM Coverage Mapping Format_][coverage-mapping-format]
(Version 6).[^llvm-and-covmap-versions]
[^llvm-and-covmap-versions]:
-The Rust compiler (as of <!-- date-check: --> Feb 2023) supports _LLVM Coverage Mapping Format_ 6.
+The Rust compiler (as of <!-- date-check: --> Jul 2023) supports _LLVM Coverage Mapping Format_ 6.
The Rust compiler will automatically use the most up-to-date coverage mapping format
version that is compatible with the compiler's built-in version of LLVM.
@@ -274,31 +274,42 @@ since it will not be called), and adds a new `FunctionCoverage`, with
## Testing LLVM Coverage
+[(See also the compiletest documentation for the `tests/coverage-map` and
+`tests/run-coverage` test suites.)](./tests/compiletest.md#coverage-tests)
+
Coverage instrumentation in the MIR is validated by a `mir-opt` test:
-[`instrument-coverage`][mir-opt-test].
+[`tests/mir-opt/instrument_coverage.rs`].
+
+Coverage instrumentation in LLVM IR is validated by the [`tests/coverage-map`]
+test suite. These tests compile a test program to LLVM IR assembly, and then
+use the [`src/tools/coverage-dump`] tool to extract and pretty-print the
+coverage mappings that would be embedded in the final binary.
-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 [`tests/run-coverage`] directory,
-together with the actual tests and expected results.
+End-to-end testing of coverage instrumentation and coverage reporting is
+performed by the [`tests/run-coverage`] and [`tests/run-coverage-rustdoc`]
+test suites. These tests compile and run a test program with coverage
+instrumentation, then use LLVM tools to convert the coverage data into a
+human-readable coverage report.
-Finally, the [`coverage-llvmir`] test compares compiles a simple Rust program
+Finally, the [`coverage-llvmir`] test compiles a simple Rust program
with `-C instrument-coverage` and compares the compiled program's LLVM IR to
expected LLVM IR instructions and structured data for a coverage-enabled
program, including various checks for Coverage Map-related metadata and the LLVM
intrinsic calls to increment the runtime counters.
-Expected results for both the `mir-opt` tests and the `coverage*` tests under
-`run-make-fulldeps` can be refreshed by running:
+Expected results for the `coverage-map`, `run-coverage`, `run-coverage-rustdoc`,
+and `mir-opt` tests can be refreshed by running:
```shell
-$ ./x test mir-opt --bless
-$ ./x test tests/run-make-fulldeps/coverage --bless
+./x test tests/*coverage* --bless
+./x test tests/mir-opt --bless
```
-[mir-opt-test]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/instrument_coverage.rs
+[`tests/mir-opt/instrument_coverage.rs`]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/instrument_coverage.rs
+[`tests/coverage-map`]: https://github.com/rust-lang/rust/tree/master/tests/coverage-map
+[`src/tools/coverage-dump`]: https://github.com/rust-lang/rust/tree/master/src/tools/coverage-dump
[`tests/run-coverage`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage
-[spanview-debugging]: compiler-debugging.md#viewing-spanview-output
+[`tests/run-coverage-rustdoc`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage-rustdoc
[`coverage-llvmir`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-llvmir
## Implementation Details of the `InstrumentCoverage` MIR Pass
@@ -310,7 +321,7 @@ function, generic, or closure), the `Instrumentor`'s constructor prepares a
[`inject_counters()`][inject-counters].
```rust
- Instrumentor::new(&self.name(), tcx, mir_body).inject_counters();
+Instrumentor::new(&self.name(), tcx, mir_body).inject_counters();
```
The `CoverageGraph` is a coverage-specific simplification of the MIR control
@@ -324,20 +335,14 @@ The `Instrumentor`'s `inject_counters()` uses the `CoverageGraph` to
compute the best places to inject coverage counters, as MIR `Statement`s,
with the following steps:
-1. Depending on the debugging configurations in `rustc`'s, `config.toml`,
- and `rustc` command line flags, various debugging features may be enabled
- to enhance `debug!()` messages in logs, and to generate various "dump" files,
- to help developers understand the MIR transformation process for coverage.
- Most of the debugging features are implemented in the [`debug`][debug]
- sub-module.
-2. [`generate_coverage_spans()`][generate-coverage-spans] computes the minimum set of distinct,
+1. [`generate_coverage_spans()`][generate-coverage-spans] computes the minimum set of distinct,
non-branching code regions, from the MIR. These `CoverageSpan`s
represent a span of code that must be counted.
-3. [`make_bcb_counters()`][make-bcb-counters] generates `CoverageKind::Counter`s and
+2. [`make_bcb_counters()`][make-bcb-counters] generates `CoverageKind::Counter`s and
`CoverageKind::Expression`s for each `CoverageSpan`, plus additional
`intermediate_expressions`[^intermediate-expressions], not associated with any `CodeRegion`, but
are required to compute a final `Expression` value for a `CodeRegion`.
-4. Inject the new counters into the MIR, as new `StatementKind::Coverage`
+3. Inject the new counters into the MIR, as new `StatementKind::Coverage`
statements. This is done by three distinct functions:
- `inject_coverage_span_counters()`
- `inject_indirect_counters()`
@@ -409,66 +414,12 @@ The BCB CFG is critical to simplifying the coverage analysis by ensuring graph p
queries (`is_dominated_by()`, `predecessors`, `successors`, etc.) have branch (control flow)
significance.
-To visualize the `CoverageGraph`, you can generate a _graphviz_ `*.dot`
-file with the following `rustc` flags:[^graphviz-dark-mode]
-
-[^graphviz-dark-mode]: This image also applies `-Z graphviz-dark-mode`, to
-produce a Graphviz document with "dark mode" styling. If you use a dark mode or
-theme in your development environment, you will probably want to use this
-option so you can review the graphviz output without straining your vision.
-
-```shell
-$ rustc -C instrument-coverage -Z dump-mir=InstrumentCoverage \
- -Z dump-mir-graphviz some_rust_source.rs
-```
-
-The `-Z dump-mir` flag requests [MIR debugging
-output][mir-debugging] (generating `*.mir` files, by default).
-`-Z dump-mir-graphviz` additionally generates `*.dot` files.
-`-Z dump-mir=InstrumentCoverage` restricts these files to the
-`InstrumentCoverage` pass. All files are written to the `./mir_dump/`
-directory, by default.
-
-Files with names ending in `.-------.InstrumentCoverage.0.dot` contain the
-_graphviz_ representations of a `CoverageGraph` (one for each MIR, that is,
-for each function and closure):
-
-<img alt="cropped image of a sample CoverageGraph in graphviz format"
- src="img/coverage-graphviz-01.png" style="border: 1px solid gray" class="center"/>
-<br/>
-
-This image shows each `BasicCoverageBlock` as a rectangular _node_, with
-directional edges (the arrows) leading from each node to its `successors()`.
-The nodes contain information in sections:
-
-1. The gray header has a label showing the BCB ID (or _index_ for looking up
- its `BasicCoverageBlockData`).
-2. The first content section shows the assigned `Counter` or `Expression` for
- each contiguous section of code. (There may be more than one `Expression`
- incremented by the same `Counter` for noncontiguous sections of code
- representing the same sequential actions.) Note the code is represented by
- the line and column ranges (for example: `52:28-52:33`, representing the
- original source line 52, for columns 28-33). These are followed by the MIR
- `Statement` or `Terminator` represented by that source range. (How these
- coverage regions are determined is discussed in the following section.)
-3. The final section(s) show the MIR `BasicBlock`s (by ID/index and its
- `TerminatorKind`) contained in this BCB. The last BCB is separated out
- because its `successors()` determine the edges leading out of the BCB, and
- into the `leading_bb()` (first `BasicBlock`) of each successor BCB.
-
-Note, to find the `BasicCoverageBlock` from a final BCB `Terminator`'s
-successor `BasicBlock`, there is an index and helper
-function--[`bcb_from_bb()`][bcb-from-bb]--to look up a `BasicCoverageBlock` from
-*any* contained `BasicBlock`.
-
[directed-graph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/trait.DirectedGraph.html
[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/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
### `CoverageSpans`
@@ -487,32 +438,6 @@ The final stage of `generate_coverage_spans()` is handled by
merges and de-duplicates them, and returns an optimal, minimal set of `CoverageSpan`s
that can be used to assign coverage `Counter`s or `Expression`s, one-for-one.
-An visual, interactive representation of the final `CoverageSpan`s can be
-generated with the following `rustc` flags:
-
-```shell
-$ rustc -C instrument-coverage -Z dump-mir=InstrumentCoverage \
- -Z dump-mir-spanview some_rust_source.rs
-```
-
-These flags request Spanview output for the `InstrumentCoverage` pass, and the
-resulting files (one for each MIR, that is, for each function or closure) can be
-found in the `mir_dump` directory (by default), with the extension:
-`.-------.InstrumentCoverage.0.html`.
-
-<img alt="cropped image of a sample Spanview in a browser"
- src="img/coverage-spanview-01.png" style="border: 1px solid gray" class="center"/>
-<br/>
-
-The image above shows one such example. The orange and blue backgrounds
-highlight alternating `CoverageSpan`s from the refined set. Hovering over a
-line expands the output on that line to show the MIR `BasicBlock` IDs covered
-by each `CoverageSpan`. While hovering, the `CoverageSpan` under the pointer
-also has a _tooltip_ block of text, showing even more detail, including the
-MIR `Statement`s and `Terminator`s contributing to the `CoverageSpan`, and
-their individual `Span`s (which should be encapsulated within the code region
-of the refined `CoverageSpan`)
-
[coverage-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html
[coverage-span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpan.html
[to-refined-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html#method.to_refined_spans
@@ -611,12 +536,3 @@ so the counter is only incremented when traversing the branch edge.
[inject-coverage-span-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_coverage_span_counters
[inject-indirect-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_indirect_counters
[inject-intermediate-expression]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/fn.inject_intermediate_expression.html
-
-### Additional Debugging Support
-
-See the
-[crate documentation for `rustc_mir::transform::coverage::debug`][coverage-debugging]
-for a detailed description of the debug output, logging, and configuration options
-available to developers working on the `InstrumentCoverage` pass.
-
-[coverage-debugging]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/debug/index.html
diff --git a/src/doc/rustc-dev-guide/src/memory.md b/src/doc/rustc-dev-guide/src/memory.md
index e5122deb2..4072d4f33 100644
--- a/src/doc/rustc-dev-guide/src/memory.md
+++ b/src/doc/rustc-dev-guide/src/memory.md
@@ -40,16 +40,16 @@ to that buffer is freed and our `'tcx` references would be invalid.
In addition to types, there are a number of other arena-allocated data structures that you can
allocate, and which are found in this module. Here are a few examples:
-- [`Substs`][subst], allocated with `mk_substs` – this will intern a slice of types, often used to
- specify the values to be substituted for generics (e.g. `HashMap<i32, u32>` would be represented
- as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`).
+- [`GenericArgs`], allocated with `mk_args` – this will intern a slice of types, often used
+to specify the values to be substituted for generics args (e.g. `HashMap<i32, u32>` would be
+represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`).
- [`TraitRef`], typically passed by value – a **trait reference** consists of a reference to a trait
along with its various type parameters (including `Self`), like `i32: Display` (here, the def-id
- would reference the `Display` trait, and the substs would contain `i32`). Note that `def-id` is
+ would reference the `Display` trait, and the args would contain `i32`). Note that `def-id` is
defined and discussed in depth in the `AdtDef and DefId` section.
- [`Predicate`] defines something the trait system has to prove (see `traits` module).
-[subst]: ./generic_arguments.html#subst
+[`GenericArgs`]: ./generic_arguments.html#GenericArgs
[`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TraitRef.html
[`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html
diff --git a/src/doc/rustc-dev-guide/src/mir/index.md b/src/doc/rustc-dev-guide/src/mir/index.md
index dc0be167b..36733c598 100644
--- a/src/doc/rustc-dev-guide/src/mir/index.md
+++ b/src/doc/rustc-dev-guide/src/mir/index.md
@@ -62,6 +62,12 @@ show you the MIR for your program. Try putting this program into play
button on the top:
[sample-play]: https://play.rust-lang.org/?gist=30074856e62e74e91f06abd19bd72ece&version=stable
+MIR shown by above link is optimized.
+Some statements like `StorageLive` are removed in optimization.
+This happens because the compiler notices the value is never accessed in the code.
+We can use `rustc [filename].rs -Z mir-opt-level=0 --emit mir` to view unoptimized MIR.
+This requires the nightly toolchain.
+
```rust
fn main() {
@@ -249,7 +255,75 @@ but [you can read about those below](#promoted)).
## Representing constants
-*to be written*
+When code has reached the MIR stage, constants can generally come in two forms:
+*MIR constants* ([`mir::Constant`]) and *type system constants* ([`ty::Const`]).
+MIR constants are used as operands: in `x + CONST`, `CONST` is a MIR constant;
+similarly, in `x + 2`, `2` is a MIR constant. Type system constants are used in
+the type system, in particular for array lengths but also for const generics.
+
+Generally, both kinds of constants can be "unevaluated" or "already evaluated".
+And unevaluated constant simply stores the `DefId` of what needs to be evaluated
+to compute this result. An evaluated constant (a "value") has already been
+computed; their representation differs between type system constants and MIR
+constants: MIR constants evaluate to a `mir::ConstValue`; type system constants
+evaluate to a `ty::ValTree`.
+
+Type system constants have some more variants to support const generics: they
+can refer to local const generic parameters, and they are subject to inference.
+Furthermore, the `mir::Constant::Ty` variant lets us use an arbitrary type
+system constant as a MIR constant; this happens whenever a const generic
+parameter is used as an operand.
+
+### MIR constant values
+
+In general, a MIR constant value (`mir::ConstValue`) was computed by evaluating
+some constant the user wrote. This [const evaluation](../const-eval.md) produces
+a very low-level representation of the result in terms of individual bytes. We
+call this an "indirect" constant (`mir::ConstValue::Indirect`) since the value
+is stored in-memory.
+
+However, storing everything in-memory would be awfully inefficient. Hence there
+are some other variants in `mir::ConstValue` that can represent certain simple
+and common values more efficiently. In particular, everything that can be
+directly written as a literal in Rust (integers, floats, chars, bools, but also
+`"string literals"` and `b"byte string literals"`) has an optimized variant that
+avoids the full overhead of the in-memory representation.
+
+### ValTrees
+
+An evaluated type system constant is a "valtree". The `ty::ValTree` datastructure
+allows us to represent
+
+* arrays,
+* many structs,
+* tuples,
+* enums and,
+* most primitives.
+
+The most important rule for
+this representation is that every value must be uniquely represented. In other
+words: a specific value must only be representable in one specific way. For example: there is only
+one way to represent an array of two integers as a `ValTree`:
+`ValTree::Branch(&[ValTree::Leaf(first_int), ValTree::Leaf(second_int)])`.
+Even though theoretically a `[u32; 2]` could be encoded in a `u64` and thus just be a
+`ValTree::Leaf(bits_of_two_u32)`, that is not a legal construction of `ValTree`
+(and is very complex to do, so it is unlikely anyone is tempted to do so).
+
+These rules also mean that some values are not representable. There can be no `union`s in type
+level constants, as it is not clear how they should be represented, because their active variant
+is unknown. Similarly there is no way to represent raw pointers, as addresses are unknown at
+compile-time and thus we cannot make any assumptions about them. References on the other hand
+*can* be represented, as equality for references is defined as equality on their value, so we
+ignore their address and just look at the backing value. We must make sure that the pointer values
+of the references are not observable at compile time. We thus encode `&42` exactly like `42`.
+Any conversion from
+valtree back a to MIR constant value must reintroduce an actual indirection. At codegen time the
+addresses may be deduplicated between multiple uses or not, entirely depending on arbitrary
+optimization choices.
+
+As a consequence, all decoding of `ValTree` must happen by matching on the type first and making
+decisions depending on that. The value itself gives no useful information without the type that
+belongs to it.
<a name="promoted"></a>
@@ -277,3 +351,5 @@ See the const-eval WG's [docs on promotion](https://github.com/rust-lang/const-e
[`ProjectionElem::Deref`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.ProjectionElem.html#variant.Deref
[`Rvalue`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.Rvalue.html
[`Operand`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.Operand.html
+[`mir::Constant`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Constant.html
+[`ty::Const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Const.html
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
index 2ad9494e8..03c7fb6b7 100644
--- 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
@@ -34,7 +34,7 @@ We record `lifetime_mapping`s for the opaque type, described below.
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
+is so they can be used as generic args 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.
@@ -355,7 +355,7 @@ error[E0308]: mismatched types
#### Well-formedness checking
-We check well-formedness of RPITITs just like regular associated types.
+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
diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md
index e78c4bb25..c35f01549 100644
--- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md
+++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md
@@ -26,7 +26,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
| rbv::ResolvedArg::Free(_, node_id),
) = def
{
- if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
+ if let Some(lt) = cx.args.get(&node_id).and_then(|p| p.as_lt()).cloned() {
return lt;
}
}
@@ -109,7 +109,7 @@ Here is the list of passes as of <!-- date-check --> March 2023:
`Go to https://example.com/.` It suggests wrapping the link with angle brackets:
`Go to <https://example.com/>.` to linkify it. This is the code behind the <!--
date-check: may 2022 --> `rustdoc::bare_urls` lint.
-
+
- `check_code_block_syntax` validates syntax inside Rust code blocks
(<code>```rust</code>)
diff --git a/src/doc/rustc-dev-guide/src/serialization.md b/src/doc/rustc-dev-guide/src/serialization.md
index 78b065311..c79628106 100644
--- a/src/doc/rustc-dev-guide/src/serialization.md
+++ b/src/doc/rustc-dev-guide/src/serialization.md
@@ -108,7 +108,7 @@ and `Encodable`.
- `MetadataEncodable` and `MetadataDecodable` generate implementations that
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`.
+ that contain `rustc_metadata::rmeta::Lazy*`.
- `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
@@ -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>` types provide some functionality over
+The `LazyArray<[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/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md
index 86ebe3a49..5cacb3013 100644
--- a/src/doc/rustc-dev-guide/src/tests/compiletest.md
+++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md
@@ -67,6 +67,12 @@ The following test suites are available, with links for more information:
- `run-make-fulldeps` — `run-make` tests which require a linkable build of `rustc`,
or the rust demangler
- [`run-pass-valgrind`](#valgrind-tests) — tests run with Valgrind
+- [`coverage-map`](#coverage-tests) - tests for coverage maps produced by
+ coverage instrumentation
+- [`run-coverage`](#coverage-tests) - tests that run an instrumented program
+ and check its coverage report
+- [`run-coverage-rustdoc`](#coverage-tests) - coverage tests that also run
+ instrumented doctests
- [Rustdoc tests](../rustdoc.md#tests):
- `rustdoc` — tests for rustdoc, making sure that the generated files
contain the expected documentation.
@@ -394,6 +400,55 @@ These may be removed in the future.
[`tests/run-pass-valgrind`]: https://github.com/rust-lang/rust/tree/master/tests/run-pass-valgrind
+### Coverage tests
+
+The tests in [`tests/coverage-map`] test the mappings between source code
+regions and coverage counters that are emitted by LLVM.
+They compile the test with `--emit=llvm-ir`,
+then use a custom tool ([`src/tools/coverage-dump`])
+to extract and pretty-print the coverage mappings embedded in the IR.
+These tests don't require the profiler runtime, so they run in PR CI jobs and
+are easy to run/bless locally.
+
+These coverage map tests can be sensitive to changes in MIR lowering or MIR
+optimizations, producing mappings that are different but produce identical
+coverage reports.
+
+As a rule of thumb, any PR that doesn't change coverage-specific
+code should **feel free to re-bless** the `coverage-map` tests as necessary,
+without worrying about the actual changes, as long as the `run-coverage` tests
+still pass.
+
+---
+
+The tests in [`tests/run-coverage`] perform an end-to-end test of coverage reporting.
+They compile a test program with coverage instrumentation, run that program to
+produce raw coverage data, and then use LLVM tools to process that data into a
+human-readable code coverage report.
+
+Instrumented binaries need to be linked against the LLVM profiler runtime,
+so `run-coverage` tests are **automatically skipped**
+unless the profiler runtime is enabled in `config.toml`:
+
+```toml
+# config.toml
+[build]
+profiler = true
+```
+
+This also means that they typically don't run in PR CI jobs,
+though they do run as part of the full set of CI jobs used for merging.
+
+The tests in [`tests/run-coverage-rustdoc`] also run instrumented doctests and
+include them in the coverage report. This avoids having to build rustdoc when
+only running the main `run-coverage` suite.
+
+[`tests/coverage-map`]: https://github.com/rust-lang/rust/tree/master/tests/coverage-map
+[`src/tools/coverage-dump`]: https://github.com/rust-lang/rust/tree/master/src/tools/coverage-dump
+[`tests/run-coverage`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage
+[`tests/run-coverage-rustdoc`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage-rustdoc
+
+
## Building auxiliary crates
It is common that some tests require additional auxiliary crates to be compiled.
@@ -467,9 +522,6 @@ fn main() {
## Revisions
-Certain classes of tests support "revisions" (as of <!-- date-check --> July 2022,
-this includes UI, assembly, codegen, debuginfo, incremental, and rustdoc UI tests,
-though incremental tests are somewhat different).
Revisions allow a single test file to be used for multiple tests.
This is done by adding a special header at the top of the file:
@@ -503,6 +555,15 @@ 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.
+<!-- date-check jul 2023 -->
+Following is classes of tests that support revisions:
+- UI
+- assembly
+- codegen
+- debuginfo
+- rustdoc UI tests
+- incremental (these are special in that they inherently cannot be run in parallel)
+
## Compare modes
Compiletest can be run in different modes, called _compare modes_, which can
diff --git a/src/doc/rustc-dev-guide/src/turbofishing-and-early-late-bound.md b/src/doc/rustc-dev-guide/src/turbofishing-and-early-late-bound.md
new file mode 100644
index 000000000..a1d8a64e8
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/turbofishing-and-early-late-bound.md
@@ -0,0 +1,120 @@
+# Turbofishing's interactions with early/late bound parameters
+
+The early/late bound parameter distinction on functions introduces some complications
+when providing generic arguments to functions. This document discusses what those are
+and how they might interact with future changes to make more things late bound.
+
+## Can't turbofish generic arguments on functions sometimes
+
+When a function has any late bound lifetime parameters (be they explicitly defined or
+implicitly introduced via lifetime elision) we disallow specifying any lifetime arguments
+on the function. Sometimes this is a hard error other times it is a future compat lint
+([`late_bound_lifetime_arguments`](https://github.com/rust-lang/rust/issues/42868)).
+
+```rust
+fn early<'a: 'a>(a: &'a ()) -> &'a () { a }
+fn late<'a>(a: &'a ()) -> &'a () { a }
+
+fn mixed<'a, 'b: 'b>(a: &'a (), b: &'b ()) -> &'a () { a }
+
+struct Foo;
+impl Foo {
+ fn late<'a>(self, a: &'a ()) -> &'a () { a }
+}
+
+fn main() {
+ // fine
+ let f = early::<'static>;
+
+ // some variation of hard errors and future compat lints
+ Foo.late::<'static>(&());
+ let f = late::<'static>;
+ let f = mixed::<'static, 'static>;
+ let f = mixed::<'static>;
+ late::<'static>(&());
+}
+```
+
+The justification for this is that late bound parameters are not present on the
+`FnDef` so the arguments to late bound parameters can't be present in the substs
+for the type. i.e. the `late` function in the above code snippet would not have
+any generic parameters on the `FnDef` zst:
+```rust
+// example desugaring of the `late` function and its zst + builtin Fn impl
+struct LateFnDef;
+impl<'a> Fn<(&'a ())> for LateFnDef {
+ type Output = &'a ();
+ ...
+}
+```
+
+The cause for some situations giving future compat lints and others giving hard errors
+is a little arbitrary but explainable:
+- It's always a hard error for method calls
+- It's only a hard error on paths to free functions if there is no unambiguous way to
+create the substs for the fndef from the lifetime arguments. (i.e. the amount of
+lifetimes provided must be exactly equal to the amount of early bound lifetimes or
+else it's a hard error)
+
+## Back compat issues from turning early bound to late bound
+
+Because of the previously mentioned restriction on turbofishing generic arguments, it
+is a breaking change to upgrade a lifetime from early bound to late bound as it can cause
+existing turbofishies to become hard errors/future compat lints.
+
+Many t-types members have expressed interest in wanting more parameters to be late bound.
+We cannot do so if making something late bound is going to break code that many would
+expect to work (judging by the future compat lint issue many people do expect to be able
+to turbofish late bound parameters).
+
+## Interactions with late bound type/const parameters
+
+If we were to make some type/const parameters late bound we would definitely not want
+to disallow turbofishing them as it presumably(?) would break a Tonne of code.
+
+While lifetimes do differ from type/consts in some ways I(BoxyUwU) do not believe there
+is any justification for why it would make sense to allow turbofishing late bound
+type/const parameters but not late bound lifetimes.
+
+## Removing the hard error/fcw
+
+From reasons above it seems reasonable that we may want to remove the hard error and fcw
+(removing the errors/fcw is definitely a blocker for making more things late bound).
+
+example behaviour:
+```rust
+fn late<'a>(a: &'a ()) -> &'a () { a }
+
+fn accepts_fn(_: impl for<'a> Fn(&'a ()) -> &'a ()) {}
+fn accepts_fn_2(_: impl Fn(&'static ()) -> &'static ()) {}
+
+fn main() {
+ let f = late::<'static>;
+
+ accepts_fn(f); //~ error: `f` doesnt implement `for<'a> Fn(&'a ()) -> &'a ()`
+ accepts_fn_2(f) // works
+
+ accepts_fn(late) // works
+}
+````
+
+one potential complication is that we would want a way to specify a generic argument
+to a function without having to specify arguments for all previous parameters. i.e.
+ideally you could write the following code somehow.
+```rust
+fn late<'a, 'b>(_: &'a (), _: &'b ()) {}
+
+fn accepts_fn(_: impl for<'a> Fn(&'a (), &'static ())) {}
+
+fn main() {
+ // a naive implementation would have a `ReInfer` as the subst for `'a` parameter
+ // no longer allowing the FnDef to satisfy the `for<'a> Fn(&'a ()` bound
+ let f = late::<'_, 'static>;
+ accepts_fn(f);
+}
+```
+Maybe we can just special case astconv for `_`/`'_` arguments for late bound parameters somehow
+and have it not mean the same thing as `_` for early bound parameters. Regardless I think we
+would need a solution that would allow writing the above code even if it was done by some new
+syntax such as havign to write `late::<k#no_argument, 'static>` (naturally `k#no_argument`
+would only make sense as an argument to late bound parameters).
diff --git a/src/doc/rustc-dev-guide/src/ty.md b/src/doc/rustc-dev-guide/src/ty.md
index 4a6cdb7c7..b7a2ba8e4 100644
--- a/src/doc/rustc-dev-guide/src/ty.md
+++ b/src/doc/rustc-dev-guide/src/ty.md
@@ -74,9 +74,9 @@ HIR is built, some basic type inference and type checking is done. During the ty
figure out what the `ty::Ty` of everything is and we also check if the type of something is
ambiguous. The `ty::Ty` is then used for type checking while making sure everything has the
expected type. The [`astconv` module][astconv] is where the code responsible for converting a
-`rustc_hir::Ty` into a `ty::Ty` is located. This occurs during the type-checking phase,
-but also in other parts of the compiler that want to ask questions like "what argument types does
-this function expect?"
+`rustc_hir::Ty` into a `ty::Ty` is located. The main routine used is `ast_ty_to_ty`. This occurs
+during the type-checking phase, but also in other parts of the compiler that want to ask
+questions like "what argument types does this function expect?"
[astconv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/astconv/index.html
@@ -137,11 +137,13 @@ benefits of interning.
## Allocating and working with types
-To allocate a new type, you can use the various `mk_` methods defined on the `tcx`. These have names
+To allocate a new type, you can use the various `new_*` methods defined on
+[`Ty`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html).
+These have names
that correspond mostly to the various kinds of types. For example:
```rust,ignore
-let array_ty = tcx.mk_array(elem_ty, len * 2);
+let array_ty = Ty::new_array_with_const_len(tcx, ty, count);
```
These methods all return a `Ty<'tcx>` – note that the lifetime you get back is the lifetime of the
@@ -198,11 +200,11 @@ the function calls if one is available in some place (like during type checking)
If no inference context is available at all, then one can be created as described in
[type-inference]. But this is only useful when the involved types (for example, if
they came from a query like `tcx.type_of()`) are actually substituted with fresh
-inference variables using [`fresh_substs_for_item`]. This can be used to answer questions
+inference variables using [`fresh_args_for_item`]. This can be used to answer questions
like "can `Vec<T>` for any `T` be unified with `Vec<u32>`?".
[type-inference]: ./type-inference.md#creating-an-inference-context
-[`fresh_substs_for_item`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.fresh_substs_for_item
+[`fresh_args_for_item`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.fresh_substs_for_item
## `ty::TyKind` Variants
@@ -285,7 +287,7 @@ struct MyStruct<T> { x: u32, y: T }
The type `MyStruct<u32>` would be an instance of `TyKind::Adt`:
```rust,ignore
-Adt(&'tcx AdtDef, SubstsRef<'tcx>)
+Adt(&'tcx AdtDef, GenericArgsRef<'tcx>)
// ------------ ---------------
// (1) (2)
//
@@ -299,12 +301,12 @@ There are two parts:
parameters. In our example, this is the `MyStruct` part *without* the argument `u32`.
(Note that in the HIR, structs, enums and unions are represented differently, but in `ty::Ty`,
they are all represented using `TyKind::Adt`.)
-- The [`SubstsRef`][substsref] is an interned list of values that are to be substituted for the
- generic parameters. In our example of `MyStruct<u32>`, we would end up with a list like `[u32]`.
- We’ll dig more into generics and substitutions in a little bit.
+- The [`GenericArgsRef`][GenericArgsRef] is an interned list of values that are to be substituted
+for the generic parameters. In our example of `MyStruct<u32>`, we would end up with a list like
+`[u32]`. We’ll dig more into generics and substitutions in a little bit.
[adtdef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.AdtDef.html
-[substsref]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/type.SubstsRef.html
+[GenericArgsRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/type.GenericArgsRef.html
**`AdtDef` and `DefId`**
@@ -361,13 +363,13 @@ delaying a redundant span bug.
## Question: Why not substitute “inside” the `AdtDef`?
-Recall that we represent a generic struct with `(AdtDef, substs)`. So why bother with this scheme?
+Recall that we represent a generic struct with `(AdtDef, args)`. So why bother with this scheme?
Well, the alternate way we could have chosen to represent types would be to always create a new,
fully-substituted form of the `AdtDef` where all the types are already substituted. This seems like
-less of a hassle. However, the `(AdtDef, substs)` scheme has some advantages over this.
+less of a hassle. However, the `(AdtDef, args)` scheme has some advantages over this.
-First, `(AdtDef, substs)` scheme has an efficiency win:
+First, `(AdtDef, args)` scheme has an efficiency win:
```rust,ignore
struct MyStruct<T> {
diff --git a/src/doc/rustc-dev-guide/src/early-late-bound.md b/src/doc/rustc-dev-guide/src/what-does-early-late-bound-mean.md
index 8fb856742..9a6a0b139 100644
--- a/src/doc/rustc-dev-guide/src/early-late-bound.md
+++ b/src/doc/rustc-dev-guide/src/what-does-early-late-bound-mean.md
@@ -1,8 +1,8 @@
# Early and Late Bound Parameter Definitions
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)
+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>`.
@@ -21,7 +21,7 @@ fn foo<'a>(_: &'a u32) {}
fn main() {
let b = foo;
- // ^ `b` has type `FnDef(foo, [])` (no substs because `'a` is late bound)
+ // ^ `b` has type `FnDef(foo, [])` (no args because `'a` is late bound)
assert!(std::mem::size_of_val(&b) == 0);
}
```
@@ -38,7 +38,7 @@ fn main() {
}
```
-Because late bound parameters are not part of the `FnDef`'s substs this allows us to prove trait
+Because late bound parameters are not part of the `FnDef`'s args 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) {}
@@ -52,7 +52,7 @@ fn main() {
// 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);
}
@@ -85,7 +85,7 @@ making `generics_of` behave this way.
## What parameters are currently late bound
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
+keeping in mind that these are not necessarily set in stone and it is almost certainly possible to
be more flexible.
### Must be a lifetime parameter
@@ -161,7 +161,7 @@ this is simpler than the rules for checking impl headers constrain all the param
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).
-The requirement that they not indirectly be in the substs of an alias for it to count is the
+The requirement that they not indirectly be in the args 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 }
@@ -174,13 +174,13 @@ same is true of the builtin `Fn*` impls.
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
+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:
+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.
+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