summaryrefslogtreecommitdiffstats
path: root/src/doc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:42 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:42 +0000
commitcec1877e180393eba0f6ddb0cf97bf3a791631c7 (patch)
tree47b4dac2a9dd9a40c30c251b4d4a72d7ccf77e9f /src/doc
parentAdding debian version 1.74.1+dfsg1-1. (diff)
downloadrustc-cec1877e180393eba0f6ddb0cf97bf3a791631c7.tar.xz
rustc-cec1877e180393eba0f6ddb0cf97bf3a791631c7.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/doc')
-rw-r--r--src/doc/book/redirects/compiler-plugins.md11
-rw-r--r--src/doc/book/src/ch02-00-guessing-game-tutorial.md4
-rw-r--r--src/doc/embedded-book/src/start/hardware.md3
-rw-r--r--src/doc/guide-plugins.md3
-rw-r--r--src/doc/nomicon/src/exception-safety.md2
-rw-r--r--src/doc/reference/src/attributes.md4
-rw-r--r--src/doc/reference/src/attributes/codegen.md60
-rw-r--r--src/doc/reference/src/behavior-considered-undefined.md46
-rw-r--r--src/doc/reference/src/destructors.md6
-rw-r--r--src/doc/reference/src/expressions/operator-expr.md10
-rw-r--r--src/doc/reference/src/inline-assembly.md4
-rw-r--r--src/doc/reference/src/items/traits.md2
-rw-r--r--src/doc/reference/src/types/impl-trait.md10
-rw-r--r--src/doc/reference/src/types/textual.md4
-rw-r--r--src/doc/rust-by-example/src/SUMMARY.md4
-rw-r--r--src/doc/rust-by-example/src/attribute.md32
-rw-r--r--src/doc/rust-by-example/src/custom_types/constants.md2
-rw-r--r--src/doc/rust-by-example/src/error/option_unwrap/question_mark.md3
-rw-r--r--src/doc/rust-by-example/src/flow_control/while_let.md34
-rw-r--r--src/doc/rust-by-example/src/fn/closures.md4
-rw-r--r--src/doc/rust-by-example/src/fn/hof.md2
-rw-r--r--src/doc/rust-by-example/src/meta/doc.md9
-rw-r--r--src/doc/rust-by-example/src/meta/playground.md15
-rw-r--r--src/doc/rust-by-example/src/primitives/array.md2
-rw-r--r--src/doc/rust-by-example/src/scope/lifetime.md2
-rw-r--r--src/doc/rust-by-example/src/scope/move.md2
-rw-r--r--src/doc/rust-by-example/src/std/hash/alt_key_types.md2
-rw-r--r--src/doc/rust-by-example/src/std_misc/arg/matching.md3
-rw-r--r--src/doc/rust-by-example/src/std_misc/file/read_lines.md8
-rw-r--r--src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md2
-rw-r--r--src/doc/rustc-dev-guide/examples/rustc-driver-example.rs2
-rw-r--r--src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs2
-rw-r--r--src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs2
-rw-r--r--src/doc/rustc-dev-guide/src/SUMMARY.md2
-rw-r--r--src/doc/rustc-dev-guide/src/appendix/bibliography.md2
-rw-r--r--src/doc/rustc-dev-guide/src/appendix/glossary.md2
-rw-r--r--src/doc/rustc-dev-guide/src/building/suggested.md1
-rw-r--r--src/doc/rustc-dev-guide/src/effects.md66
-rw-r--r--src/doc/rustc-dev-guide/src/feature-gates.md12
-rw-r--r--src/doc/rustc-dev-guide/src/hir-debugging.md9
-rw-r--r--src/doc/rustc-dev-guide/src/implementing_new_features.md6
-rw-r--r--src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md123
-rw-r--r--src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md18
-rw-r--r--src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md2
-rw-r--r--src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md2
-rw-r--r--src/doc/rustc-dev-guide/src/solve/invariants.md154
-rw-r--r--src/doc/rustc-dev-guide/src/solve/the-solver.md73
-rw-r--r--src/doc/rustc-dev-guide/src/solve/trait-solving.md71
-rw-r--r--src/doc/rustc-dev-guide/src/stabilization_guide.md2
-rw-r--r--src/doc/rustc-dev-guide/src/tests/headers.md2
-rw-r--r--src/doc/rustc-dev-guide/src/traits/unsize.md84
-rw-r--r--src/doc/rustc/src/SUMMARY.md3
-rw-r--r--src/doc/rustc/src/codegen-options/index.md8
-rw-r--r--src/doc/rustc/src/exploit-mitigations.md404
-rw-r--r--src/doc/rustc/src/images/image1.pngbin15293 -> 164896 bytes
-rw-r--r--src/doc/rustc/src/images/image2.pngbin28772 -> 155307 bytes
-rw-r--r--src/doc/rustc/src/images/image3.pngbin19069 -> 19936 bytes
-rw-r--r--src/doc/rustc/src/platform-support.md73
-rw-r--r--src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md2
-rw-r--r--src/doc/rustc/src/platform-support/aix.md26
-rw-r--r--src/doc/rustc/src/platform-support/android.md16
-rw-r--r--src/doc/rustc/src/platform-support/apple-tvos.md4
-rw-r--r--src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md137
-rw-r--r--src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md24
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md4
-rw-r--r--src/doc/rustc/src/platform-support/mips-release-6.md2
-rw-r--r--src/doc/rustc/src/platform-support/nto-qnx.md2
-rw-r--r--src/doc/rustc/src/platform-support/openharmony.md2
-rw-r--r--src/doc/rustc/src/platform-support/unknown-uefi.md10
-rw-r--r--src/doc/rustc/src/profile-guided-optimization.md23
-rw-r--r--src/doc/rustdoc/src/advanced-features.md20
-rw-r--r--src/doc/rustdoc/src/unstable-features.md19
-rw-r--r--src/doc/rustdoc/src/write-documentation/what-to-include.md4
-rw-r--r--src/doc/unstable-book/src/compiler-flags/check-cfg.md216
-rw-r--r--src/doc/unstable-book/src/compiler-flags/no-jump-tables.md19
-rw-r--r--src/doc/unstable-book/src/compiler-flags/remap-path-scope.md24
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md161
-rw-r--r--src/doc/unstable-book/src/language-features/closure-track-caller.md4
-rw-r--r--src/doc/unstable-book/src/language-features/coroutines.md246
-rw-r--r--src/doc/unstable-book/src/language-features/diagnostic-namespace.md84
-rw-r--r--src/doc/unstable-book/src/language-features/generators.md246
-rw-r--r--src/doc/unstable-book/src/language-features/plugin.md114
-rw-r--r--src/doc/unstable-book/src/language-features/string-deref-patterns.md45
-rw-r--r--src/doc/unstable-book/src/the-unstable-book.md18
84 files changed, 1752 insertions, 1140 deletions
diff --git a/src/doc/book/redirects/compiler-plugins.md b/src/doc/book/redirects/compiler-plugins.md
index 66061adf5..67187f5f6 100644
--- a/src/doc/book/redirects/compiler-plugins.md
+++ b/src/doc/book/redirects/compiler-plugins.md
@@ -2,12 +2,5 @@
<small>There is a new edition of the book and this is an old link.</small>
-> Compiler plugins are user-provided libraries that extend the compiler's behavior with new syntax extensions, lint checks, etc.
-
----
-
-This particular chapter has moved to [the Unstable Book][2].
-
-* **[In the Unstable Rust Book: `plugin`][2]**
-
-[2]: ../unstable-book/language-features/plugin.html
+> Compiler plugins were user-provided libraries that extended the compiler's behavior in certain ways.
+> Support for them has been removed.
diff --git a/src/doc/book/src/ch02-00-guessing-game-tutorial.md b/src/doc/book/src/ch02-00-guessing-game-tutorial.md
index 4f2857333..5e27fb114 100644
--- a/src/doc/book/src/ch02-00-guessing-game-tutorial.md
+++ b/src/doc/book/src/ch02-00-guessing-game-tutorial.md
@@ -930,8 +930,8 @@ discusses structs and method syntax, and Chapter 6 explains how enums work.
[randcrate]: https://crates.io/crates/rand
[semver]: http://semver.org
[cratesio]: https://crates.io/
-[doccargo]: http://doc.crates.io
-[doccratesio]: http://doc.crates.io/crates-io.html
+[doccargo]: https://doc.rust-lang.org/cargo/
+[doccratesio]: https://doc.rust-lang.org/cargo/reference/publishing.html
[match]: ch06-02-match.html
[shadowing]: ch03-01-variables-and-mutability.html#shadowing
[parse]: ../std/primitive.str.html#method.parse
diff --git a/src/doc/embedded-book/src/start/hardware.md b/src/doc/embedded-book/src/start/hardware.md
index 8166e62e5..ba9fe6e76 100644
--- a/src/doc/embedded-book/src/start/hardware.md
+++ b/src/doc/embedded-book/src/start/hardware.md
@@ -64,6 +64,9 @@ target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
```
We'll use `thumbv7em-none-eabihf` as that covers the Cortex-M4F core.
+> **NOTE**: As you may remember from the previous chapter, we have to install
+> all targets and this is a new one. So don't forget to run the installation
+> process `rustup target add thumbv7em-none-eabihf` for this target.
The second step is to enter the memory region information into the `memory.x`
file.
diff --git a/src/doc/guide-plugins.md b/src/doc/guide-plugins.md
index 6c5115487..ccb9bb2ee 100644
--- a/src/doc/guide-plugins.md
+++ b/src/doc/guide-plugins.md
@@ -1,4 +1,3 @@
% The (old) Rust Compiler Plugins Guide
-This content has moved into
-[the Unstable Book](unstable-book/language-features/plugin.html).
+Support for plugins has been removed.
diff --git a/src/doc/nomicon/src/exception-safety.md b/src/doc/nomicon/src/exception-safety.md
index 8404bb859..762b38b98 100644
--- a/src/doc/nomicon/src/exception-safety.md
+++ b/src/doc/nomicon/src/exception-safety.md
@@ -172,7 +172,7 @@ impl<'a, T> Hole<'a, T> {
fn removed(&self) -> &T { self.elt.as_ref().unwrap() }
- unsafe fn get(&self, index: usize) -> &T { &self.data[index] }
+ fn get(&self, index: usize) -> &T { &self.data[index] }
unsafe fn move_to(&mut self, index: usize) {
let index_ptr: *const _ = &self.data[index];
diff --git a/src/doc/reference/src/attributes.md b/src/doc/reference/src/attributes.md
index 92ce1cd09..a1ad5c60c 100644
--- a/src/doc/reference/src/attributes.md
+++ b/src/doc/reference/src/attributes.md
@@ -275,8 +275,8 @@ The following is an index of all built-in attributes.
- [`debugger_visualizer`] — Embeds a file that specifies debugger output for a type.
[Doc comments]: comments.md#doc-comments
-[ECMA-334]: https://www.ecma-international.org/publications/standards/Ecma-334.htm
-[ECMA-335]: https://www.ecma-international.org/publications/standards/Ecma-335.htm
+[ECMA-334]: https://www.ecma-international.org/publications-and-standards/standards/ecma-334/
+[ECMA-335]: https://www.ecma-international.org/publications-and-standards/standards/ecma-335/
[Expression Attributes]: expressions.md#expression-attributes
[IDENTIFIER]: identifiers.md
[RAW_STRING_LITERAL]: tokens.md#raw-string-literals
diff --git a/src/doc/reference/src/attributes/codegen.md b/src/doc/reference/src/attributes/codegen.md
index c929f979c..7a50fe26f 100644
--- a/src/doc/reference/src/attributes/codegen.md
+++ b/src/doc/reference/src/attributes/codegen.md
@@ -204,6 +204,66 @@ Feature | Implicitly Enables | Feature Name
`tme` | | FEAT_TME - Transactional Memory Extension
`vh` | | FEAT_VHE - Virtualization Host Extensions
+#### `riscv32` or `riscv64`
+
+This platform requires that `#[target_feature]` is only applied to [`unsafe`
+functions][unsafe function].
+
+Further documentation on these features can be found in their respective
+specification. Many specifications are described in the [RISC-V ISA Manual] or
+in another manual hosted on the [RISC-V GitHub Account].
+
+[RISC-V ISA Manual]: https://github.com/riscv/riscv-isa-manual
+[RISC-V GitHub Account]: https://github.com/riscv
+
+Feature | Implicitly Enables | Description
+------------|---------------------|-------------------
+`a` | | [A][rv-a] — Atomic instructions
+`c` | | [C][rv-c] — Compressed instructions
+`m` | | [M][rv-m] — Integer Multiplication and Division instructions
+`zb` | `zba`, `zbc`, `zbs` | [Zb][rv-zb] — Bit Manipulation instructions
+`zba` | | [Zba][rv-zb-zba] — Address Generation instructions
+`zbb` | | [Zbb][rv-zb-zbb] — Basic bit-manipulation
+`zbc` | | [Zbc][rv-zb-zbc] — Carry-less multiplication
+`zbkb` | | [Zbkb][rv-zb-zbkb] — Bit Manipulation Instructions for Cryptography
+`zbkc` | | [Zbkc][rv-zb-zbc] — Carry-less multiplication for Cryptography
+`zbkx` | | [Zbkx][rv-zb-zbkx] — Crossbar permutations
+`zbs` | | [Zbs][rv-zb-zbs] — Single-bit instructions
+`zk` | `zkn`, `zkr`, `zks`, `zkt`, `zbkb`, `zbkc`, `zkbx` | [Zk][rv-zk] — Scalar Cryptography
+`zkn` | `zknd`, `zkne`, `zknh`, `zbkb`, `zbkc`, `zkbx` | [Zkn][rv-zkn] — NIST Algorithm suite extension
+`zknd` | | [Zknd][rv-zknd] — NIST Suite: AES Decryption
+`zkne` | | [Zkne][rv-zkne] — NIST Suite: AES Encryption
+`zknh` | | [Zknh][rv-zknh] — NIST Suite: Hash Function Instructions
+`zkr` | | [Zkr][rv-zkr] — Entropy Source Extension
+`zks` | `zksed`, `zksh`, `zbkb`, `zbkc`, `zkbx` | [Zks][rv-zks] — ShangMi Algorithm Suite
+`zksed` | | [Zksed][rv-zksed] — ShangMi Suite: SM4 Block Cipher Instructions
+`zksh` | | [Zksh][rv-zksh] — ShangMi Suite: SM3 Hash Function Instructions
+`zkt` | | [Zkt][rv-zkt] — Data Independent Execution Latency Subset
+
+<!-- Keep links near each table to make it easier to move and update. -->
+
+[rv-a]: https://github.com/riscv/riscv-isa-manual/blob/de46343a245c6ee1f7b1a40c92fe1a86bd4f4978/src/a-st-ext.adoc
+[rv-c]: https://github.com/riscv/riscv-isa-manual/blob/de46343a245c6ee1f7b1a40c92fe1a86bd4f4978/src/c-st-ext.adoc
+[rv-m]: https://github.com/riscv/riscv-isa-manual/blob/de46343a245c6ee1f7b1a40c92fe1a86bd4f4978/src/m-st-ext.adoc
+[rv-zb]: https://github.com/riscv/riscv-bitmanip
+[rv-zb-zba]: https://github.com/riscv/riscv-bitmanip/blob/main/bitmanip/zba.adoc
+[rv-zb-zbb]: https://github.com/riscv/riscv-bitmanip/blob/main/bitmanip/zbb.adoc
+[rv-zb-zbc]: https://github.com/riscv/riscv-bitmanip/blob/main/bitmanip/zbc.adoc
+[rv-zb-zbkb]: https://github.com/riscv/riscv-bitmanip/blob/main/bitmanip/zbkb.adoc
+[rv-zb-zbkc]: https://github.com/riscv/riscv-bitmanip/blob/main/bitmanip/zbkc.adoc
+[rv-zb-zbkx]: https://github.com/riscv/riscv-bitmanip/blob/main/bitmanip/zbkx.adoc
+[rv-zb-zbs]: https://github.com/riscv/riscv-bitmanip/blob/main/bitmanip/zbs.adoc
+[rv-zk]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zk.adoc
+[rv-zkn]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zkn.adoc
+[rv-zkne]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zkne.adoc
+[rv-zknd]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zknd.adoc
+[rv-zknh]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zknh.adoc
+[rv-zkr]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zkr.adoc
+[rv-zks]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zks.adoc
+[rv-zksed]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zksed.adoc
+[rv-zksh]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zksh.adoc
+[rv-zkt]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zkr.adoc
+
#### `wasm32` or `wasm64`
`#[target_feature]` may be used with both safe and
diff --git a/src/doc/reference/src/behavior-considered-undefined.md b/src/doc/reference/src/behavior-considered-undefined.md
index f140fb20c..756b86db0 100644
--- a/src/doc/reference/src/behavior-considered-undefined.md
+++ b/src/doc/reference/src/behavior-considered-undefined.md
@@ -27,9 +27,12 @@ Please read the [Rustonomicon] before writing unsafe code.
</div>
* Data races.
-* Evaluating a [dereference expression] (`*expr`) on a raw pointer that is
- [dangling] or unaligned, even in [place expression context]
- (e.g. `addr_of!(*expr)`).
+* Accessing (loading from or storing to) a place that is [dangling] or [based on
+ a misaligned pointer].
+* Performing a place projection that violates the requirements of [in-bounds
+ pointer arithmetic][offset]. A place projection is a [field
+ expression][project-field], a [tuple index expression][project-tuple], or an
+ [array/slice index expression][project-slice].
* Breaking the [pointer aliasing rules]. `Box<T>`, `&mut T` and `&T` follow
LLVM’s scoped [noalias] model, except if the `&T` contains an
[`UnsafeCell<U>`]. References and boxes must not be [dangling] while they are
@@ -68,7 +71,7 @@ Please read the [Rustonomicon] before writing unsafe code.
* A `!` (all values are invalid for this type).
* An integer (`i*`/`u*`), floating point value (`f*`), or raw pointer obtained
from [uninitialized memory][undef], or uninitialized memory in a `str`.
- * A reference or `Box<T>` that is [dangling], unaligned, or points to an invalid value.
+ * A reference or `Box<T>` that is [dangling], misaligned, or points to an invalid value.
* Invalid metadata in a wide reference, `Box<T>`, or raw pointer:
* `dyn Trait` metadata is invalid if it is not a pointer to a vtable for
`Trait` that matches the actual dynamic trait the pointer or reference points to.
@@ -102,6 +105,36 @@ reading uninitialized memory is permitted are inside `union`s and in "padding"
The span of bytes a pointer or reference "points to" is determined by the pointer value and the size of the pointee type (using `size_of_val`).
+### Places based on misaligned pointers
+[based on a misaligned pointer]: #places-based-on-misaligned-pointers
+
+A place is said to be "based on a misaligned pointer" if the last `*` projection
+during place computation was performed on a pointer that was not aligned for its
+type. (If there is no `*` projection in the place expression, then this is
+accessing the field of a local and rustc will guarantee proper alignment. If
+there are multiple `*` projection, then each of them incurs a load of the
+pointer-to-be-dereferenced itself from memory, and each of these loads is
+subject to the alignment constraint. Note that some `*` projections can be
+omitted in surface Rust syntax due to automatic dereferencing; we are
+considering the fully expanded place expression here.)
+
+For instance, if `ptr` has type `*const S` where `S` has an alignment of 8, then
+`ptr` must be 8-aligned or else `(*ptr).f` is "based on an misaligned pointer".
+This is true even if the type of the field `f` is `u8` (i.e., a type with
+alignment 1). In other words, the alignment requirement derives from the type of
+the pointer that was dereferenced, *not* the type of the field that is being
+accessed.
+
+Note that a place based on a misaligned pointer only leads to Undefined Behavior
+when it is loaded from or stored to. `addr_of!`/`addr_of_mut!` on such a place
+is allowed. `&`/`&mut` on a place requires the alignment of the field type (or
+else the program would be "producing an invalid value"), which generally is a
+less restrictive requirement than being based on an aligned pointer. Taking a
+reference will lead to a compiler error in cases where the field type might be
+more aligned than the type that contains it, i.e., `repr(packed)`. This means
+that being based on an aligned pointer is always sufficient to ensure that the
+new reference is aligned, but it is not always necessary.
+
### Dangling pointers
[dangling]: #dangling-pointers
@@ -128,8 +161,11 @@ must never exceed `isize::MAX`.
[Rustonomicon]: ../nomicon/index.html
[`NonNull<T>`]: ../core/ptr/struct.NonNull.html
[`NonZero*`]: ../core/num/index.html
-[dereference expression]: expressions/operator-expr.md#the-dereference-operator
[place expression context]: expressions.md#place-expressions-and-value-expressions
[rules]: inline-assembly.md#rules-for-inline-assembly
[points to]: #pointed-to-bytes
[pointed to]: #pointed-to-bytes
+[offset]: ../std/primitive.pointer.html#method.offset
+[project-field]: expressions/field-expr.md
+[project-tuple]: expressions/tuple-expr.md#tuple-indexing-expressions
+[project-slice]: expressions/array-expr.md#array-and-slice-indexing-expressions
diff --git a/src/doc/reference/src/destructors.md b/src/doc/reference/src/destructors.md
index 17afc3676..9c426426c 100644
--- a/src/doc/reference/src/destructors.md
+++ b/src/doc/reference/src/destructors.md
@@ -156,7 +156,7 @@ temporary variable that holds the result of that expression when used in a
Apart from lifetime extension, the temporary scope of an expression is the
smallest scope that contains the expression and is one of the following:
-* The entire function body.
+* The entire function.
* A statement.
* The body of an [`if`], [`while`] or [`loop`] expression.
* The `else` block of an `if` expression.
@@ -168,8 +168,8 @@ smallest scope that contains the expression and is one of the following:
> **Notes**:
>
> Temporaries that are created in the final expression of a function
-> body are dropped *after* any named variables bound in the function body, as
-> there is no smaller enclosing temporary scope.
+> body are dropped *after* any named variables bound in the function body.
+> Their drop scope is the entire function, as there is no smaller enclosing temporary scope.
>
> The [scrutinee] of a `match` expression is not a temporary scope, so
> temporaries in the scrutinee can be dropped after the `match` expression. For
diff --git a/src/doc/reference/src/expressions/operator-expr.md b/src/doc/reference/src/expressions/operator-expr.md
index 8b6429636..bd4998af5 100644
--- a/src/doc/reference/src/expressions/operator-expr.md
+++ b/src/doc/reference/src/expressions/operator-expr.md
@@ -478,6 +478,16 @@ unsafe {
assert_eq!(values[1], 3);
```
+#### Slice DST pointer to pointer cast
+
+For slice types like `[T]` and `[U]`, the raw pointer types `*const [T]`, `*mut [T]`,
+`*const [U]`, and `*mut [U]` encode the number of elements in this slice. Casts between
+these raw pointer types preserve the number of elements. Note that, as a consequence,
+such casts do *not* necessarily preserve the size of the pointer's referent (e.g.,
+casting `*const [u16]` to `*const [u8]` will result in a raw pointer which refers to an
+object of half the size of the original). The same holds for `str` and any compound type
+whose unsized tail is a slice type, such as struct `Foo(i32, [u8])` or `(u64, Foo)`.
+
## Assignment expressions
> **<sup>Syntax</sup>**\
diff --git a/src/doc/reference/src/inline-assembly.md b/src/doc/reference/src/inline-assembly.md
index 26f1acedc..e905fcb26 100644
--- a/src/doc/reference/src/inline-assembly.md
+++ b/src/doc/reference/src/inline-assembly.md
@@ -414,10 +414,13 @@ Flags are used to further influence the behavior of the inline assembly block.
Currently the following options are defined:
- `pure`: The `asm!` block has no side effects, and its outputs depend only on its direct inputs (i.e. the values themselves, not what they point to) or values read from memory (unless the `nomem` options is also set).
This allows the compiler to execute the `asm!` block fewer times than specified in the program (e.g. by hoisting it out of a loop) or even eliminate it entirely if the outputs are not used.
+ The `pure` option must be combined with either the `nomem` or `readonly` options, otherwise a compile-time error is emitted.
- `nomem`: The `asm!` blocks does not read or write to any memory.
This allows the compiler to cache the values of modified global variables in registers across the `asm!` block since it knows that they are not read or written to by the `asm!`.
+ The compiler also assumes that this `asm!` block does not perform any kind of synchronization with other threads, e.g. via fences.
- `readonly`: The `asm!` block does not write to any memory.
This allows the compiler to cache the values of unmodified global variables in registers across the `asm!` block since it knows that they are not written to by the `asm!`.
+ The compiler also assumes that this `asm!` block does not perform any kind of synchronization with other threads, e.g. via fences.
- `preserves_flags`: The `asm!` block does not modify the flags register (defined in the rules below).
This allows the compiler to avoid recomputing the condition flags after the `asm!` block.
- `noreturn`: The `asm!` block never returns, and its return type is defined as `!` (never).
@@ -432,7 +435,6 @@ Currently the following options are defined:
The compiler performs some additional checks on options:
- The `nomem` and `readonly` options are mutually exclusive: it is a compile-time error to specify both.
-- The `pure` option must be combined with either the `nomem` or `readonly` options, otherwise a compile-time error is emitted.
- It is a compile-time error to specify `pure` on an asm block with no outputs or only discarded outputs (`_`).
- It is a compile-time error to specify `noreturn` on an asm block with outputs.
diff --git a/src/doc/reference/src/items/traits.md b/src/doc/reference/src/items/traits.md
index 3c5d31d5c..828a8a35f 100644
--- a/src/doc/reference/src/items/traits.md
+++ b/src/doc/reference/src/items/traits.md
@@ -43,7 +43,7 @@ trait Example {
}
```
-Trait functions are not allowed to be [`async`] or [`const`].
+Trait functions are not allowed to be [`const`].
## Trait bounds
diff --git a/src/doc/reference/src/types/impl-trait.md b/src/doc/reference/src/types/impl-trait.md
index af900408e..b46c209b7 100644
--- a/src/doc/reference/src/types/impl-trait.md
+++ b/src/doc/reference/src/types/impl-trait.md
@@ -88,6 +88,12 @@ which also avoids the drawbacks of using a boxed trait object.
Similarly, the concrete types of iterators could become very complex, incorporating the types of all previous iterators in a chain.
Returning `impl Iterator` means that a function only exposes the `Iterator` trait as a bound on its return type, instead of explicitly specifying all of the other iterator types involved.
+## Return-position `impl Trait` in traits and trait implementations
+
+Functions in traits may also use `impl Trait` as a syntax for an anonymous associated type.
+
+Every `impl Trait` in the return type of an associated function in a trait is desugared to an anonymous associated type. The return type that appears in the implementation's function signature is used to determine the value of the associated type.
+
### Differences between generics and `impl Trait` in return position
In argument position, `impl Trait` is very similar in semantics to a generic type parameter.
@@ -121,8 +127,8 @@ Instead, the function chooses the return type, but only promises that it will im
## Limitations
-`impl Trait` can only appear as a parameter or return type of a free or inherent function.
-It cannot appear inside implementations of traits, nor can it be the type of a let binding or appear inside a type alias.
+`impl Trait` can only appear as a parameter or return type of a non-`extern` function.
+It cannot be the type of a `let` binding, field type, or appear inside a type alias.
[closures]: closure.md
[_GenericArgs_]: ../paths.md#paths-in-expressions
diff --git a/src/doc/reference/src/types/textual.md b/src/doc/reference/src/types/textual.md
index 41ed35ea1..fcbec0823 100644
--- a/src/doc/reference/src/types/textual.md
+++ b/src/doc/reference/src/types/textual.md
@@ -17,7 +17,9 @@ is valid UTF-8. Calling a `str` method with a non-UTF-8 buffer can cause
Since `str` is a [dynamically sized type], it can only be instantiated through a
pointer type, such as `&str`.
-## Bit validity
+## Layout and bit validity
+
+`char` is guaranteed to have the same size and alignment as `u32` on all platforms.
Every byte of a `char` is guaranteed to be initialized (in other words,
`transmute::<char, [u8; size_of::<char>()]>(...)` is always sound -- but since
diff --git a/src/doc/rust-by-example/src/SUMMARY.md b/src/doc/rust-by-example/src/SUMMARY.md
index b1bcf223d..b8e6ada91 100644
--- a/src/doc/rust-by-example/src/SUMMARY.md
+++ b/src/doc/rust-by-example/src/SUMMARY.md
@@ -161,7 +161,7 @@
- [Unpacking options with `?`](error/option_unwrap/question_mark.md)
- [Combinators: `map`](error/option_unwrap/map.md)
- [Combinators: `and_then`](error/option_unwrap/and_then.md)
- - [Defaults: `or`, `or_else`, `get_or_insert`, 'get_or_insert_with`](error/option_unwrap/defaults.md)
+ - [Defaults: `or`, `or_else`, `get_or_insert`, `get_or_insert_with`](error/option_unwrap/defaults.md)
- [`Result`](error/result.md)
- [`map` for `Result`](error/result/result_map.md)
- [aliases for `Result`](error/result/result_alias.md)
@@ -197,7 +197,7 @@
- [File I/O](std_misc/file.md)
- [`open`](std_misc/file/open.md)
- [`create`](std_misc/file/create.md)
- - [`read lines`](std_misc/file/read_lines.md)
+ - [`read_lines`](std_misc/file/read_lines.md)
- [Child processes](std_misc/process.md)
- [Pipes](std_misc/process/pipe.md)
- [Wait](std_misc/process/wait.md)
diff --git a/src/doc/rust-by-example/src/attribute.md b/src/doc/rust-by-example/src/attribute.md
index dcb7d6c1a..d6a49dc01 100644
--- a/src/doc/rust-by-example/src/attribute.md
+++ b/src/doc/rust-by-example/src/attribute.md
@@ -14,9 +14,34 @@ can be used to/for:
* mark functions that will be part of a benchmark
* [attribute like macros][macros]
-When attributes apply to a whole crate, their syntax is `#![crate_attribute]`,
-and when they apply to a module or item, the syntax is `#[item_attribute]`
-(notice the missing bang `!`).
+Attributes look like `#[outer_attribute]` or `#![inner_attribute]`,
+with the difference between them being where they apply.
+
+- `#[outer_attribute]` applies to the [item][item] immediately
+ following it. Some examples of items are: a function, a module
+ declaration, a constant, a structure, an enum. Here is an example
+ where attribute `#[derive(Debug)]` applies to the struct
+ `Rectangle`:
+ ```rust
+ #[derive(Debug)]
+ struct Rectangle {
+ width: u32,
+ height: u32,
+ }
+ ```
+
+- `#![inner_attribute]` applies to the enclosing [item][item] (typically a
+ module or a crate). In other words, this attribute is intepreted as
+ applying to the entire scope in which it's place. Here is an example
+ where `#![allow(unusude_variables)]` applies to the whole crate (if
+ placed in `main.rs`):
+ ```rust
+ #![allow(unused_variables)]
+
+ fn main() {
+ let x = 3; // This would normally warn about an unused variable.
+ }
+ ```
Attributes can take arguments with different syntaxes:
@@ -36,5 +61,6 @@ Attributes can have multiple values and can be separated over multiple lines, to
[cfg]: attribute/cfg.md
[crate]: attribute/crate.md
+[item]: https://doc.rust-lang.org/stable/reference/items.html
[lint]: https://en.wikipedia.org/wiki/Lint_%28software%29
[macros]: https://doc.rust-lang.org/book/ch19-06-macros.html#attribute-like-macros
diff --git a/src/doc/rust-by-example/src/custom_types/constants.md b/src/doc/rust-by-example/src/custom_types/constants.md
index 8878ba834..c060db734 100644
--- a/src/doc/rust-by-example/src/custom_types/constants.md
+++ b/src/doc/rust-by-example/src/custom_types/constants.md
@@ -4,7 +4,7 @@ Rust has two different types of constants which can be declared in any scope
including global. Both require explicit type annotation:
* `const`: An unchangeable value (the common case).
-* `static`: A possibly `mut`able variable with [`'static`][static] lifetime.
+* `static`: A possibly mutable variable with [`'static`][static] lifetime.
The static lifetime is inferred and does not have to be specified.
Accessing or modifying a mutable static variable is [`unsafe`][unsafe].
diff --git a/src/doc/rust-by-example/src/error/option_unwrap/question_mark.md b/src/doc/rust-by-example/src/error/option_unwrap/question_mark.md
index 831625229..04de93cc7 100644
--- a/src/doc/rust-by-example/src/error/option_unwrap/question_mark.md
+++ b/src/doc/rust-by-example/src/error/option_unwrap/question_mark.md
@@ -8,7 +8,8 @@ function is being executed and return `None`.
```rust,editable
fn next_birthday(current_age: Option<u8>) -> Option<String> {
// If `current_age` is `None`, this returns `None`.
- // If `current_age` is `Some`, the inner `u8` gets assigned to `next_age`
+ // If `current_age` is `Some`, the inner `u8` value + 1
+ // gets assigned to `next_age`
let next_age: u8 = current_age? + 1;
Some(format!("Next year I will be {}", next_age))
}
diff --git a/src/doc/rust-by-example/src/flow_control/while_let.md b/src/doc/rust-by-example/src/flow_control/while_let.md
index 897375a8e..745b7ae75 100644
--- a/src/doc/rust-by-example/src/flow_control/while_let.md
+++ b/src/doc/rust-by-example/src/flow_control/while_let.md
@@ -31,26 +31,24 @@ loop {
Using `while let` makes this sequence much nicer:
```rust,editable
-fn main() {
- // Make `optional` of type `Option<i32>`
- let mut optional = Some(0);
-
- // This reads: "while `let` destructures `optional` into
- // `Some(i)`, evaluate the block (`{}`). Else `break`.
- while let Some(i) = optional {
- if i > 9 {
- println!("Greater than 9, quit!");
- optional = None;
- } else {
- println!("`i` is `{:?}`. Try again.", i);
- optional = Some(i + 1);
- }
- // ^ Less rightward drift and doesn't require
- // explicitly handling the failing case.
+// Make `optional` of type `Option<i32>`
+let mut optional = Some(0);
+
+// This reads: "while `let` destructures `optional` into
+// `Some(i)`, evaluate the block (`{}`). Else `break`.
+while let Some(i) = optional {
+ if i > 9 {
+ println!("Greater than 9, quit!");
+ optional = None;
+ } else {
+ println!("`i` is `{:?}`. Try again.", i);
+ optional = Some(i + 1);
}
- // ^ `if let` had additional optional `else`/`else if`
- // clauses. `while let` does not have these.
+ // ^ Less rightward drift and doesn't require
+ // explicitly handling the failing case.
}
+// ^ `if let` had additional optional `else`/`else if`
+// clauses. `while let` does not have these.
```
### See also:
diff --git a/src/doc/rust-by-example/src/fn/closures.md b/src/doc/rust-by-example/src/fn/closures.md
index 82286003b..e7b8c9867 100644
--- a/src/doc/rust-by-example/src/fn/closures.md
+++ b/src/doc/rust-by-example/src/fn/closures.md
@@ -14,7 +14,7 @@ variable names *must* be specified.
Other characteristics of closures include:
* using `||` instead of `()` around input variables.
-* optional body delimination (`{}`) for a single expression (mandatory otherwise).
+* optional body delimitation (`{}`) for a single expression (mandatory otherwise).
* the ability to capture the outer environment variables.
```rust,editable
@@ -26,7 +26,7 @@ fn main() {
// TODO: uncomment the line above and see the compiler error. The compiler
// suggests that we define a closure instead.
- // Closures are anonymous, here we are binding them to references
+ // Closures are anonymous, here we are binding them to references.
// Annotation is identical to function annotation but is optional
// as are the `{}` wrapping the body. These nameless functions
// are assigned to appropriately named variables.
diff --git a/src/doc/rust-by-example/src/fn/hof.md b/src/doc/rust-by-example/src/fn/hof.md
index 88918cb52..9be5b41fe 100644
--- a/src/doc/rust-by-example/src/fn/hof.md
+++ b/src/doc/rust-by-example/src/fn/hof.md
@@ -10,7 +10,7 @@ fn is_odd(n: u32) -> bool {
}
fn main() {
- println!("Find the sum of all the squared odd numbers under 1000");
+ println!("Find the sum of all the numbers with odd squares under 1000");
let upper = 1000;
// Imperative approach
diff --git a/src/doc/rust-by-example/src/meta/doc.md b/src/doc/rust-by-example/src/meta/doc.md
index e9e51186f..b1732f837 100644
--- a/src/doc/rust-by-example/src/meta/doc.md
+++ b/src/doc/rust-by-example/src/meta/doc.md
@@ -2,7 +2,8 @@
Use `cargo doc` to build documentation in `target/doc`.
-Use `cargo test` to run all tests (including documentation tests), and `cargo test --doc` to only run documentation tests.
+Use `cargo test` to run all tests (including documentation tests), and `cargo
+test --doc` to only run documentation tests.
These commands will appropriately invoke `rustdoc` (and `rustc`) as required.
@@ -67,7 +68,8 @@ $ rustdoc --test --extern doc="libdoc.rlib" doc.rs
## Doc attributes
-Below are a few examples of the most common `#[doc]` attributes used with `rustdoc`.
+Below are a few examples of the most common `#[doc]` attributes used with
+`rustdoc`.
### `inline`
@@ -104,7 +106,8 @@ Using this tells `rustdoc` not to include this in documentation:
pub use self::async_await::*;
```
-For documentation, `rustdoc` is widely used by the community. It's what is used to generate the [std library docs](https://doc.rust-lang.org/std/).
+For documentation, `rustdoc` is widely used by the community. It's what is used
+to generate the [std library docs](https://doc.rust-lang.org/std/).
### See also:
diff --git a/src/doc/rust-by-example/src/meta/playground.md b/src/doc/rust-by-example/src/meta/playground.md
index 7fcfad1a7..e78552d29 100644
--- a/src/doc/rust-by-example/src/meta/playground.md
+++ b/src/doc/rust-by-example/src/meta/playground.md
@@ -1,6 +1,7 @@
# Playground
-The [Rust Playground](https://play.rust-lang.org/) is a way to experiment with Rust code through a web interface.
+The [Rust Playground](https://play.rust-lang.org/) is a way to experiment with
+Rust code through a web interface.
## Using it with `mdbook`
@@ -12,7 +13,9 @@ fn main() {
}
```
-This allows the reader to both run your code sample, but also modify and tweak it. The key here is the adding the word `editable` to your codefence block separated by a comma.
+This allows the reader to both run your code sample, but also modify and tweak
+it. The key here is the adding the word `editable` to your codefence block
+separated by a comma.
````markdown
```rust,editable
@@ -20,7 +23,8 @@ This allows the reader to both run your code sample, but also modify and tweak i
```
````
-Additionally, you can add `ignore` if you want `mdbook` to skip your code when it builds and tests.
+Additionally, you can add `ignore` if you want `mdbook` to skip your code when
+it builds and tests.
````markdown
```rust,editable,ignore
@@ -30,7 +34,10 @@ Additionally, you can add `ignore` if you want `mdbook` to skip your code when i
## Using it with docs
-You may have noticed in some of the [official Rust docs][official-rust-docs] a button that says "Run", which opens the code sample up in a new tab in Rust Playground. This feature is enabled if you use the #[doc] attribute called [`html_playground_url`][html-playground-url].
+You may have noticed in some of the [official Rust docs][official-rust-docs] a
+button that says "Run", which opens the code sample up in a new tab in Rust
+Playground. This feature is enabled if you use the `#[doc]` attribute called
+[`html_playground_url`][html-playground-url].
### See also:
diff --git a/src/doc/rust-by-example/src/primitives/array.md b/src/doc/rust-by-example/src/primitives/array.md
index 5f5e69944..704a2131c 100644
--- a/src/doc/rust-by-example/src/primitives/array.md
+++ b/src/doc/rust-by-example/src/primitives/array.md
@@ -6,7 +6,7 @@ at compile time, is part of their type signature `[T; length]`.
Slices are similar to arrays, but their length is not known at compile time.
Instead, a slice is a two-word object; the first word is a pointer to the data,
-the second word the length of the slice. The word size is the same as usize,
+the second word is the length of the slice. The word size is the same as usize,
determined by the processor architecture, e.g. 64 bits on an x86-64. Slices can
be used to borrow a section of an array and have the type signature `&[T]`.
diff --git a/src/doc/rust-by-example/src/scope/lifetime.md b/src/doc/rust-by-example/src/scope/lifetime.md
index 68b42d380..01c4bf405 100644
--- a/src/doc/rust-by-example/src/scope/lifetime.md
+++ b/src/doc/rust-by-example/src/scope/lifetime.md
@@ -1,6 +1,6 @@
# Lifetimes
-A *lifetime* is a construct of the compiler (or more specifically, its *borrow
+A *lifetime* is a construct the compiler (or more specifically, its *borrow
checker*) uses to ensure all borrows are valid. Specifically, a variable's
lifetime begins when it is created and ends when it is destroyed. While
lifetimes and scopes are often referred to together, they are not the same.
diff --git a/src/doc/rust-by-example/src/scope/move.md b/src/doc/rust-by-example/src/scope/move.md
index 0433e8ac1..df631ee08 100644
--- a/src/doc/rust-by-example/src/scope/move.md
+++ b/src/doc/rust-by-example/src/scope/move.md
@@ -1,7 +1,7 @@
# Ownership and moves
Because variables are in charge of freeing their own resources,
-**resources can only have one owner**. This also prevents resources
+**resources can only have one owner**. This prevents resources
from being freed more than once. Note that not all variables own
resources (e.g. [references]).
diff --git a/src/doc/rust-by-example/src/std/hash/alt_key_types.md b/src/doc/rust-by-example/src/std/hash/alt_key_types.md
index ab94819b2..7e68e8c67 100644
--- a/src/doc/rust-by-example/src/std/hash/alt_key_types.md
+++ b/src/doc/rust-by-example/src/std/hash/alt_key_types.md
@@ -3,7 +3,7 @@
Any type that implements the `Eq` and `Hash` traits can be a key in `HashMap`.
This includes:
-* `bool` (though not very useful since there is only two possible keys)
+* `bool` (though not very useful since there are only two possible keys)
* `int`, `uint`, and all variations thereof
* `String` and `&str` (protip: you can have a `HashMap` keyed by `String`
and call `.get()` with an `&str`)
diff --git a/src/doc/rust-by-example/src/std_misc/arg/matching.md b/src/doc/rust-by-example/src/std_misc/arg/matching.md
index 4cb68eabf..4a96fbc21 100644
--- a/src/doc/rust-by-example/src/std_misc/arg/matching.md
+++ b/src/doc/rust-by-example/src/std_misc/arg/matching.md
@@ -70,6 +70,9 @@ fn main() {
}
```
+If you named your program `match_args.rs` and compile it like this `rustc
+match_args.rs`, you can execute it as follows:
+
```shell
$ ./match_args Rust
This is not the answer.
diff --git a/src/doc/rust-by-example/src/std_misc/file/read_lines.md b/src/doc/rust-by-example/src/std_misc/file/read_lines.md
index 216b0181c..1a2a64241 100644
--- a/src/doc/rust-by-example/src/std_misc/file/read_lines.md
+++ b/src/doc/rust-by-example/src/std_misc/file/read_lines.md
@@ -56,15 +56,13 @@ fn main() {
// File hosts.txt must exist in the current path
if let Ok(lines) = read_lines("./hosts.txt") {
// Consumes the iterator, returns an (Optional) String
- for line in lines {
- if let Ok(ip) = line {
- println!("{}", ip);
- }
+ for line in lines.flatten() {
+ println!("{}", line);
}
}
}
-// The output is wrapped in a Result to allow matching on errors
+// The output is wrapped in a Result to allow matching on errors.
// Returns an Iterator to the Reader of the lines of the file.
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, {
diff --git a/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md b/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md
index ee25b1661..9cc162f51 100644
--- a/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md
+++ b/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md
@@ -30,7 +30,7 @@ use std::thread;
fn main() {
// This is our data to process.
- // We will calculate the sum of all digits via a threaded map-reduce algorithm.
+ // We will calculate the sum of all digits via a threaded map-reduce algorithm.
// Each whitespace separated chunk will be handled in a different thread.
//
// TODO: see what happens to the output if you insert spaces!
diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs
index 70e77fd5b..fc0a5f469 100644
--- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs
+++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs
@@ -63,6 +63,8 @@ fn main() {
// Registry of diagnostics codes.
registry: registry::Registry::new(&rustc_error_codes::DIAGNOSTICS),
make_codegen_backend: None,
+ expanded_args: Vec::new(),
+ ice_file: None,
};
rustc_interface::run_compiler(config, |compiler| {
compiler.enter(|queries| {
diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs
index 888674aaf..0195224de 100644
--- a/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs
+++ b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs
@@ -73,6 +73,8 @@ fn main() {
override_queries: None,
registry: registry::Registry::new(&rustc_error_codes::DIAGNOSTICS),
make_codegen_backend: None,
+ expanded_args: Vec::new(),
+ ice_file: None,
};
rustc_interface::run_compiler(config, |compiler| {
compiler.enter(|queries| {
diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs
index df0e0385d..3d3827e5d 100644
--- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs
+++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs
@@ -51,6 +51,8 @@ fn main() {
override_queries: None,
make_codegen_backend: None,
registry: registry::Registry::new(&rustc_error_codes::DIAGNOSTICS),
+ expanded_args: Vec::new(),
+ ice_file: None,
};
rustc_interface::run_compiler(config, |compiler| {
compiler.enter(|queries| {
diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md
index 41e16c5e6..4a7fd2b77 100644
--- a/src/doc/rustc-dev-guide/src/SUMMARY.md
+++ b/src/doc/rustc-dev-guide/src/SUMMARY.md
@@ -124,6 +124,7 @@
- [Goals and clauses](./traits/goals-and-clauses.md)
- [Canonical queries](./traits/canonical-queries.md)
- [Next-gen trait solving](./solve/trait-solving.md)
+ - [Invariants of the type system](./solve/invariants.md)
- [The solver](./solve/the-solver.md)
- [Canonicalization](./solve/canonicalization.md)
- [Coinduction](./solve/coinduction.md)
@@ -135,6 +136,7 @@
- [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)
+- [Effect checking](./effects.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/appendix/bibliography.md b/src/doc/rustc-dev-guide/src/appendix/bibliography.md
index c2bb00e3b..cc262abef 100644
--- a/src/doc/rustc-dev-guide/src/appendix/bibliography.md
+++ b/src/doc/rustc-dev-guide/src/appendix/bibliography.md
@@ -79,7 +79,7 @@ Rust, as well as publications about Rust.
Rust](https://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip
Munksgaard's master's thesis. Research for Servo.
* [Ownership is Theft: Experiences Building an Embedded OS in Rust - Amit Levy, et. al.](https://amitlevy.com/papers/tock-plos2015.pdf)
-* [You can't spell trust without Rust](https://raw.githubusercontent.com/Gankro/thesis/master/thesis.pdf). Alexis Beingessner's master's thesis.
+* [You can't spell trust without Rust](https://faultlore.com/blah/papers/thesis.pdf). Aria Beingessner's master's thesis.
* [Rust-Bio: a fast and safe bioinformatics library](https://academic.oup.com/bioinformatics/article/32/3/444/1743419). Johannes Köster
* [Safe, Correct, and Fast Low-Level Networking](https://octarineparrot.com/assets/msci_paper.pdf). Robert Clipsham's master's thesis.
* [Formalizing Rust traits](https://open.library.ubc.ca/cIRcle/collections/ubctheses/24/items/1.0220521). Jonatan Milewski's master's thesis.
diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md
index 27b6cddf2..ee3a3a720 100644
--- a/src/doc/rustc-dev-guide/src/appendix/glossary.md
+++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md
@@ -25,6 +25,7 @@ Term | Meaning
<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 `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="effect">effects</span> &nbsp; | Right now only means const traits and `~const` bounds. ([see more](../effects.md))
<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)
@@ -93,6 +94,7 @@ Term | Meaning
<span id="upvar">upvar</span> &nbsp; | A variable captured by a closure from outside the closure.
<span id="variance">variance</span> &nbsp; | Determines how changes to a generic type/lifetime parameter affect subtyping; for example, if `T` is a subtype of `U`, then `Vec<T>` is a subtype `Vec<U>` because `Vec` is *covariant* in its generic parameter. See [the background chapter](./background.md#variance) for a more general explanation. See the [variance chapter](../variance.md) for an explanation of how type checking handles variance.
<span id="variant-idx">variant index</span> &nbsp; | In an enum, identifies a variant by assigning them indices starting at 0. This is purely internal and not to be confused with the ["discriminant"](#discriminant) which can be overwritten by the user (e.g. `enum Bool { True = 42, False = 0 }`).
+<span id="WF">Well-formedness</span> &nbsp; | Semantically:An expression that evaluates to meaningful result. In Type Systems: A type related construct which follows rules of the type system.
<span id="wide-ptr">wide pointer</span> &nbsp; | A pointer with additional metadata. See "fat pointer" for more.
<span id="zst">ZST</span> &nbsp; | Zero-Sized Type. A type whose values have size 0 bytes. Since `2^0 = 1`, such types can have exactly one value. For example, `()` (unit) is a ZST. `struct Foo;` is also a ZST. The compiler can do some nice optimizations around ZSTs.
diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md
index cb722696e..1336ff629 100644
--- a/src/doc/rustc-dev-guide/src/building/suggested.md
+++ b/src/doc/rustc-dev-guide/src/building/suggested.md
@@ -277,7 +277,6 @@ let
# `config.toml.example`) from `1bd30ce2aac40c7698aa4a1b9520aa649ff2d1c5`
config = pkgs.writeText "rustc-config" ''
profile = "compiler" # you may want to choose a different profile, like `library` or `tools`
- changelog-seen = 2
[build]
patch-binaries-for-nix = true
diff --git a/src/doc/rustc-dev-guide/src/effects.md b/src/doc/rustc-dev-guide/src/effects.md
new file mode 100644
index 000000000..1fda7bcbb
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/effects.md
@@ -0,0 +1,66 @@
+# Effects and effect checking
+
+Note: all of this describes the implementation of the unstable `effects` and
+`const_trait_impl` features. None of this implementation is usable or visible from
+stable Rust.
+
+The implementation of const traits and `~const` bounds is a limited effect system.
+It is used to allow trait bounds on `const fn` to be used within the `const fn` for
+method calls. Within the function, in order to know whether a method on a trait
+bound is `const`, we need to know whether there is a `~const` bound for the trait.
+In order to know whether we can instantiate a `~const` bound on a `const fn`, we
+need to know whether there is a `const_trait` impl for the type and trait being
+used (or whether the `const fn` is used at runtime, then any type implementing the
+trait is ok, just like with other bounds).
+
+We perform these checks via a const generic boolean that gets attached to all
+`const fn` and `const trait`. The following sections will explain the desugarings
+and the way we perform the checks at call sites.
+
+The const generic boolean is inverted to the meaning of `const`. In the compiler
+it is called `host`, because it enables "host APIs" like `static` items, network
+access, disk access, random numbers and everything else that isn't available in
+`const` contexts. So `false` means "const", `true` means "not const" and if it's
+a generic parameter, it means "maybe const" (meaning we're in a const fn or const
+trait).
+
+## `const fn`
+
+All `const fn` have a `#[rustc_host] const host: bool` generic parameter that is
+hidden from users. Any `~const Trait` bounds in the generics list or `where` bounds
+of a `const fn` get converted to `Trait<host> + Trait<true>` bounds. The `Trait<true>`
+exists so that associated types of the generic param can be used from projections
+like `<T as Trait>::Assoc`, because there are no `<T as ~const Trait>` projections for now.
+
+## `#[const_trait] trait`s
+
+The `#[const_trait]` attribute gives the marked trait a `#[rustc_host] const host: bool`
+generic parameter. All functions of the trait "inherit" this generic parameter, just like
+they have all the regular generic parameters of the trait. Any `~const Trait` super-trait
+bounds get desugared to `Trait<host> + Trait<true>` in order to allow using associated
+types and consts of the super traits in the trait declaration. This is necessary, because
+`<Self as SuperTrait>::Assoc` is always `<Self as SuperTrait<true>>::Assoc` as there is
+no `<Self as ~const SuperTrait>` syntax.
+
+## `typeck` performing method and function call checks.
+
+When generic parameters are instantiated for any items, the `host` generic parameter
+is always instantiated as an inference variable. This is a special kind of inference var
+that is not part of the type or const inference variables, similar to how we have
+special inference variables for type variables that we know to be an integer, but not
+yet which one. These separate inference variables fall back to `true` at
+the end of typeck (in `fallback_effects`) to ensure that `let _ = some_fn_item_name;`
+will keep compiling.
+
+All actually used (in function calls, casts, or anywhere else) function items, will
+have the `enforce_context_effects` method invoked.
+It trivially returns if the function being called has no `host` generic parameter.
+
+In order to error if a non-const function is called in a const context, we have not
+yet disabled the const-check logic that happens on MIR, because
+`enforce_context_effects` does not yet perform this check.
+
+The function call's `host` parameter is then equated to the context's `host` value,
+which almost always trivially succeeds, as it was an inference var. If the inference
+var has already been bound (since the function item is invoked twice), the second
+invocation checks it against the first.
diff --git a/src/doc/rustc-dev-guide/src/feature-gates.md b/src/doc/rustc-dev-guide/src/feature-gates.md
index 8ad4fea1f..788f93d66 100644
--- a/src/doc/rustc-dev-guide/src/feature-gates.md
+++ b/src/doc/rustc-dev-guide/src/feature-gates.md
@@ -20,12 +20,12 @@ See ["Stability in code"][adding] in the "Implementing new features" section for
To remove a feature gate, follow these steps:
-1. Remove the feature gate declaration in `rustc_feature/src/active.rs`.
+1. Remove the feature gate declaration in `rustc_feature/src/unstable.rs`.
It will look like this:
```rust,ignore
/// description of feature
- (active, $feature_name, "$version", Some($tracking_issue_number), $edition)
+ (unstable, $feature_name, "$version", Some($tracking_issue_number), $edition)
```
2. Add a modified version of the feature gate declaration that you just
@@ -45,12 +45,12 @@ To remove a feature gate, follow these steps:
To rename a feature gate, follow these steps (the first two are the same steps
to follow when [removing a feature gate][removing]):
-1. Remove the old feature gate declaration in `rustc_feature/src/active.rs`.
+1. Remove the old feature gate declaration in `rustc_feature/src/unstable.rs`.
It will look like this:
```rust,ignore
/// description of feature
- (active, $old_feature_name, "$version", Some($tracking_issue_number), $edition)
+ (unstable, $old_feature_name, "$version", Some($tracking_issue_number), $edition)
```
2. Add a modified version of the old feature gate declaration that you just
@@ -64,12 +64,12 @@ to follow when [removing a feature gate][removing]):
```
3. Add a feature gate declaration with the new name to
- `rustc_feature/src/active.rs`. It should look very similar to the old
+ `rustc_feature/src/unstable.rs`. It should look very similar to the old
declaration:
```rust,ignore
/// description of feature
- (active, $new_feature_name, "$version", Some($tracking_issue_number), $edition)
+ (unstable, $new_feature_name, "$version", Some($tracking_issue_number), $edition)
```
diff --git a/src/doc/rustc-dev-guide/src/hir-debugging.md b/src/doc/rustc-dev-guide/src/hir-debugging.md
index c25a558a0..5a0bda208 100644
--- a/src/doc/rustc-dev-guide/src/hir-debugging.md
+++ b/src/doc/rustc-dev-guide/src/hir-debugging.md
@@ -1,6 +1,13 @@
# HIR Debugging
-The `-Z unpretty=hir-tree` flag will dump out the HIR.
+Use the `-Z unpretty=hir` flag to produce a human-readable representation of the HIR.
+For cargo projects this can be done with `cargo rustc -- -Z unpretty=hir`.
+This output is useful when you need to see at a glance how your code was desugared and transformed
+during AST lowering.
+
+For a full `Debug` dump of the data in the HIR, use the `-Z unpretty=hir-tree` flag.
+This may be useful when you need to see the full structure of the HIR from the perspective of the
+compiler.
If you are trying to correlate `NodeId`s or `DefId`s with source code, the
`-Z unpretty=expanded,identified` flag may be useful.
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 01508889f..427589dab 100644
--- a/src/doc/rustc-dev-guide/src/implementing_new_features.md
+++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md
@@ -123,12 +123,12 @@ a new unstable feature:
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
+1. Add a feature gate declaration to `rustc_feature/src/unstable.rs` in the unstable
`declare_features` block.
```rust ignore
/// description of feature
- (active, $feature_name, "CURRENT_RUSTC_VERSION", Some($tracking_issue_number), $edition)
+ (unstable, $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
@@ -140,7 +140,7 @@ a new unstable feature:
```rust ignore
/// Allows defining identifiers beyond ASCII.
- (active, non_ascii_idents, "CURRENT_RUSTC_VERSION", Some(55467), None),
+ (unstable, non_ascii_idents, "CURRENT_RUSTC_VERSION", Some(55467), None),
```
Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features`
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 9379a57f6..fd215e3e9 100644
--- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md
+++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md
@@ -73,21 +73,21 @@ When compiling with `-C instrument-coverage`,
Coverage instrumentation is performed on the MIR with a [MIR pass][mir-passes]
called [`InstrumentCoverage`][mir-instrument-coverage]. This MIR pass analyzes
the control flow graph (CFG)--represented by MIR `BasicBlock`s--to identify
-code branches, and injects additional [`Coverage`][coverage-statement]
-statements into the `BasicBlock`s.
+code branches, attaches [`FunctionCoverageInfo`] to the function's body,
+and injects additional [`Coverage`][coverage-statement] statements into the
+`BasicBlock`s.
A MIR `Coverage` statement is a virtual instruction that indicates a counter
should be incremented when its adjacent statements are executed, to count
a span of code ([`CodeRegion`][code-region]). It counts the number of times a
-branch is executed, and also specifies the exact location of that code span in
-the Rust source code.
+branch is executed, and is referred to by coverage mappings in the function's
+coverage-info struct.
-Note that many of these `Coverage` statements will _not_ be converted into
+Note that many coverage counters will _not_ be converted into
physical counters (or any other executable instructions) in the final binary.
-Some of them will be (see [`CoverageKind::Counter`]),
+Some of them will be (see [`CoverageKind::CounterIncrement`]),
but other counters can be computed on the fly, when generating a coverage
-report, by mapping a `CodeRegion` to a
-[`CoverageKind::Expression`].
+report, by mapping a `CodeRegion` to a coverage-counter _expression_.
As an example:
@@ -121,8 +121,8 @@ determines when to break out of a loop (a `while` condition, or an `if` or
`match` with a `break`). In MIR, this is typically lowered to a `SwitchInt`,
with one branch to stay in the loop, and another branch to break out of the
loop. The branch that breaks out will almost always execute less often,
-so `InstrumentCoverage` chooses to add a `Counter` to that branch, and an
-`Expression(continue) = Counter(loop) - Counter(break)` to the branch that
+so `InstrumentCoverage` chooses to add a `CounterIncrement` to that branch, and
+uses an expression (`Counter(loop) - Counter(break)`) for the branch that
continues.
The `InstrumentCoverage` MIR pass is documented in
@@ -130,9 +130,9 @@ 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
+[`FunctionCoverageInfo`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/struct.FunctionCoverageInfo.html
[code-region]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/struct.CodeRegion.html
-[`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
+[`CoverageKind::CounterIncrement`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.CounterIncrement
[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
@@ -150,40 +150,38 @@ MIR `Statement` into some backend-specific action or instruction.
match statement.kind {
...
mir::StatementKind::Coverage(box ref coverage) => {
- self.codegen_coverage(&mut bx, coverage.clone(), statement.source_info.scope);
- bx
+ self.codegen_coverage(bx, coverage, statement.source_info.scope);
}
```
-`codegen_coverage()` handles each `CoverageKind` as follows:
+`codegen_coverage()` handles inlined statements and then forwards the coverage
+statement to [`Builder::add_coverage`], which handles each `CoverageKind` as
+follows:
-- For all `CoverageKind`s, Coverage data (counter ID, expression equation
- and ID, and code regions) are passed to the backend's `Builder`, to
- populate data structures that will be used to generate the crate's
- "Coverage Map". (See the [`FunctionCoverage`][function-coverage] `struct`.)
-- For `CoverageKind::Counter`s, an instruction is injected in the backend
+
+- For both `CounterIncrement` and `ExpressionUsed`, the underlying counter or
+ expression ID is passed through to the corresponding [`FunctionCoverage`]
+ struct to indicate that the corresponding regions of code were not removed
+ by MIR optimizations.
+- For `CoverageKind::CounterIncrement`s, an instruction is injected in the backend
IR to increment the physical counter, by calling the `BuilderMethod`
[`instrprof_increment()`][instrprof-increment].
```rust
- pub fn codegen_coverage(&self, bx: &mut Bx, coverage: Coverage, scope: SourceScope) {
+ fn add_coverage(&mut self, instance: Instance<'tcx>, coverage: &Coverage) {
...
- let instance = ... // the scoped instance (current or inlined function)
- let Coverage { kind, code_region } = coverage;
- match kind {
- CoverageKind::Counter { function_source_hash, id } => {
- ...
- bx.add_coverage_counter(instance, id, code_region);
+ let Coverage { kind } = coverage;
+ match *kind {
+ CoverageKind::CounterIncrement { id } => {
+ func_coverage.mark_counter_id_seen(id);
...
bx.instrprof_increment(fn_name, hash, num_counters, index);
}
- CoverageKind::Expression { id, lhs, op, rhs } => {
- bx.add_coverage_counter_expression(instance, id, lhs, op, rhs, code_region);
+ CoverageKind::ExpressionUsed { id } => {
+ func_coverage.mark_expression_id_seen(id);
}
- CoverageKind::Unreachable => {
- bx.add_coverage_unreachable(
- instance,
- code_region.expect(...
+ }
+ }
```
> The function name `instrprof_increment()` is taken from the LLVM intrinsic
@@ -199,7 +197,8 @@ 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_llvm/coverageinfo/map_data/struct.FunctionCoverage.html
+[`Builder::add_coverage`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/builder/struct.Builder.html#method.add_coverage
+[`FunctionCoverage`]: 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
@@ -327,9 +326,10 @@ Instrumentor::new(&self.name(), tcx, mir_body).inject_counters();
The `CoverageGraph` is a coverage-specific simplification of the MIR control
flow graph (CFG). Its nodes are [`BasicCoverageBlock`s][bcb], which
encompass one or more sequentially-executed MIR `BasicBlock`s
-(with no internal branching), plus a `CoverageKind` counter (to
-be added, via coverage analysis), and an optional set of additional counters
-to count incoming edges (if there are more than one).
+(with no internal branching).
+
+Nodes and edges in the graph can have associated [`BcbCounter`]s, which are
+stored in [`CoverageCounters`].
The `Instrumentor`'s `inject_counters()` uses the `CoverageGraph` to
compute the best places to inject coverage counters, as MIR `Statement`s,
@@ -338,16 +338,15 @@ with the following steps:
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.
-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
+2. [`make_bcb_counters()`][make-bcb-counters] generates `BcbCounter::Counter`s and
+ `BcbCounter::Expression`s for each `CoverageSpan`, plus additional
+ _intermediate expressions_[^intermediate-expressions] that are not associated
+ with any `CodeRegion`, but
are required to compute a final `Expression` value for a `CodeRegion`.
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()`
- - `inject_intermediate_expression()`, called for each intermediate expression
- returned from `make_bcb_counters()`
+ statements.
+4. Attach all other necessary coverage information to the function's body as
+ [`FunctionCoverageInfo`].
[^intermediate-expressions]: Intermediate expressions are sometimes required
because `Expression`s are limited to binary additions or subtractions. For
@@ -359,7 +358,8 @@ intermediate expression for `B - C`.
[coverage-graph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html
[inject-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_counters
[bcb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.BasicCoverageBlock.html
-[debug]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/debug
+[`BcbCounter`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/enum.BcbCounter.html
+[`CoverageCounters`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.CoverageCounters.html
[generate-coverage-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html#method.generate_coverage_spans
[make-bcb-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.BcbCounters.html#method.make_bcb_counters
@@ -505,34 +505,3 @@ its `Counter` or `Expression`.
[bcb-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/counters/struct.BcbCounters.html
[traverse-coverage-graph-with-loops]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.TraverseCoverageGraphWithLoops.html
-
-### Injecting counters into a MIR `BasicBlock`
-
-With the refined `CoverageSpan`s, and after all `Counter`s and `Expression`s are
-created, the final step is to inject the `StatementKind::Coverage` statements
-into the MIR. There are three distinct sources, handled by the following
-functions:
-
-- [`inject_coverage_span_counters()`][inject-coverage-span-counters] injects the
- counter from each `CoverageSpan`'s BCB.
-- [`inject_indirect_counters()`][inject-indirect-counters] injects counters
- for any BCB not assigned to a `CoverageSpan`, and for all edge counters.
- These counters don't have `CoverageSpan`s.
-- [`inject_intermediate_expression()`][inject-intermediate-expression] injects
- the intermediate expressions returned from `make_bcb_counters()`. These
- counters aren't associated with any BCB, edge, or `CoverageSpan`.
-
-These three functions inject the `Coverage` statements into the MIR.
-`Counter`s and `Expression`s with `CoverageSpan`s add `Coverage` statements
-to a corresponding `BasicBlock`, with a `CodeRegion` computed from the
-refined `Span` and current `SourceMap`.
-
-All other `Coverage` statements have a `CodeRegion` of `None`, but they
-still must be injected because they contribute to other `Expression`s.
-
-Finally, edge's with a `CoverageKind::Counter` require a new `BasicBlock`,
-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
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 03c7fb6b7..9ed62c87c 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
@@ -298,6 +298,24 @@ types in the impl, since this mapping describes the type that should
come after the `=` in `type Assoc = ...` for each RPITIT.
</details>
+##### Implied bounds in RPITIT hidden type inference
+
+Since `collect_return_position_impl_trait_in_trait_tys` does fulfillment and
+region resolution, we must provide it `assumed_wf_types` so that we can prove
+region obligations with the same expected implied bounds as
+`compare_method_predicate_entailment` does.
+
+Since the return type of a method is understood to be one of the assumed WF
+types, and we eagerly fold the return type with inference variables to do
+opaque type inference, after opaque type inference, the return type will
+resolve to contain the hidden types of the RPITITs. this would mean that the
+hidden types of the RPITITs would be assumed to be well-formed without having
+independently proven that they are. This resulted in a
+[subtle unsoundness bug](https://github.com/rust-lang/rust/pull/116072). In
+order to prevent this cyclic reasoning, we instead replace the hidden types of
+the RPITITs in the return type of the method with *placeholders*, which lead
+to no implied well-formedness bounds.
+
#### Default trait body
Type-checking a default trait body, like:
diff --git a/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md b/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md
index 47b9fb5d9..95e3c7cc8 100644
--- a/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md
+++ b/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md
@@ -7,7 +7,7 @@
To get diagnostics from the compiler,
configure `rustc_interface::Config` to output diagnostic to a buffer,
and run `TyCtxt.analysis`. The following was tested
-with <!-- date-check: mar 2023 --> `nightly-2023-03-27`:
+with <!-- date-check: oct 2023 --> `nightly-2023-10-03`:
```rust
{{#include ../examples/rustc-driver-getting-diagnostics.rs}}
diff --git a/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md b/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md
index 4edbbca00..fc119c1ec 100644
--- a/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md
+++ b/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md
@@ -5,7 +5,7 @@
## Getting the type of an expression
To get the type of an expression, use the `global_ctxt` to get a `TyCtxt`.
-The following was tested with <!-- date-check: mar 2023 --> `nightly-2023-03-27`:
+The following was tested with <!-- date-check: oct 2023 --> `nightly-2023-10-03`:
```rust
{{#include ../examples/rustc-driver-interacting-with-the-ast.rs}}
diff --git a/src/doc/rustc-dev-guide/src/solve/invariants.md b/src/doc/rustc-dev-guide/src/solve/invariants.md
new file mode 100644
index 000000000..75ae53070
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/solve/invariants.md
@@ -0,0 +1,154 @@
+# Invariants of the type system
+
+FIXME: This file talks about invariants of the type system as a whole, not only the solver
+
+There are a lot of invariants - things the type system guarantees to be true at all times -
+which are desirable or expected from other languages and type systems. Unfortunately, quite
+a few of them do not hold in Rust right now. This is either a fundamental to its design or
+caused by bugs and something that may change in the future.
+
+It is important to know about the things you can assume while working on - and with - the
+type system, so here's an incomplete and inofficial list of invariants of
+the core type system:
+
+- ✅: this invariant mostly holds, with some weird exceptions, you can rely on it outside
+of these cases
+- ❌: this invariant does not hold, either due to bugs or by design, you must not rely on
+it for soundness or have to be incredibly careful when doing so
+
+### `wf(X)` implies `wf(normalize(X))` ✅
+
+If a type containing aliases is well-formed, it should also be
+well-formed after normalizing said aliases. We rely on this as
+otherwise we would have to re-check for well-formedness for these
+types.
+
+This is unfortunately broken for `<fndef as FnOnce<..>>::Output` due to implied bounds,
+resulting in [#114936].
+
+### Structural equality modulo regions implies semantic equality ✅
+
+If you have a some type and equate it to itself after replacing any regions with unique
+inference variables in both the lhs and rhs, the now potentially structurally different
+types should still be equal to each other.
+
+Needed to prevent goals from succeeding in HIR typeck and then failing in MIR borrowck.
+If this does invariant is broken MIR typeck ends up failing with an ICE.
+
+### Applying inference results from a goal does not change its result ❌
+
+TODO: this invariant is formulated in a weird way and needs to be elaborated.
+Pretty much: I would like this check to only fail if there's a solver bug:
+https://github.com/rust-lang/rust/blob/2ffeb4636b4ae376f716dc4378a7efb37632dc2d/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs#L391-L407
+
+If we prove some goal/equate types/whatever, apply the resulting inference constraints,
+and then redo the original action, the result should be the same.
+
+This unfortunately does not hold - at least in the new solver - due to a few annoying reasons.
+
+### The trait solver has to be *locally sound* ✅
+
+This means that we must never return *success* for goals for which no `impl` exists. That would
+mean we assume a trait is implemented even though it is not, which is very likely to result in
+actual unsoundness. When using `where`-bounds to prove a goal, the `impl` will be provided by the
+user of the item.
+
+This invariant only holds if we check region constraints. As we do not check region constraints
+during implicit negative overlap check in coherence, this invariant is broken there. As this check
+relies on *completeness* of the trait solver, it is not able to use the current region constraints
+check - `InferCtxt::resolve_regions` - as its handling of type outlives goals is incomplete.
+
+### Normalization of semantically equal aliases in empty environments results in a unique type ✅
+
+Normalization for alias types/consts has to have a unique result. Otherwise we can easily
+implement transmute in safe code. Given the following function, we have to make sure that
+the input and output types always get normalized to the same concrete type.
+
+```rust
+fn foo<T: Trait>(
+ x: <T as Trait>::Assoc
+) -> <T as Trait>::Assoc {
+ x
+}
+```
+
+Many of the currently known unsound issues end up relying on this invariant being broken.
+It is however very difficult to imagine a sound type system without this invariant, so
+the issue is that the invariant is broken, not that we incorrectly rely on it.
+
+### Generic goals and their instantiations have the same result ✅
+
+Pretty much: If we successfully typecheck a generic function concrete instantiations
+of that function should also typeck. We should not get errors post-monomorphization.
+We can however get overflow errors at that point.
+
+TODO: example for overflow error post-monomorphization
+
+This invariant is relied on to allow the normalization of generic aliases. Breaking
+it can easily result in unsoundness, e.g. [#57893](https://github.com/rust-lang/rust/issues/57893)
+
+### Trait goals in empty environments are proven by a unique impl ✅
+
+If a trait goal holds with an empty environment, there should be a unique `impl`,
+either user-defined or builtin, which is used to prove that goal. This is
+necessary to select a unique method. It
+
+We do however break this invariant in few cases, some of which are due to bugs,
+some by design:
+- *marker traits* are allowed to overlap as they do not have associated items
+- *specialization* allows specializing impls to overlap with their parent
+- the builtin trait object trait implementation can overlap with a user-defined impl:
+[#57893]
+
+### The type system is complete ❌
+
+The type system is not complete, it often adds unnecessary inference constraints, and errors
+even though the goal could hold.
+
+- method selection
+- opaque type inference
+- handling type outlives constraints
+- preferring `ParamEnv` candidates over `Impl` candidates during candidate selection
+in the trait solver
+
+#### The type system is complete during the implicit negative overlap check in coherence ✅
+
+During the implicit negative overlap check in coherence we must never return *error* for
+goals which can be proven. This would allow for overlapping impls with potentially different
+associated items, breaking a bunch of other invariants.
+
+This invariant is currently broken in many different ways while actually something we rely on.
+We have to be careful as it is quite easy to break:
+- generalization of aliases
+- generalization during subtyping binders (luckily not exploitable in coherence)
+
+### Trait solving must be (free) lifetime agnostic ✅
+
+Trait solving during codegen should have the same result as during typeck. As we erase
+all free regions during codegen we must not rely on them during typeck. A noteworthy example
+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 as equal. We can however
+lose equality information from HIR to MIR typeck.
+
+The new solver "uniquifies regions" during canonicalization, canonicalizing `u32: Trait<'x, 'x>`
+as `exists<'0, '1> u32: Trait<'0, '1>`, to make it harder to rely on this property.
+
+### Removing ambiguity makes strictly more things compile ❌
+
+Ideally we *should* not rely on ambiguity for things to compile.
+Not doing that will cause future improvements to be breaking changes.
+
+Due to *incompleteness* this is not the case and improving inference can result in inference
+changes, breaking existing projects.
+
+### Semantic equality implies structural equality ✅
+
+Two types being equal in the type system must mean that they have the
+same `TypeId` after instantiating their generic parameters with concrete
+arguments. This currently does not hold: [#97156].
+
+[#57893]: https://github.com/rust-lang/rust/issues/57893
+[#97156]: https://github.com/rust-lang/rust/issues/97156
+[#114936]: https://github.com/rust-lang/rust/issues/114936 \ No newline at end of file
diff --git a/src/doc/rustc-dev-guide/src/solve/the-solver.md b/src/doc/rustc-dev-guide/src/solve/the-solver.md
index 61e6cad1c..f7d82d117 100644
--- a/src/doc/rustc-dev-guide/src/solve/the-solver.md
+++ b/src/doc/rustc-dev-guide/src/solve/the-solver.md
@@ -6,12 +6,71 @@ approach.
[chalk]: https://rust-lang.github.io/chalk/book/recursive.html
-The basic structure of the solver is a pure function
-`fn evaluate_goal(goal: Goal<'tcx>) -> Response`.
-While the actual solver is not fully pure to deal with overflow and cycles, we are
-going to defer that for now.
+## A rough walkthrough
-To deal with inference variables and to improve caching, we use
-[canonicalization](./canonicalization.md).
+The entry-point of the solver is `InferCtxtEvalExt::evaluate_root_goal`. This
+function sets up the root `EvalCtxt` and then calls `EvalCtxt::evaluate_goal`,
+to actually enter the trait solver.
-TODO: write the remaining code for this as well.
+`EvalCtxt::evaluate_goal` handles [canonicalization](./canonicalization.md), caching,
+overflow, and solver cycles. Once that is done, it creates a nested `EvalCtxt` with a
+separate local `InferCtxt` and calls `EvalCtxt::compute_goal`, which is responsible for the
+'actual solver behavior'. We match on the `PredicateKind`, delegating to a separate function
+for each one.
+
+For trait goals, such a `Vec<T>: Clone`, `EvalCtxt::compute_trait_goal` has
+to collect all the possible ways this goal can be proven via
+`EvalCtxt::assemble_and_evaluate_candidates`. Each candidate is handled in
+a separate "probe", to not leak inference constraints to the other candidates.
+We then try to merge the assembled candidates via `EvalCtxt::merge_candidates`.
+
+
+## Important concepts and design pattern
+
+### `EvalCtxt::add_goal`
+
+To prove nested goals, we don't directly call `EvalCtxt::compute_goal`, but instead
+add the goal to the `EvalCtxt` with `EvalCtxt::all_goal`. We then prove all nested
+goals together in either `EvalCtxt::try_evaluate_added_goals` or
+`EvalCtxt::evaluate_added_goals_and_make_canonical_response`. This allows us to handle
+inference constraints from later goals.
+
+E.g. if we have both `?x: Debug` and `(): ConstrainToU8<?x>` as nested goals,
+then proving `?x: Debug` is initially ambiguous, but after proving `(): ConstrainToU8<?x>`
+we constrain `?x` to `u8` and proving `u8: Debug` succeeds.
+
+### Matching on `TyKind`
+
+We lazily normalize types in the solver, so we always have to assume that any types
+and constants are potentially unnormalized. This means that matching on `TyKind` can easily
+be incorrect.
+
+We handle normalization in two different ways. When proving `Trait` goals when normalizing
+associated types, we separately assemble candidates depending on whether they structurally
+match the self type. Candidates which match on the self type are handled in
+`EvalCtxt::assemble_candidates_via_self_ty` which recurses via
+`EvalCtxt::assemble_candidates_after_normalizing_self_ty`, which normalizes the self type
+by one level. In all other cases we have to match on a `TyKind` we first use
+`EvalCtxt::try_normalize_ty` to normalize the type as much as possible.
+
+### Higher ranked goals
+
+In case the goal is higher-ranked, e.g. `for<'a> F: FnOnce(&'a ())`, `EvalCtxt::compute_goal`
+eagerly instantiates `'a` with a placeholder and then recursively proves
+`F: FnOnce(&'!a ())` as a nested goal.
+
+### Dealing with choice
+
+Some goals can be proven in multiple ways. In these cases we try each option in
+a separate "probe" and then attempt to merge the resulting responses by using
+`EvalCtxt::try_merge_responses`. If merging the responses fails, we use
+`EvalCtxt::flounder` instead, returning ambiguity. For some goals, we try
+incompletely prefer some choices over others in case `EvalCtxt::try_merge_responses`
+fails.
+
+## Learning more
+
+The solver should be fairly self-contained. I hope that the above information provides a
+good foundation when looking at the code itself. Please reach out on zulip if you get stuck
+while doing so or there are some quirks and design decisions which were unclear and deserve
+better comments or should be mentioned here.
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 c3089f4a8..7c1e0b684 100644
--- a/src/doc/rustc-dev-guide/src/solve/trait-solving.md
+++ b/src/doc/rustc-dev-guide/src/solve/trait-solving.md
@@ -39,77 +39,6 @@ which does not have any nested goals. Therefore `Vec<T>: Clone` holds.
The trait solver can either return success, ambiguity or an error as a [`CanonicalResponse`].
For success and ambiguity it also returns constraints inference and region constraints.
-## Requirements
-
-Before we dive into the new solver lets first take the time to go through all of our requirements
-on the trait system. We can then use these to guide our design later on.
-
-TODO: elaborate on these rules and get more precise about their meaning.
-Also add issues where each of these rules have been broken in the past
-(or still are).
-
-### 1. The trait solver has to be *sound*
-
-This means that we must never return *success* for goals for which no `impl` exists. That would
-simply be unsound by assuming a trait is implemented even though it is not. When using predicates
-from the `where`-bounds, the `impl` will be proved by the user of the item.
-
-### 2. If type checker solves generic goal concrete instantiations of that goal have the same result
-
-Pretty much: If we successfully typecheck a generic function concrete instantiations
-of that function should also typeck. We should not get errors post-monomorphization.
-We can however get overflow as in the following snippet:
-
-```rust
-fn foo<T: Trait>(x: )
-```
-
-### 3. Trait goals in empty environments are proven by a unique impl
-
-If a trait goal holds with an empty environment, there is a unique `impl`,
-either user-defined or builtin, which is used to prove that goal.
-
-This is necessary for codegen to select a unique method.
-An exception here are *marker traits* which are allowed to overlap.
-
-### 4. Normalization in empty environments results in a unique type
-
-Normalization for alias types/consts has a unique result. Otherwise we can easily implement
-transmute in safe code. Given the following function, we have to make sure that the input and
-output types always get normalized to the same concrete type.
-```rust
-fn foo<T: Trait>(
- x: <T as Trait>::Assoc
-) -> <T as Trait>::Assoc {
- x
-}
-```
-
-### 5. During coherence trait solving has to be complete
-
-During coherence we never return *error* for goals which can be proven. This allows overlapping
-impls which would break rule 3.
-
-### 6. Trait solving must be (free) lifetime agnostic
-
-Trait solving during codegen should have the same result as during typeck. As we erase
-all free regions during codegen we must not rely on them during typeck. A noteworthy example
-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 as equal. We can however
-lose equality information from HIR to MIR typeck.
-
-### 7. Removing ambiguity makes strictly more things compile
-
-We *should* not rely on ambiguity for things to compile.
-Not doing that will cause future improvements to be breaking changes.
-
-### 8. semantic equality implies structural equality
-
-Two types being equal in the type system must mean that they have the same `TypeId`.
-
-
[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/traits/solve/struct.Goal.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/stabilization_guide.md b/src/doc/rustc-dev-guide/src/stabilization_guide.md
index 001ed25a5..9bc70f65c 100644
--- a/src/doc/rustc-dev-guide/src/stabilization_guide.md
+++ b/src/doc/rustc-dev-guide/src/stabilization_guide.md
@@ -109,7 +109,7 @@ to stabilize, something like (this example is taken from
```rust,ignore
// pub(restricted) visibilities (RFC 1422)
-(active, pub_restricted, "CURRENT_RUSTC_VERSION", Some(32409)),
+(unstable, pub_restricted, "CURRENT_RUSTC_VERSION", Some(32409)),
```
The above line should be moved down to the area for "accepted"
diff --git a/src/doc/rustc-dev-guide/src/tests/headers.md b/src/doc/rustc-dev-guide/src/tests/headers.md
index f066dbbb5..fce2397e5 100644
--- a/src/doc/rustc-dev-guide/src/tests/headers.md
+++ b/src/doc/rustc-dev-guide/src/tests/headers.md
@@ -190,7 +190,7 @@ The following headers are generally available, and not specific to particular
test suites.
* `compile-flags` passes extra command-line args to the compiler,
- e.g. `compile-flags -g` which forces debuginfo to be enabled.
+ e.g. `// compile-flags: -g` which forces debuginfo to be enabled.
* `run-flags` passes extra args to the test if the test is to be executed.
* `edition` controls the edition the test should be compiled with
(defaults to 2015). Example usage: `// edition:2018`.
diff --git a/src/doc/rustc-dev-guide/src/traits/unsize.md b/src/doc/rustc-dev-guide/src/traits/unsize.md
new file mode 100644
index 000000000..b11760992
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/traits/unsize.md
@@ -0,0 +1,84 @@
+# [`CoerceUnsized`](https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html)
+
+`CoerceUnsized` is primarily concerned with data containers. When a struct
+(typically, a smart pointer) implements `CoerceUnsized`, that means that the
+data it points to is being unsized.
+
+Some implementors of `CoerceUnsized` include:
+* `&T`
+* `Arc<T>`
+* `Box<T>`
+
+This trait is (eventually) intended to be implemented by user-written smart
+pointers, and there are rules about when a type is allowed to implement
+`CoerceUnsized` that are explained in the trait's documentation.
+
+# [`Unsize`](https://doc.rust-lang.org/std/marker/trait.Unsize.html)
+
+To contrast, the `Unsize` trait is concerned the actual types that are allowed
+to be unsized.
+
+This is not intended to be implemented by users ever, since `Unsize` does not
+instruct the compiler (namely codegen) *how* to unsize a type, just whether it
+is allowed to be unsized. This is paired somewhat intimately with codegen
+which must understand how types are represented and unsized.
+
+## Primitive unsizing implementations
+
+Built-in implementations are provided for:
+* `T` -> `dyn Trait + 'a` when `T: Trait` (and `T: Sized + 'a`, and `Trait`
+ is object safe).
+* `[T; N]` -> `[T]`
+
+## Structural implementations
+
+There are two implementations of `Unsize` which can be thought of as
+structural:
+* `(A1, A2, .., An): Unsize<(A1, A2, .., U)>` given `An: Unsize<U>`, which
+ allows the tail field of a tuple to be unsized. This is gated behind the
+ [`unsized_tuple_coercion`] feature.
+* `Struct<.., Pi, .., Pj, ..>: Unsize<Struct<.., Ui, .., Uj, ..>>` given
+ `TailField<Pi, .., Pj>: Unsize<Ui, .. Uj>`, which allows the tail field of a
+ struct to be unsized if it is the only field that mentions generic parameters
+ `Pi`, .., `Pj` (which don't need to be contiguous).
+
+The rules for the latter implementation are slightly complicated, since they
+may allow more than one parameter to be changed (not necessarily unsized) and
+are best stated in terms of the tail field of the struct.
+
+[`unsized_tuple_coercion`]: https://doc.rust-lang.org/beta/unstable-book/language-features/unsized-tuple-coercion.html
+
+## Upcasting implementations
+
+Two things are called "upcasting" internally:
+1. True upcasting `dyn SubTrait` -> `dyn SuperTrait` (this also allows
+ dropping auto traits and adjusting lifetimes, as below).
+2. Dropping auto traits and adjusting the lifetimes of dyn trait
+ *without changing the principal[^1]*:
+ `dyn Trait + AutoTraits... + 'a` -> `dyn Trait + NewAutoTraits... + 'b`
+ when `AutoTraits` ⊇ `NewAutoTraits`, and `'a: 'b`.
+
+These may seem like different operations, since (1.) includes adjusting the
+vtable of a dyn trait, while (2.) is a no-op. However, to the type system,
+these are handled with much the same code.
+
+This built-in implementation of `Unsize` is the most involved, particularly
+after [it was reworked](https://github.com/rust-lang/rust/pull/114036) to
+support the complexities of associated types.
+
+Specifically, the upcasting algorithm involves: For each supertrait of the
+source dyn trait's principal (including itself)...
+1. Unify the super trait ref with the principal of the target (making sure
+ we only ever upcast to a true supertrait, and never [via an impl]).
+2. For every auto trait in the source, check that it's present in the principal
+ (allowing us to drop auto traits, but never gain new ones).
+3. For every projection in the source, check that it unifies with a single
+ projection in the target (since there may be more than one given
+ `trait Sub: Sup<.., A = i32> + Sup<.., A = u32>`).
+
+[via an impl]: https://github.com/rust-lang/rust/blob/f3457dbf84cd86d284454d12705861398ece76c3/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs#L19
+
+Specifically, (3.) prevents a choice of projection bound to guide inference
+unnecessarily, though it may guide inference when it is unambiguous.
+
+[^1]: The principal is the one non-auto trait of a `dyn Trait`. \ No newline at end of file
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 5c6633864..1b27b77b3 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -33,7 +33,7 @@
- [\*-esp-espidf](platform-support/esp-idf.md)
- [\*-unknown-fuchsia](platform-support/fuchsia.md)
- [\*-kmc-solid_\*](platform-support/kmc-solid.md)
- - [csky-unknown-linux-gnuabiv2](platform-support/csky-unknown-linux-gnuabiv2.md)
+ - [csky-unknown-linux-gnuabiv2\*](platform-support/csky-unknown-linux-gnuabiv2.md)
- [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md)
- [loongarch\*-unknown-none\*](platform-support/loongarch-none.md)
- [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)
@@ -41,6 +41,7 @@
- [mipsel-sony-psx](platform-support/mipsel-sony-psx.md)
- [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md)
- [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md)
+ - [powerpc64-ibm-aix](platform-support/aix.md)
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
- [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index d72543c7e..cfbe1e09c 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -249,11 +249,9 @@ flavor. Valid options are:
* `gcc`: use the `cc` executable, which is typically gcc or clang on many systems.
* `ld`: use the `ld` executable.
* `msvc`: use the `link.exe` executable from Microsoft Visual Studio MSVC.
-* `ptx-linker`: use
- [`rust-ptx-linker`](https://github.com/denzp/rust-ptx-linker) for Nvidia
- NVPTX GPGPU support.
-* `bpf-linker`: use
- [`bpf-linker`](https://github.com/alessandrod/bpf-linker) for eBPF support.
+* `ptx`: use [`rust-ptx-linker`](https://github.com/denzp/rust-ptx-linker)
+ for Nvidia NVPTX GPGPU support.
+* `bpf`: use [`bpf-linker`](https://github.com/alessandrod/bpf-linker) for eBPF support.
* `wasm-ld`: use the [`wasm-ld`](https://lld.llvm.org/WebAssembly.html)
executable, a port of LLVM `lld` for WebAssembly.
* `ld64.lld`: use the LLVM `lld` executable with the [`-flavor darwin`
diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md
index 172048704..d4e2fc52e 100644
--- a/src/doc/rustc/src/exploit-mitigations.md
+++ b/src/doc/rustc/src/exploit-mitigations.md
@@ -1,12 +1,12 @@
# Exploit Mitigations
-This chapter documents the exploit mitigations supported by the Rust
-compiler, and is by no means an extensive survey of the Rust programming
-language’s security features.
+This chapter documents the exploit mitigations supported by the Rust compiler,
+and is by no means an extensive survey of the Rust programming language’s
+security features.
This chapter is for software engineers working with the Rust programming
-language, and assumes prior knowledge of the Rust programming language and
-its toolchain.
+language, and assumes prior knowledge of the Rust programming language and its
+toolchain.
## Introduction
@@ -14,8 +14,8 @@ its toolchain.
The Rust programming language provides memory[1] and thread[2] safety
guarantees via its ownership[3], references and borrowing[4], and slice
types[5] features. However, Unsafe Rust[6] introduces unsafe blocks, unsafe
-functions and methods, unsafe traits, and new types that are not subject to
-the borrowing rules.
+functions and methods, unsafe traits, and new types that are not subject to the
+borrowing rules.
Parts of the Rust standard library are implemented as safe abstractions over
unsafe code (and historically have been vulnerable to memory corruption[7]).
@@ -23,33 +23,32 @@ Furthermore, the Rust code and documentation encourage creating safe
abstractions over unsafe code. This can cause a false sense of security if
unsafe code is not properly reviewed and tested.
-Unsafe Rust introduces features that do not provide the same memory and
-thread safety guarantees. This causes programs or libraries to be
-susceptible to memory corruption (CWE-119)[8] and concurrency issues
-(CWE-557)[9]. Modern C and C++ compilers provide exploit mitigations to
-increase the difficulty to exploit vulnerabilities resulting from these
-issues. Therefore, the Rust compiler must also support these exploit
-mitigations in order to mitigate vulnerabilities resulting from the use of
-Unsafe Rust. This chapter documents these exploit mitigations and how they
-apply to Rust.
+Unsafe Rust introduces features that do not provide the same memory and thread
+safety guarantees. This causes programs or libraries to be susceptible to
+memory corruption (CWE-119)[8] and concurrency issues (CWE-557)[9]. Modern C
+and C++ compilers provide exploit mitigations to increase the difficulty to
+exploit vulnerabilities resulting from these issues. Therefore, the Rust
+compiler must also support these exploit mitigations in order to mitigate
+vulnerabilities resulting from the use of Unsafe Rust. This chapter documents
+these exploit mitigations and how they apply to Rust.
-This chapter does not discuss the effectiveness of these exploit mitigations
-as they vary greatly depending on several factors besides their design and
-implementation, but rather describe what they do, so their effectiveness can
-be understood within a given context.
+This chapter does not discuss the effectiveness of these exploit mitigations as
+they vary greatly depending on several factors besides their design and
+implementation, but rather describe what they do, so their effectiveness can be
+understood within a given context.
## Exploit mitigations
-This section documents the exploit mitigations applicable to the Rust
-compiler when building programs for the Linux operating system on the AMD64
-architecture and equivalent.<sup id="fnref:1" role="doc-noteref"><a
-href="#fn:1" class="footnote">1</a></sup>
+This section documents the exploit mitigations applicable to the Rust compiler
+when building programs for the Linux operating system on the AMD64 architecture
+and equivalent.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1"
+class="footnote">1</a></sup> All examples in this section were built using
+nightly builds of the Rust compiler on Debian testing.
-The Rust Programming Language currently has no specification. The Rust
-compiler (i.e., rustc) is the language reference implementation. All
-references to “the Rust compiler” in this chapter refer to the language
-reference implementation.
+The Rust Programming Language currently has no specification. The Rust compiler
+(i.e., rustc) is the language reference implementation. All references to “the
+Rust compiler” in this chapter refer to the language reference implementation.
Table I \
Summary of exploit mitigations supported by the Rust compiler when building
@@ -83,8 +82,8 @@ instructing the dynamic linker to load it similarly to a shared object at a
random load address, thus also benefiting from address-space layout
randomization (ASLR). This is also referred to as “full ASLR”.
-The Rust compiler supports position-independent executable, and enables it
-by default since version 0.12.0 (2014-10-09)[10]–[13].
+The Rust compiler supports position-independent executable, and enables it by
+default since version 0.12.0 (2014-10-09)[10]–[13].
```text
$ readelf -h target/release/hello-rust | grep Type:
@@ -93,8 +92,7 @@ $ readelf -h target/release/hello-rust | grep Type:
Fig. 1. Checking if an executable is a position-independent executable.
An executable with an object type of `ET_DYN` (i.e., shared object) and not
-`ET_EXEC` (i.e., executable) is a position-independent executable (see Fig.
-1).
+`ET_EXEC` (i.e., executable) is a position-independent executable (see Fig. 1).
### Integer overflow checks
@@ -104,8 +102,11 @@ behavior (which may cause vulnerabilities) by checking for results of signed
and unsigned integer computations that cannot be represented in their type,
resulting in an overflow or wraparound.
-The Rust compiler supports integer overflow checks, and enables it when
-debug assertions are enabled since version 1.1.0 (2015-06-25)[14]–[20].
+The Rust compiler supports integer overflow checks, and enables it when debug
+assertions are enabled since version 1.0.0 (2015-05-15)[14]–[17], but support
+for it was not completed until version 1.1.0 (2015-06-25)[16]. An option to
+control integer overflow checks was later stabilized in version 1.17.0
+(2017-04-27)[18]–[20].
```compile_fail
fn main() {
@@ -136,21 +137,21 @@ u: 0
Fig. 4. Build and execution of hello-rust-integer with debug assertions
disabled.
-Integer overflow checks are enabled when debug assertions are enabled (see
-Fig. 3), and disabled when debug assertions are disabled (see Fig. 4). To
-enable integer overflow checks independently, use the option to control
-integer overflow checks, scoped attributes, or explicit checking methods
-such as `checked_add`<sup id="fnref:2" role="doc-noteref"><a href="#fn:2"
+Integer overflow checks are enabled when debug assertions are enabled (see Fig.
+3), and disabled when debug assertions are disabled (see Fig. 4). To enable
+integer overflow checks independently, use the option to control integer
+overflow checks, scoped attributes, or explicit checking methods such as
+`checked_add`<sup id="fnref:2" role="doc-noteref"><a href="#fn:2"
class="footnote">2</a></sup>.
-It is recommended that explicit wrapping methods such as `wrapping_add` be
-used when wrapping semantics are intended, and that explicit checking and
-wrapping methods always be used when using Unsafe Rust.
+It is recommended that explicit wrapping methods such as `wrapping_add` be used
+when wrapping semantics are intended, and that explicit checking and wrapping
+methods always be used when using Unsafe Rust.
-<small id="fn:2">2\. See [the `u32` docs](../std/primitive.u32.html)
-for more information on the checked, overflowing, saturating, and wrapping
-methods (using u32 as an example). <a href="#fnref:2"
-class="reversefootnote" role="doc-backlink">↩</a></small>
+<small id="fn:2">2\. See [the `u32` docs](../std/primitive.u32.html) for more
+information on the checked, overflowing, saturating, and wrapping methods
+(using u32 as an example). <a href="#fnref:2" class="reversefootnote"
+role="doc-backlink">↩</a></small>
### Non-executable memory regions
@@ -158,17 +159,16 @@ class="reversefootnote" role="doc-backlink">↩</a></small>
Non-executable memory regions increase the difficulty of exploitation by
limiting the memory regions that can be used to execute arbitrary code. Most
modern processors provide support for the operating system to mark memory
-regions as non executable, but it was previously emulated by software, such
-as in grsecurity/PaX's
-[PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt) and
-[SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors that
-did not provide support for it. This is also known as “No Execute (NX) Bit”,
-“Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others.
+regions as non executable, but it was previously emulated by software, such as
+in grsecurity/PaX’s [PAGEEXEC](https://pax.grsecurity.net/docs/pageexec.txt)
+and [SEGMEXEC](https://pax.grsecurity.net/docs/segmexec.txt), on processors
+that did not provide support for it. This is also known as “No Execute (NX)
+Bit”, “Execute Disable (XD) Bit”, “Execute Never (XN) Bit”, and others.
The Rust compiler supports non-executable memory regions, and enables it by
-default since its initial release, version 0.1 (2012-01-20)[21], [22], but
-has regressed since then[23]–[25], and enforced by default since version
-1.8.0 (2016-04-14)[25].
+default since its initial release, version 0.1 (2012-01-20)[21], [22], but has
+regressed since then[23]–[25], and enforced by default since version 1.8.0
+(2016-04-14)[25].
```text
$ readelf -l target/release/hello-rust | grep -A 1 GNU_STACK
@@ -178,9 +178,9 @@ $ readelf -l target/release/hello-rust | grep -A 1 GNU_STACK
Fig. 5. Checking if non-executable memory regions are enabled for a given
binary.
-The presence of an element of type `PT_GNU_STACK` in the program header
-table with the `PF_X` (i.e., executable) flag unset indicates non-executable
-memory regions<sup id="fnref:3" role="doc-noteref"><a href="#fn:3"
+The presence of an element of type `PT_GNU_STACK` in the program header table
+with the `PF_X` (i.e., executable) flag unset indicates non-executable memory
+regions<sup id="fnref:3" role="doc-noteref"><a href="#fn:3"
class="footnote">3</a></sup> are enabled for a given binary (see Fig. 5).
Conversely, the presence of an element of type `PT_GNU_STACK` in the program
header table with the `PF_X` flag set or the absence of an element of type
@@ -196,38 +196,40 @@ class="reversefootnote" role="doc-backlink">↩</a></small>
Stack clashing protection protects the stack from overlapping with another
memory region—allowing arbitrary data in both to be overwritten using each
-other—by reading from the stack pages as the stack grows to cause a page
-fault when attempting to read from the guard page/region. This is also
-referred to as “stack probes” or “stack probing”.
+other—by reading from the stack pages as the stack grows to cause a page fault
+when attempting to read from the guard page/region. This is also referred to as
+“stack probes” or “stack probing”.
The Rust compiler supports stack clashing protection via stack probing, and
enables it by default since version 1.20.0 (2017-08-31)[26]–[29].
-![Screenshot of IDA Pro listing cross references to __rust_probestack in hello-rust.](images/image1.png "Cross references to __rust_probestack in hello-rust.")
-Fig. 6. IDA Pro listing cross references to `__rust_probestack` in
-hello-rust.
-
```rust
-fn hello() {
- println!("Hello, world!");
+fn main() {
+ let v: [u8; 16384] = [1; 16384];
+ let first = &v[0];
+ println!("The first element is: {first}");
}
+```
+Fig. 6. hello-rust-stack-probe-1 program.
+![Screenshot of IDA Pro listing the "unrolled loop" stack probe variant in modified hello-rust.](images/image1.png "The \"unrolled loop\" stack probe variant in modified hello-rust.")
+Fig. 7. The "unrolled loop" stack probe variant in modified hello-rust.
+
+```rust
fn main() {
- let _: [u64; 1024] = [0; 1024];
- hello();
+ let v: [u8; 65536] = [1; 65536];
+ let first = &v[0];
+ println!("The first element is: {first}");
}
```
-Fig 7. Modified hello-rust.
+Fig. 8. hello-rust-stack-probe-2 program.
-![Screenshot of IDA Pro listing cross references to __rust_probestack in modified hello-rust.](images/image2.png "Cross references to __rust_probestack in modified hello-rust.")
-Fig. 8. IDA Pro listing cross references to `__rust_probestack` in modified
-hello-rust.
+![Screenshot of IDA Pro listing the "standard loop" stack probe variant in modified hello-rust.](images/image2.png "The \"standard loop\" stack probe variant in modified hello-rust.")
+Fig. 9. The "standard loop" stack probe variant in modified hello-rust.
-To check if stack clashing protection is enabled for a given binary, search
-for cross references to `__rust_probestack`. The `__rust_probestack` is
-called in the prologue of functions whose stack size is larger than a page
-size (see Fig. 6), and can be forced for illustration purposes by modifying
-the hello-rust example as seen in Fig. 7 and Fig. 8.
+To check if stack clashing protection is enabled for a given binary, look for
+any of the two stack probe variants in the prologue of functions whose stack
+size is larger than a page size (see Figs. 6–9).
### Read-only relocations and immediate binding
@@ -246,21 +248,20 @@ $ readelf -l target/release/hello-rust | grep GNU_RELRO
```
Fig. 9. Checking if read-only relocations is enabled for a given binary.
-The presence of an element of type `PT_GNU_RELRO` in the program header
-table indicates read-only relocations are enabled for a given binary (see
-Fig. 9). Conversely, the absence of an element of type `PT_GNU_RELRO` in the
-program header table indicates read-only relocations are not enabled for a
-given binary.
+The presence of an element of type `PT_GNU_RELRO` in the program header table
+indicates read-only relocations are enabled for a given binary (see Fig. 9).
+Conversely, the absence of an element of type `PT_GNU_RELRO` in the program
+header table indicates read-only relocations are not enabled for a given
+binary.
**Immediate binding** protects additional segments containing relocations
-(i.e., `.got.plt`) from being overwritten by instructing the dynamic linker
-to perform all relocations before transferring control to the program during
-startup, so all segments containing relocations can be marked read only
-(when combined with read-only relocations). This is also referred to as
-“full RELRO”.
+(i.e., `.got.plt`) from being overwritten by instructing the dynamic linker to
+perform all relocations before transferring control to the program during
+startup, so all segments containing relocations can be marked read only (when
+combined with read-only relocations). This is also referred to as “full RELRO”.
-The Rust compiler supports immediate binding, and enables it by default
-since version 1.21.0 (2017-10-12)[30], [31].
+The Rust compiler supports immediate binding, and enables it by default since
+version 1.21.0 (2017-10-12)[30], [31].
```text
$ readelf -d target/release/hello-rust | grep BIND_NOW
@@ -270,16 +271,15 @@ Fig. 10. Checking if immediate binding is enabled for a given binary.
The presence of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW`
flag<sup id="fnref:4" role="doc-noteref"><a href="#fn:4"
-class="footnote">4</a></sup> in the dynamic section indicates immediate
-binding is enabled for a given binary (see Fig. 10). Conversely, the absence
-of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag in the
-dynamic section indicates immediate binding is not enabled for a given
-binary.
+class="footnote">4</a></sup> in the dynamic section indicates immediate binding
+is enabled for a given binary (see Fig. 10). Conversely, the absence of an
+element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag in the dynamic
+section indicates immediate binding is not enabled for a given binary.
The presence of both an element of type `PT_GNU_RELRO` in the program header
-table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW`
-flag in the dynamic section indicates full RELRO is enabled for a given
-binary (see Fig. 9 and Fig. 10).
+table and of an element with the `DT_BIND_NOW` tag and the `DF_BIND_NOW` flag
+in the dynamic section indicates full RELRO is enabled for a given binary (see
+Figs. 9–10).
<small id="fn:4">4\. And the `DF_1_NOW` flag for some link editors. <a
href="#fnref:4" class="reversefootnote" role="doc-backlink">↩</a></small>
@@ -287,26 +287,24 @@ href="#fnref:4" class="reversefootnote" role="doc-backlink">↩</a></small>
### Heap corruption protection
-Heap corruption protection protects memory allocated dynamically by
-performing several checks, such as checks for corrupted links between list
-elements, invalid pointers, invalid sizes, double/multiple “frees” of the
-same memory allocated, and many corner cases of these. These checks are
-implementation specific, and vary per allocator.
+Heap corruption protection protects memory allocated dynamically by performing
+several checks, such as checks for corrupted links between list elements,
+invalid pointers, invalid sizes, double/multiple “frees” of the same memory
+allocated, and many corner cases of these. These checks are implementation
+specific, and vary per allocator.
[ARM Memory Tagging Extension
(MTE)](https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/enhancing-memory-safety),
-when available, will provide hardware assistance for a probabilistic
-mitigation to detect memory safety violations by tagging memory allocations,
-and automatically checking that the correct tag is used on every memory
-access.
+when available, will provide hardware assistance for a probabilistic mitigation
+to detect memory safety violations by tagging memory allocations, and
+automatically checking that the correct tag is used on every memory access.
Rust’s default allocator has historically been
-[jemalloc](http://jemalloc.net/), and it has long been the cause of issues
-and the subject of much discussion[32]–[38]. Consequently, it has been
-removed as the default allocator in favor of the operating system’s standard
-C library default allocator<sup id="fnref:5" role="doc-noteref"><a
-href="#fn:5" class="footnote">5</a></sup> since version 1.32.0
-(2019-01-17)[39].
+[jemalloc](http://jemalloc.net/), and it has long been the cause of issues and
+the subject of much discussion[32]–[38]. Consequently, it has been removed as
+the default allocator in favor of the operating system’s standard C library
+default allocator<sup id="fnref:5" role="doc-noteref"><a href="#fn:5"
+class="footnote">5</a></sup> since version 1.32.0 (2019-01-17)[39].
```rust,no_run
fn main() {
@@ -330,8 +328,7 @@ $ cargo run
free(): invalid next size (normal)
Aborted
```
-Fig. 12. Build and execution of hello-rust-heap with debug assertions
-enabled.
+Fig. 12. Build and execution of hello-rust-heap with debug assertions enabled.
```text
$ cargo run --release
@@ -341,47 +338,41 @@ $ cargo run --release
free(): invalid next size (normal)
Aborted
```
-Fig. 13. Build and execution of hello-rust-heap with debug assertions
-disabled.
+Fig. 13. Build and execution of hello-rust-heap with debug assertions disabled.
-Heap corruption checks are being performed when using the default allocator
-(i.e., the GNU Allocator) as seen in Fig. 12 and Fig. 13.
+Heap corruption checks are performed when using the default allocator (i.e.,
+the GNU Allocator) (see Figs. 12–13).
<small id="fn:5">5\. Linux's standard C library default allocator is the GNU
-Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram
-Gloger, which in turn is derived from dlmalloc (Doug Lea malloc) by Doug
-Lea. <a href="#fnref:5" class="reversefootnote"
-role="doc-backlink">↩</a></small>
+Allocator, which is derived from ptmalloc (pthreads malloc) by Wolfram Gloger,
+which in turn is derived from dlmalloc (Doug Lea malloc) by Doug Lea. <a
+href="#fnref:5" class="reversefootnote" role="doc-backlink">↩</a></small>
### Stack smashing protection
-Stack smashing protection protects programs from stack-based buffer
-overflows by inserting a random guard value between local variables and the
-saved return instruction pointer, and checking if this value has changed
-when returning from a function. This is also known as “Stack Protector” or
-“Stack Smashing Protector (SSP)”.
+Stack smashing protection protects programs from stack-based buffer overflows
+by inserting a random guard value between local variables and the saved return
+instruction pointer, and checking if this value has changed when returning from
+a function. This is also known as “Stack Protector” or “Stack Smashing
+Protector (SSP)”.
-The Rust compiler supports stack smashing protection on nightly builds[42].
+The Rust compiler supports stack smashing protection on nightly builds[40].
![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.")
-Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in
-hello-rust.
+Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in hello-rust.
-To check if stack smashing protection is enabled for a given binary, search
-for cross references to `__stack_chk_fail`. The presence of these
-cross-references in Rust-compiled code (e.g., `hello_rust::main`) indicates
-that the stack smashing protection is enabled (see Fig. 14).
+To check if stack smashing protection is enabled for a given binary, search for
+cross references to `__stack_chk_fail` (see Fig. 14).
### Forward-edge control flow protection
-Forward-edge control flow protection protects programs from having its
-control flow changed/hijacked by performing checks to ensure that
-destinations of indirect branches are one of their valid destinations in the
-control flow graph. The comprehensiveness of these checks vary per
-implementation. This is also known as “forward-edge control flow integrity
-(CFI)”.
+Forward-edge control flow protection protects programs from having its control
+flow changed/hijacked by performing checks to ensure that destinations of
+indirect branches are one of their valid destinations in the control flow
+graph. The comprehensiveness of these checks vary per implementation. This is
+also known as “forward-edge control flow integrity (CFI)”.
Newer processors provide hardware assistance for forward-edge control flow
protection, such as ARM Branch Target Identification (BTI), ARM Pointer
@@ -394,22 +385,19 @@ commercially available [grsecurity/PaX Reuse Attack Protector
(RAP)](https://grsecurity.net/rap_faq).
The Rust compiler supports forward-edge control flow protection on nightly
-builds[40]-[41] <sup id="fnref:6" role="doc-noteref"><a href="#fn:6"
+builds[41]-[42] <sup id="fnref:6" role="doc-noteref"><a href="#fn:6"
class="footnote">6</a></sup>.
```text
-$ readelf -s -W target/debug/rust-cfi | grep "\.cfi"
- 12: 0000000000005170 46 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_one.cfi
- 15: 00000000000051a0 16 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi7add_two.cfi
- 17: 0000000000005270 396 FUNC LOCAL DEFAULT 14 _RNvCsjaOHoaNjor6_8rust_cfi4main.cfi
-...
+$ readelf -s -W target/release/hello-rust | grep "\.cfi"
+ 5: 0000000000006480 657 FUNC LOCAL DEFAULT 15 _ZN10hello_rust4main17h4e359f1dcd627c83E.cfi
```
-Fig. 15. Checking if LLVM CFI is enabled for a given binary[41].
+Fig. 15. Checking if LLVM CFI is enabled for a given binary.
The presence of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and
-references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge control
-flow protection) is enabled for a given binary. Conversely, the absence of
-symbols suffixed with ".cfi" or the `__cfi_init` symbol (and references to
+references to `__cfi_check`) indicates that LLVM CFI (i.e., forward-edge
+control flow protection) is enabled for a given binary. Conversely, the absence
+of symbols suffixed with ".cfi" or the `__cfi_init` symbol (and references to
`__cfi_check`) indicates that LLVM CFI is not enabled for a given binary (see
Fig. 15).
@@ -421,48 +409,47 @@ class="reversefootnote" role="doc-backlink">↩</a></small>
### Backward-edge control flow protection
**Shadow stack** protects saved return instruction pointers from being
-overwritten by storing a copy of them on a separate (shadow) stack, and
-using these copies as authoritative values when returning from functions.
-This is also known as “ShadowCallStack” and “Return Flow Guard”, and is
-considered an implementation of backward-edge control flow protection (or
-“backward-edge CFI”).
+overwritten by storing a copy of them on a separate (shadow) stack, and using
+these copies as authoritative values when returning from functions. This is
+also known as “ShadowCallStack” and “Return Flow Guard”, and is considered an
+implementation of backward-edge control flow protection (or “backward-edge
+CFI”).
**Safe stack** protects not only the saved return instruction pointers, but
-also register spills and some local variables from being overwritten by
-storing unsafe variables, such as large arrays, on a separate (unsafe)
-stack, and using these unsafe variables on the separate stack instead. This
-is also known as “SafeStack”, and is also considered an implementation of
-backward-edge control flow protection.
+also register spills and some local variables from being overwritten by storing
+unsafe variables, such as large arrays, on a separate (unsafe) stack, and using
+these unsafe variables on the separate stack instead. This is also known as
+“SafeStack”, and is also considered an implementation of backward-edge control
+flow protection.
-Both shadow and safe stack are intended to be a more comprehensive
-alternatives to stack smashing protection as they protect the saved return
-instruction pointers (and other data in the case of safe stack) from
-arbitrary writes and non-linear out-of-bounds writes.
+Both shadow and safe stack are intended to be a more comprehensive alternatives
+to stack smashing protection as they protect the saved return instruction
+pointers (and other data in the case of safe stack) from arbitrary writes and
+non-linear out-of-bounds writes.
Newer processors provide hardware assistance for backward-edge control flow
-protection, such as ARM Pointer Authentication, and Intel Shadow Stack as
-part of Intel CET.
+protection, such as ARM Pointer Authentication, and Intel Shadow Stack as part
+of Intel CET.
-The Rust compiler supports shadow stack for aarch64 only
-<sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote">7</a></sup>
-on nightly Rust compilers [43]-[44]. Safe stack is available on nightly
-Rust compilers [45]-[46].
+The Rust compiler supports shadow stack for the AArch64 architecture<sup
+id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote">7</a></sup>on
+nightly builds[43]-[44], and also supports safe stack on nightly
+builds[45]-[46].
```text
$ readelf -s target/release/hello-rust | grep __safestack_init
- 1177: 00000000000057b0 444 FUNC GLOBAL DEFAULT 9 __safestack_init
+ 678: 0000000000008c80 426 FUNC GLOBAL DEFAULT 15 __safestack_init
```
Fig. 16. Checking if LLVM SafeStack is enabled for a given binary.
-The presence of the `__safestack_init` symbol indicates that LLVM SafeStack
-is enabled for a given binary (see Fig. 16). Conversely, the absence of the
-`__safestack_init` symbol indicates that LLVM SafeStack is not enabled for a
-given binary.
+The presence of the `__safestack_init` symbol indicates that LLVM SafeStack is
+enabled for a given binary. Conversely, the absence of the `__safestack_init`
+symbol indicates that LLVM SafeStack is not enabled for a given binary (see
+Fig. 16).
-<small id="fn:7">7\. The shadow stack implementation for the AMD64
-architecture and equivalent in LLVM was removed due to performance and
-security issues. <a href="#fnref:7" class="reversefootnote"
-role="doc-backlink">↩</a></small>
+<small id="fn:7">7\. The shadow stack implementation for the AMD64 architecture
+and equivalent in LLVM was removed due to performance and security issues. <a
+href="#fnref:7" class="reversefootnote" role="doc-backlink">↩</a></small>
## Appendix
@@ -470,29 +457,28 @@ role="doc-backlink">↩</a></small>
As of the latest version of the [Linux Standard Base (LSB) Core
Specification](https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/progheader.html),
the `PT_GNU_STACK` program header indicates whether the stack should be
-executable, and the absence of this header indicates that the stack should
-be executable. However, the Linux kernel currently sets the
-`READ_IMPLIES_EXEC` personality upon loading any executable with the
-`PT_GNU_STACK` program header and the `PF_X `flag set or with the absence of
-this header, resulting in not only the stack, but also all readable virtual
-memory mappings being executable.
+executable, and the absence of this header indicates that the stack should be
+executable. However, the Linux kernel currently sets the `READ_IMPLIES_EXEC`
+personality upon loading any executable with the `PT_GNU_STACK` program header
+and the `PF_X` flag set or with the absence of this header, resulting in not
+only the stack, but also all readable virtual memory mappings being executable.
An attempt to fix this [was made in
2012](https://lore.kernel.org/lkml/f298f914-2239-44e4-8aa1-a51282e7fac0@zmail15.collab.prod.int.phx2.redhat.com/),
and another [was made in
2020](https://lore.kernel.org/kernel-hardening/20200327064820.12602-1-keescook@chromium.org/).
The former never landed, and the latter partially fixed it, but introduced
-other issues—the absence of the `PT_GNU_STACK` program header still causes
-not only the stack, but also all readable virtual memory mappings to be
-executable in some architectures, such as IA-32 and equivalent (or causes
-the stack to be non-executable in some architectures, such as AMD64 and
-equivalent, contradicting the LSB).
+other issues—the absence of the `PT_GNU_STACK` program header still causes not
+only the stack, but also all readable virtual memory mappings to be executable
+in some architectures, such as IA-32 and equivalent (or causes the stack to be
+non-executable in some architectures, such as AMD64 and equivalent,
+contradicting the LSB).
-The `READ_IMPLIES_EXEC` personality needs to be completely separated from
-the `PT_GNU_STACK` program header by having a separate option for it (or
-setarch -X could just be used whenever `READ_IMPLIES_EXEC` is needed), and
-the absence of the `PT_GNU_STACK` program header needs to have more secure
-defaults (unrelated to `READ_IMPLIES_EXEC`).
+The `READ_IMPLIES_EXEC` personality needs to be completely separated from the
+`PT_GNU_STACK` program header by having a separate option for it (or setarch -X
+could just be used whenever `READ_IMPLIES_EXEC` is needed), and the absence of
+the `PT_GNU_STACK` program header needs to have more secure defaults (unrelated
+to `READ_IMPLIES_EXEC`).
## References
@@ -576,19 +562,19 @@ defaults (unrelated to `READ_IMPLIES_EXEC`).
25. A. Clark. “Explicitly disable stack execution on linux and bsd #30859.”
GitHub. <https://github.com/rust-lang/rust/pull/30859>.
-26. “Replace stack overflow checking with stack probes #16012.” GitHub.
+26. Zoxc. “Replace stack overflow checking with stack probes #16012.” GitHub.
<https://github.com/rust-lang/rust/issues/16012>.
-27. B. Striegel. “Extend stack probe support to non-tier-1 platforms, and
- clarify policy for mitigating LLVM-dependent unsafety #43241.” GitHub.
- <https://github.com/rust-lang/rust/issues/43241>.
-
-28. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub.
+27. A. Crichton. “rustc: Implement stack probes for x86 #42816.” GitHub.
<https://github.com/rust-lang/rust/pull/42816>.
-29. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub.
+28. A. Crichton. “Add \_\_rust\_probestack intrinsic #175.” GitHub.
<https://github.com/rust-lang/compiler-builtins/pull/175>.
+29. S. Guelton, S. Ledru, J. Stone. “Bringing Stack Clash Protection to Clang /
+ X86 — the Open Source Way.” The LLVM Project Blog.
+ <https://blog.llvm.org/posts/2021-01-05-stack-clash-protection/>.
+
30. B. Anderson. “Consider applying -Wl,-z,relro or -Wl,-z,relro,-z,now by
default #29877.” GitHub. <https://github.com/rust-lang/rust/issues/29877>.
@@ -621,16 +607,16 @@ defaults (unrelated to `READ_IMPLIES_EXEC`).
39. A. Crichton. “Remove the alloc\_jemalloc crate #55238.” GitHub.
<https://github.com/rust-lang/rust/pull/55238>.
-40. R. de C Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support
+40. bbjornse. “Add codegen option for using LLVM stack smash protection #84197.”
+ GitHub. <https://github.com/rust-lang/rust/pull/84197>
+
+41. R. de C. Valle. “Tracking Issue for LLVM Control Flow Integrity (CFI) Support
for Rust #89653.” GitHub. <https://github.com/rust-lang/rust/issues/89653>.
-41. “ControlFlowIntegrity.” The Rust Unstable Book.
+42. “ControlFlowIntegrity.” The Rust Unstable Book.
[https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity).
-42. bbjornse. “add codegen option for using LLVM stack smash protection #84197.”
- GitHub. <https://github.com/rust-lang/rust/pull/84197>
-
-43. ivanloz. “Add support for LLVM ShadowCallStack. #98208.” GitHub.
+43. I. Lozano. “Add support for LLVM ShadowCallStack #98208.” GitHub.
<https://github.com/rust-lang/rust/pull/98208>.
44. “ShadowCallStack.” The Rust Unstable Book.
diff --git a/src/doc/rustc/src/images/image1.png b/src/doc/rustc/src/images/image1.png
index ee2d3fd4f..0da45e566 100644
--- a/src/doc/rustc/src/images/image1.png
+++ b/src/doc/rustc/src/images/image1.png
Binary files differ
diff --git a/src/doc/rustc/src/images/image2.png b/src/doc/rustc/src/images/image2.png
index 03061e1f0..a9cf23f87 100644
--- a/src/doc/rustc/src/images/image2.png
+++ b/src/doc/rustc/src/images/image2.png
Binary files differ
diff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png
index ef02c605e..844a2fe67 100644
--- a/src/doc/rustc/src/images/image3.png
+++ b/src/doc/rustc/src/images/image3.png
Binary files differ
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index ff831a205..907e9c59f 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -33,9 +33,9 @@ All tier 1 targets with host tools support the full standard library.
target | notes
-------|-------
`aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+) [^missing-stack-probes]
-`i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support]
-`i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support]
-`i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+)
+`i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI]
+`i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI]
+`i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI]
`x86_64-apple-darwin` | 64-bit macOS (10.12+, Sierra+)
`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 7+) [^windows-support]
`x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 7+) [^windows-support]
@@ -47,7 +47,10 @@ target | notes
[^windows-support]: Only Windows 10 currently undergoes automated testing. Earlier versions of Windows rely on testing and support from the community.
+[^x86_32-floats-return-ABI]: Due to limitations of the C ABI, floating-point support on `i686` targets is non-compliant: floating-point return values are passed via an x87 register, so NaN payload bits can be lost. See [issue #114479][x86-32-float-issue].
+
[77071]: https://github.com/rust-lang/rust/issues/77071
+[x86-32-float-issue]: https://github.com/rust-lang/rust/issues/114479
## Tier 1
@@ -90,10 +93,6 @@ target | notes
`arm-unknown-linux-gnueabihf` | ARMv6 Linux, hardfloat (kernel 3.2, glibc 2.17)
`armv7-unknown-linux-gnueabihf` | ARMv7-A Linux, hardfloat (kernel 3.2, glibc 2.17)
[`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36)
-`mips-unknown-linux-gnu` | MIPS Linux (kernel 4.4, glibc 2.23)
-`mips64-unknown-linux-gnuabi64` | MIPS64 Linux, n64 ABI (kernel 4.4, glibc 2.23)
-`mips64el-unknown-linux-gnuabi64` | MIPS64 (LE) Linux, n64 ABI (kernel 4.4, glibc 2.23)
-`mipsel-unknown-linux-gnu` | MIPS (LE) Linux (kernel 4.4, glibc 2.23)
`powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17)
`powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17)
`powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17)
@@ -150,19 +149,16 @@ target | std | notes
`armv7r-none-eabi` | * | Bare ARMv7-R
`armv7r-none-eabihf` | * | Bare ARMv7-R, hardfloat
`asmjs-unknown-emscripten` | ✓ | asm.js via Emscripten
-`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE
-`i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17)
-`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL
-[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android
-`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD
-`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL
+`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE [^x86_32-floats-x87]
+`i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) [^x86_32-floats-x87]
+`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL [^x86_32-floats-x87]
+[`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | 32-bit x86, restricted to Pentium
+[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android [^x86_32-floats-return-ABI]
+`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD [^x86_32-floats-return-ABI]
+`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL [^x86_32-floats-return-ABI]
[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI
[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64D ABI)
[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64S ABI)
-`mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL
-`mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL
-`mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL
-`mipsel-unknown-linux-musl` | ✓ | MIPS (LE) Linux with MUSL
[`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs]
`riscv32i-unknown-none-elf` | * | Bare RISC-V (RV32I ISA)
`riscv32imac-unknown-none-elf` | * | Bare RISC-V (RV32IMAC ISA)
@@ -195,6 +191,8 @@ target | std | notes
`x86_64-unknown-redox` | ✓ | Redox OS
[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | 64-bit UEFI
+[^x86_32-floats-x87]: Floating-point support on `i586` targets is non-compliant: the `x87` registers and instructions used for these targets do not provide IEEE-754-compliant behavior, in particular when it comes to rounding and NaN payload bits. See [issue #114479][x86-32-float-issue].
+
[Fortanix ABI]: https://edp.fortanix.com/
## Tier 3
@@ -220,6 +218,7 @@ target | std | host | notes
-------|:---:|:----:|-------
`aarch64-apple-ios-macabi` | ? | | Apple Catalyst on ARM64
[`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS
+[`aarch64-apple-tvos-sim`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS Simulator
[`aarch64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | ARM64 Apple WatchOS Simulator
[`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3
[`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon
@@ -247,7 +246,7 @@ target | std | host | notes
`armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
[`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv6 NetBSD w/hard-float
[`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain)
-[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ? | | ARMv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain)
+[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ✓ | | ARMv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain)
[`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | ARMv7-A OpenHarmony |
[`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7-A Linux with uClibc, softfloat
[`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7-A Linux with uClibc, hardfloat
@@ -262,23 +261,33 @@ target | std | host | notes
`avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core`
`bpfeb-unknown-none` | * | | BPF (big endian)
`bpfel-unknown-none` | * | | BPF (little endian)
-`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux(little endian)
+`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian)
+`csky-unknown-linux-gnuabiv2hf` | ✓ | | C-SKY abiv2 Linux, hardfloat (little endian)
`hexagon-unknown-linux-musl` | ? | |
-`i386-apple-ios` | ✓ | | 32-bit x86 iOS
-[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS |
-`i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+)
-`i686-pc-windows-msvc` | * | | 32-bit Windows XP support
-[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
-`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku
-[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd
-[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2
-[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD
-`i686-uwp-windows-gnu` | ? | |
-`i686-uwp-windows-msvc` | ? | |
-`i686-wrs-vxworks` | ? | |
+`i386-apple-ios` | ✓ | | 32-bit x86 iOS [^x86_32-floats-return-ABI]
+[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS [^x86_32-floats-return-ABI]
+`i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+) [^x86_32-floats-return-ABI]
+`i686-pc-windows-msvc` | * | | 32-bit Windows XP support [^x86_32-floats-return-ABI]
+[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | [^x86_32-floats-return-ABI]
+`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku [^x86_32-floats-return-ABI]
+[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd [^x86_32-floats-return-ABI]
+[`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2 [^x86_32-floats-return-ABI]
+[`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD [^x86_32-floats-return-ABI]
+`i686-uwp-windows-gnu` | ? | | [^x86_32-floats-return-ABI]
+`i686-uwp-windows-msvc` | ? | | [^x86_32-floats-return-ABI]
+`i686-wrs-vxworks` | ? | | [^x86_32-floats-return-ABI]
[`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux
+`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
+`mips-unknown-linux-musl` | ✓ | | MIPS Linux with musl libc
`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc
[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux MUSL
+`mips64-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 Linux, N64 ABI (kernel 4.4, glibc 2.23)
+`mips64-unknown-linux-muslabi64` | ✓ | | MIPS64 Linux, N64 ABI, musl libc
+`mips64el-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 (little endian) Linux, N64 ABI (kernel 4.4, glibc 2.23)
+`mips64el-unknown-linux-muslabi64` | ✓ | | MIPS64 (little endian) Linux, N64 ABI, musl libc
+`mipsel-unknown-linux-gnu` | ✓ | ✓ | MIPS (little endian) Linux (kernel 4.4, glibc 2.23)
+`mipsel-unknown-linux-musl` | ✓ | | MIPS (little endian) Linux with musl libc
+[`mipsel-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | 32-bit MIPS (LE), requires mips32 cpu support
`mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP)
[`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * | | MIPS (LE) Sony PlayStation 1 (PSX)
`mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc
@@ -301,7 +310,7 @@ target | std | host | notes
`powerpc64-wrs-vxworks` | ? | |
`powerpc64le-unknown-linux-musl` | ? | |
[`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64
-`powerpc64-ibm-aix` | ? | | 64-bit AIX (7.2 and newer)
+[`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer)
`riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33)
`riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches)
`riscv32im-unknown-none-elf` | * | | Bare RISC-V (RV32IM ISA)
diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md
index f8cd92f92..9233a36db 100644
--- a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md
+++ b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md
@@ -58,7 +58,7 @@ To build a rust toolchain, create a `config.toml` with the following contents:
```toml
profile = "compiler"
-changelog-seen = 2
+change-id = 115898
[build]
sanitizers = true
diff --git a/src/doc/rustc/src/platform-support/aix.md b/src/doc/rustc/src/platform-support/aix.md
new file mode 100644
index 000000000..c3ce71a18
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/aix.md
@@ -0,0 +1,26 @@
+# `powerpc64-ibm-aix`
+
+**Tier: 3**
+
+Rust for AIX operating system, currently only 64-bit PowerPC is supported.
+
+## Target maintainers
+
+- QIU Chaofan `qiucofan@cn.ibm.com`, https://github.com/ecnelises
+- Kai LUO, `lkail@cn.ibm.com`, https://github.com/bzEq
+
+## Requirements
+
+This target supports host tools, std and alloc. This target cannot be cross-compiled as for now, mainly because of the unavailability of system linker on other platforms.
+
+Binary built for this target is expected to run on Power7 or newer CPU, and AIX 7.2 or newer version.
+
+Binary format of this platform is [XCOFF](https://www.ibm.com/docs/en/aix/7.2?topic=formats-xcoff-object-file-format). Archive file format is ['AIX big format'](https://www.ibm.com/docs/en/aix/7.2?topic=formats-ar-file-format-big).
+
+## Testing
+
+This target supports running test suites natively, but it's not available to cross-compile and execute in emulator.
+
+## Interoperability with C code
+
+This target supports C code. C code compiled by XL, Open XL and Clang are compatible with Rust. Typical triple of AIX on 64-bit PowerPC of these compilers are also `powerpc64-ibm-aix`.
diff --git a/src/doc/rustc/src/platform-support/android.md b/src/doc/rustc/src/platform-support/android.md
index 4ef74295e..9ddf00e3a 100644
--- a/src/doc/rustc/src/platform-support/android.md
+++ b/src/doc/rustc/src/platform-support/android.md
@@ -45,3 +45,19 @@ The riscv64-linux-android target is supported as a Tier 3 target.
A list of all supported targets can be found
[here](../platform-support.html)
+
+## Architecture Notes
+
+### riscv64-linux-android
+
+Currently the `riscv64-linux-android` target requires the following architecture features/extensions:
+
+* `a` (atomics)
+* `d` (double-precision floating-point)
+* `c` (compressed instruction set)
+* `f` (single-precision floating-point)
+* `m` (multiplication and division)
+* `v` (vector)
+* `Zba` (address calculation instructions)
+* `Zbb` (base instructions)
+* `Zbs` (single-bit instructions)
diff --git a/src/doc/rustc/src/platform-support/apple-tvos.md b/src/doc/rustc/src/platform-support/apple-tvos.md
index d87fd1959..e7ea109df 100644
--- a/src/doc/rustc/src/platform-support/apple-tvos.md
+++ b/src/doc/rustc/src/platform-support/apple-tvos.md
@@ -52,7 +52,7 @@ The targets can be built by enabling them for a `rustc` build in `config.toml`,
```toml
[build]
build-stage = 1
-target = ["aarch64-apple-tvos", "x86_64-apple-tvos"]
+target = ["aarch64-apple-tvos", "x86_64-apple-tvos", "aarch64-apple-tvos-sim"]
```
It's possible that cargo under `-Zbuild-std` may also be used to target them.
@@ -67,6 +67,8 @@ Rust programs can be built for these targets
$ rustc --target aarch64-apple-tvos your-code.rs
...
$ rustc --target x86_64-apple-tvos your-code.rs
+...
+$ rustc --target aarch64-apple-tvos-sim your-code.rs
```
## Testing
diff --git a/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md b/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md
index 49eed366d..e1473bd96 100644
--- a/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md
+++ b/src/doc/rustc/src/platform-support/armv7-sony-vita-newlibeabihf.md
@@ -2,15 +2,16 @@
**Tier: 3**
-This tier supports the ARM Cortex A9 processor running on a PlayStation Vita console. `armv7-vita-newlibeabihf` aims to have support for `std` crate using `newlib` as a bridge.
+This tier supports the ARM Cortex A9 processor running on a PlayStation Vita console.
Rust support for this target is not affiliated with Sony, and is not derived
from nor used with any official Sony SDK.
## Target maintainers
-* [@amg98](https://github.com/amg98)
* [@nikarh](https://github.com/nikarh)
+* [@pheki](https://github.com/pheki)
+* [@ZetaNumbers](https://github.com/ZetaNumbers)
## Requirements
@@ -20,18 +21,16 @@ This target is cross-compiled, and requires installing [VITASDK](https://vitasdk
`alloc`, and `panic_abort`.
`std` is partially supported, but mostly works. Some APIs are unimplemented
-and will simply return an error, such as `std::process`. An allocator is provided
-by default.
+and will simply return an error, such as `std::process`.
-In order to support some APIs, binaries must be linked against `libc` written
-for the target, using a linker for the target. These are provided by the
-VITASDK toolchain.
+This target generates binaries in the ELF format with thumb ISA by default.
+
+Binaries are linked with `arm-vita-eabi-gcc` provided by VITASDK toolchain.
-This target generates binaries in the ELF format with thumb ISA.
## Building the target
-Rust does not ship pre-compiled artifacts for this target. You can use `build-std` flag to build binaries with `std`:
+Rust does not ship pre-compiled artifacts for this target. You can use `build-std` flag to build ELF binaries with `std`:
```sh
cargo build -Z build-std=std,panic_abort --target=armv7-sony-vita-newlibeabihf --release
@@ -39,113 +38,45 @@ cargo build -Z build-std=std,panic_abort --target=armv7-sony-vita-newlibeabihf -
## Building Rust programs
-To test your developed rust programs on PlayStation Vita, first you must correctly package your elf. These steps can be preformed using tools available in VITASDK, and can be automated using a tool like `cargo-make`.
+The recommended way to build artifacts that can be installed and run on PlayStation Vita is by using the [cargo-vita](https://github.com/vita-rust/cargo-vita) tool. This tool uses `build-std` and VITASDK toolchain to build artifacts runnable on Vita.
+
+To install the tool run:
+
+```sh
+cargo install cargo-vita
+```
-First, set up environment variables for `VITASDK`, and it's binaries:
+[VITASDK](https://vitasdk.org/) toolchain must be installed, and the `VITASDK` environment variable must be set to its location, e.g.:
```sh
export VITASDK=/opt/vitasdk
-export PATH=$PATH:$VITASDK/bin
```
-Use the example below as a template for your project:
+Add the following section to your project's `Cargo.toml`:
+
```toml
-[env]
-TITLE = "Rust Hello World"
-TITLEID = "RUST00001"
-
-# At least a "sce_sys" folder should be place there for app metadata (title, icons, description...)
-# You can find sample assets for that on $VITASDK/share/gcc-arm-vita-eabi/samples/hello_world/sce_sys/
-STATIC_DIR = "static" # Folder where static assets should be placed (sce_sys folder is at $STATIC_DIR/sce_sys)
-CARGO_TARGET_DIR = { script = ["echo ${CARGO_TARGET_DIR:=target}"] }
-CARGO_OUT_DIR = "${CARGO_TARGET_DIR}/${RUST_TARGET}/release"
-
-[tasks.build]
-description = "Build the project using `cargo`."
-command = "cargo"
-args = ["build", "-Z", "build-std=std,panic_abort", "--target=armv7-sony-vita-newlibeabihf", "--release"]
-
-[tasks.strip]
-description = "Strip the produced ELF executable."
-dependencies = ["build"]
-command = "arm-vita-eabi-strip"
-args = ["-g", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_FS_NAME}.elf']
-
-[tasks.velf]
-description = "Build an VELF executable from the obtained ELF file."
-dependencies = ["strip"]
-command = "vita-elf-create"
-args = ['${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.elf', '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf']
-
-[tasks.eboot-bin]
-description = "Build an `eboot.bin` file from the obtained VELF file."
-dependencies = ["velf"]
-command = "vita-make-fself"
-args = ["-s", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf', '${CARGO_OUT_DIR}/eboot.bin']
-
-[tasks.param-sfo]
-description = "Build the `param.sfo` manifest using with given TITLE and TITLEID."
-command = "vita-mksfoex"
-args = ["-s", 'TITLE_ID=${TITLEID}', '${TITLE}', '${CARGO_OUT_DIR}/param.sfo']
-
-[tasks.manifest]
-description = "List all static resources into a manifest file."
-script = [
- 'mkdir -p "${CARGO_OUT_DIR}"',
- '''
- if [ -d "${STATIC_DIR}" ]; then
- find "${STATIC_DIR}" -type f > "${CARGO_OUT_DIR}/MANIFEST"
- else
- touch "${CARGO_OUT_DIR}/MANIFEST"
- fi
- '''
-]
-
-[tasks.vpk]
-description = "Build a VPK distribution of the project executable and resources."
-dependencies = ["eboot-bin", "param-sfo", "manifest"]
-script_runner = "@rust"
-script = [
- '''
- use std::io::BufRead;
- use std::fs::File;
-
- fn main() {
-
- let crate_name = env!("CARGO_MAKE_CRATE_NAME");
- let static_dir = env!("STATIC_DIR");
- let out_dir = std::path::PathBuf::from(env!("CARGO_OUT_DIR"));
-
- let mut cmd = ::std::process::Command::new("vita-pack-vpk");
- cmd.arg("-s").arg(out_dir.join("param.sfo"));
- cmd.arg("-b").arg(out_dir.join("eboot.bin"));
-
- // Add files from MANIFEST
- if let Ok(file) = File::open(out_dir.join("MANIFEST")) {
- let mut reader = ::std::io::BufReader::new(file);
- let mut lines = reader.lines();
- while let Some(Ok(line)) = lines.next() {
- let p1 = ::std::path::PathBuf::from(line); // path on FS
- let p2 = p1.strip_prefix(static_dir).unwrap(); // path in VPK
- cmd.arg("--add").arg(format!("{}={}", p1.display(), p2.display()));
- }
- }
-
- cmd.arg(out_dir.join(format!("{}.vpk", crate_name)))
- .output()
- .expect("command failed.");
- }
- '''
-]
+[package.metadata.vita]
+# A unique 9 character alphanumeric identifier of the app.
+title_id = "RUSTAPP01"
+# A title that will be used for the app. Optional, name will be used if not defined
+title_name = "My application"
```
-After running the above script, you should be able to get a *.vpk file in the same folder your *.elf executable resides. Now you can pick it and install it on your own PlayStation Vita using, or you can use an [Vita3K](https://vita3k.org/) emulator.
+To build a VPK with ELF in the release profile, run:
+
+```sh
+cargo vita build vpk --release
+```
+
+After building a *.vpk file it can be uploaded to a PlayStation Vita and installed, or used with a [Vita3K](https://vita3k.org/) emulator.
## Testing
-Currently there is no support to run the rustc test suite for this target.
+The default Rust test runner is supported, and tests can be compiled to an elf and packed to a *.vpk file using `cargo-vita` tool. Filtering tests is not currently supported since passing command-line arguments to the executable is not supported on Vita, so the runner will always execute all tests.
+
+The Rust test suite for `library/std` is not yet supported.
## Cross-compilation
-This target can be cross-compiled from `x86_64` on either Windows, MacOS or Linux systems. Other hosts are not supported for cross-compilation.
+This target can be cross-compiled from `x86_64` on Windows, MacOS or Linux systems. Other hosts are not supported for cross-compilation.
diff --git a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md
index e73598be0..a54abcb60 100644
--- a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md
+++ b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md
@@ -4,8 +4,21 @@
This target supports [C-SKY](https://github.com/c-sky) CPUs with `abi` v2 and `glibc`.
-https://c-sky.github.io/
-https://gitlab.com/c-sky/
+target | std | host | notes
+-------|:---:|:----:|-------
+`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian)
+`csky-unknown-linux-gnuabiv2hf` | ✓ | | C-SKY abiv2 Linux, hardfloat (little endian)
+
+Reference:
+
+- [CSKY ABI Manual](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1695027452256/T-HEAD_800_Series_ABI_Standards_Manual.pdf)
+- [csky-linux-gnuabiv2-toolchain](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource/1356021/1619528643136/csky-linux-gnuabiv2-tools-x86_64-glibc-linux-4.9.56-20210423.tar.gz)
+- [csky-linux-gnuabiv2-qemu](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1689324918932/xuantie-qemu-x86_64-Ubuntu-18.04-20230714-0202.tar.gz)
+
+other links:
+
+- https://c-sky.github.io/
+- https://gitlab.com/c-sky/
## Target maintainers
@@ -13,7 +26,6 @@ https://gitlab.com/c-sky/
## Requirements
-
## Building the target
### Get a C toolchain
@@ -28,13 +40,17 @@ The target can be built by enabling it for a `rustc` build, by placing the follo
```toml
[build]
-target = ["x86_64-unknown-linux-gnu", "csky-unknown-linux-gnuabiv2"]
+target = ["x86_64-unknown-linux-gnu", "csky-unknown-linux-gnuabiv2", "csky-unknown-linux-gnuabiv2hf"]
stage = 2
[target.csky-unknown-linux-gnuabiv2]
# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN
cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc"
+[target.csky-unknown-linux-gnuabiv2hf]
+# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN
+cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc"
+
### Build
```sh
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index f7cce35b1..34ab3cdaf 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -692,10 +692,12 @@ Fuchsia's test runner interacts with the Fuchsia emulator and is located at
test environment with:
```sh
-src/ci/docker/scripts/fuchsia-test-runner.py start \
+( \
+ src/ci/docker/scripts/fuchsia-test-runner.py start \
--rust-build ${RUST_SRC_PATH}/build \
--sdk ${SDK_PATH} \
--target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia} \
+)
```
Where `${RUST_SRC_PATH}/build` is the `build-dir` set in `config.toml` and
diff --git a/src/doc/rustc/src/platform-support/mips-release-6.md b/src/doc/rustc/src/platform-support/mips-release-6.md
index 3f1912fc6..9203a31e9 100644
--- a/src/doc/rustc/src/platform-support/mips-release-6.md
+++ b/src/doc/rustc/src/platform-support/mips-release-6.md
@@ -67,7 +67,7 @@ The following procedure outlines the build process for the MIPS64 R6 target with
### Prerequisite: Disable debuginfo
-A LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `config.toml` to disable this:
+An LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `config.toml` to disable this:
```toml
[rust]
diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md
index b376c4a84..9f0662783 100644
--- a/src/doc/rustc/src/platform-support/nto-qnx.md
+++ b/src/doc/rustc/src/platform-support/nto-qnx.md
@@ -98,7 +98,7 @@ Example content:
```toml
profile = "compiler"
-changelog-seen = 2
+change-id = 115898
```
2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host (for both `aarch64` and `x86_64` targets)
diff --git a/src/doc/rustc/src/platform-support/openharmony.md b/src/doc/rustc/src/platform-support/openharmony.md
index 89539f388..05fd407ed 100644
--- a/src/doc/rustc/src/platform-support/openharmony.md
+++ b/src/doc/rustc/src/platform-support/openharmony.md
@@ -101,7 +101,7 @@ To build a rust toolchain, create a `config.toml` with the following contents:
```toml
profile = "compiler"
-changelog-seen = 2
+change-id = 115898
[build]
sanitizers = true
diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md
index 68cd7fae3..1230ea22b 100644
--- a/src/doc/rustc/src/platform-support/unknown-uefi.md
+++ b/src/doc/rustc/src/platform-support/unknown-uefi.md
@@ -265,9 +265,14 @@ cargo build --target x86_64-unknown-uefi -Zbuild-std=std,panic_abort
#### os_str
- While the strings in UEFI should be valid UCS-2, in practice, many implementations just do not care and use UTF-16 strings.
- Thus, the current implementation supports full UTF-16 strings.
+#### stdio
+- Uses `Simple Text Input Protocol` and `Simple Text Output Protocol`.
+- Note: UEFI uses CRLF for new line. This means Enter key is registered as CR instead of LF.
+#### args
+- Uses `EFI_LOADED_IMAGE_PROTOCOL->LoadOptions`
## Example: Hello World With std
-The following code features a valid UEFI application, including stdio and `alloc` (`OsString` and `Vec`):
+The following code features a valid UEFI application, including `stdio` and `alloc` (`OsString` and `Vec`):
This example can be compiled as binary crate via `cargo` using the toolchain
compiled from the above source (named custom):
@@ -286,6 +291,9 @@ use std::{
};
pub fn main() {
+ println!("Starting Rust Application...");
+
+ // Use System Table Directly
let st = env::system_table().as_ptr() as *mut efi::SystemTable;
let mut s: Vec<u16> = OsString::from("Hello World!\n").encode_wide().collect();
s.push(0);
diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md
index d9cf7ce30..38b655b75 100644
--- a/src/doc/rustc/src/profile-guided-optimization.md
+++ b/src/doc/rustc/src/profile-guided-optimization.md
@@ -145,3 +145,26 @@ in Clang's documentation is therefore an interesting read for anyone who wants
to use PGO with Rust.
[clang-pgo]: https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization
+
+## Community Maintained Tools
+
+As an alternative to directly using the compiler for Profile-Guided Optimization,
+you may choose to go with `cargo-pgo`, which has an intuitive command-line API
+and saves you the trouble of doing all the manual work. You can read more about
+it in their repository accessible from this link: https://github.com/Kobzol/cargo-pgo
+
+For the sake of completeness, here are the corresponding steps using `cargo-pgo`:
+
+```bash
+# Install if you haven't already
+cargo install cargo-pgo
+
+cargo pgo build
+cargo pgo optimize
+```
+
+These steps will do the following just as before:
+
+1. Build an instrumented binary from the source code.
+2. Run the instrumented binary to gather PGO profiles.
+3. Use the gathered PGO profiles from the last step to build an optimized binary.
diff --git a/src/doc/rustdoc/src/advanced-features.md b/src/doc/rustdoc/src/advanced-features.md
index dbf0baec0..1733c8fc9 100644
--- a/src/doc/rustdoc/src/advanced-features.md
+++ b/src/doc/rustdoc/src/advanced-features.md
@@ -110,3 +110,23 @@ https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true
This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL
to automatically go to the first result.
+
+## `#[repr(transparent)]`: Documenting the transparent representation
+
+You can read more about `#[repr(transparent)]` itself in the [Rust Reference][repr-trans-ref] and
+in the [Rustonomicon][repr-trans-nomicon].
+
+Since this representation is only considered part of the public ABI if the single field with non-trivial
+size or alignment is public and if the documentation does not state otherwise, Rustdoc helpfully displays
+the attribute if and only if the non-1-ZST field is public or at least one field is public in case all
+fields are 1-ZST fields. The term *1-ZST* refers to types that are one-aligned and zero-sized.
+
+It would seem that one can manually hide the attribute with `#[cfg_attr(not(doc), repr(transparent))]`
+if one wishes to declare the representation as private even if the non-1-ZST field is public.
+However, due to [current limitations][cross-crate-cfg-doc], this method is not always guaranteed to work.
+Therefore, if you would like to do so, you should always write it down in prose independently of whether
+you use `cfg_attr` or not.
+
+[repr-trans-ref]: https://doc.rust-lang.org/reference/type-layout.html#the-transparent-representation
+[repr-trans-nomicon]: https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent
+[cross-crate-cfg-doc]: https://github.com/rust-lang/rust/issues/114952
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 7473b0992..41602dec4 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -207,6 +207,21 @@ To do so, the `#[doc(keyword = "...")]` attribute is used. Example:
mod empty_mod {}
```
+### Use the Rust logo as the crate logo
+
+This is for official Rust project use only.
+
+Internal Rustdoc pages like settings.html and scrape-examples-help.html show the Rust logo.
+This logo is tracked as a static resource. The attribute `#![doc(rust_logo)]` makes this same
+built-in resource act as the main logo.
+
+```rust
+#![feature(rustdoc_internals)]
+#![allow(internal_features)]
+#![doc(rust_logo)]
+//! This crate has the Rust(tm) branding on it.
+```
+
## Effects of other nightly features
These nightly-only features are not primarily related to Rustdoc,
@@ -613,10 +628,10 @@ Using this flag looks like this:
```bash
$ rustdoc src/lib.rs -Z unstable-options \
- --check-cfg='names()' --check-cfg='values(feature, "foo", "bar")'
+ --check-cfg='cfg(feature, values("foo", "bar"))'
```
-The example above check every well known names (`target_os`, `doc`, `test`, ... via `names()`)
+The example above check every well known names and values (`target_os`, `doc`, `test`, ...)
and check the values of `feature`: `foo` and `bar`.
### `--generate-link-to-definition`: Generate links on types in source code
diff --git a/src/doc/rustdoc/src/write-documentation/what-to-include.md b/src/doc/rustdoc/src/write-documentation/what-to-include.md
index 16457ed0f..75d3b7dae 100644
--- a/src/doc/rustdoc/src/write-documentation/what-to-include.md
+++ b/src/doc/rustdoc/src/write-documentation/what-to-include.md
@@ -73,7 +73,7 @@ and your test suite, this example needs some additional code:
``````text
/// Example
/// ```rust
-/// # main() -> Result<(), std::num::ParseIntError> {
+/// # fn main() -> Result<(), std::num::ParseIntError> {
/// let fortytwo = "42".parse::<u32>()?;
/// println!("{} + 10 = {}", fortytwo, fortytwo+10);
/// # Ok(())
@@ -117,7 +117,7 @@ rustdoc --theme awesome.css src/lib.rs
Here is an example of a new theme, [Ayu].
-[Ayu]: https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/css/themes/ayu.css
+[Ayu]: https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/css/rustdoc.css#L2384-L2574
[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html#rustdoc-does-not-show-unhelpful-implementation-details-c-hidden
[Documentation tests]: documentation-tests.md
[on this blog]: https://blog.guillaume-gomez.fr/articles/2016-09-16+Generating+doc+with+rustdoc+and+a+custom+theme
diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md
index 10f0fbc50..0e15c7907 100644
--- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md
+++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md
@@ -10,97 +10,80 @@ This feature allows you to enable complete or partial checking of configuration.
check them. The `--check-cfg` option takes a value, called the _check cfg specification_. The
check cfg specification is parsed using the Rust metadata syntax, just as the `--cfg` option is.
-`--check-cfg` option can take one of two forms:
+`--check-cfg` option take one form:
-1. `--check-cfg names(...)` enables checking condition names.
-2. `--check-cfg values(...)` enables checking the values within list-valued conditions.
-
-These two options are independent. `names` checks only the namespace of condition names
-while `values` checks only the namespace of the values of list-valued conditions.
+1. `--check-cfg cfg(...)` enables checking the values within list-valued conditions.
NOTE: No implicit expectation is added when using `--cfg` for both forms. Users are expected to
-pass all expected names and values using `names(...)` and `values(...)`.
+pass all expected names and values using `cfg(...)`.
-## The `names(...)` form
+## The `cfg(...)` form
-The `names(...)` form enables checking the names. This form uses a named list:
+The `cfg(...)` form enables checking the values within list-valued conditions. It has this
+basic form:
```bash
-rustc --check-cfg 'names(name1, name2, ... nameN)'
+rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
```
-where each `name` is a bare identifier (has no quotes). The order of the names is not significant.
+where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal
+string. `name` specifies the name of the condition, such as `feature` or `my_cfg`.
-If `--check-cfg names(...)` is specified at least once, then `rustc` will check all references to
-condition names. `rustc` will check every `#[cfg]` attribute, `#[cfg_attr]` attribute, `cfg` clause
-inside `#[link]` attribute and `cfg!(...)` call against the provided list of expected condition
-names. If a name is not present in this list, then `rustc` will report an `unexpected_cfgs` lint
-diagnostic. The default diagnostic level for this lint is `Warn`.
+When the `cfg(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]`
+attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]`
+and `cfg!(name = "value")` call. It will check that the `"value"` specified is present in the
+list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs`
+lint diagnostic. The default diagnostic level for this lint is `Warn`.
-If `--check-cfg names(...)` is not specified, then `rustc` will not check references to condition
-names.
+To enable checking of values, but to provide an empty set of expected values, use these forms:
-`--check-cfg names(...)` may be specified more than once. The result is that the list of valid
-condition names is merged across all options. It is legal for a condition name to be specified
-more than once; redundantly specifying a condition name has no effect.
+```bash
+rustc --check-cfg 'cfg(name1, ..., nameN)'
+rustc --check-cfg 'cfg(name1, ..., nameN, values())'
+```
-To enable checking condition names with an empty set of valid condition names, use the following
-form. The parentheses are required.
+To enable checking of name but not values (i.e. unknown expected values), use this form:
```bash
-rustc --check-cfg 'names()'
+rustc --check-cfg 'cfg(name1, ..., nameN, values(any()))'
```
-Note that `--check-cfg 'names()'` is _not_ equivalent to omitting the option entirely.
-The first form enables checking condition names, while specifying that there are no valid
-condition names (outside of the set of well-known names defined by `rustc`). Omitting the
-`--check-cfg 'names(...)'` option does not enable checking condition names.
-
-## The `values(...)` form
+The `--check-cfg cfg(...)` option can be repeated, both for the same condition name and for
+different names. If it is repeated for the same condition name, then the sets of values for that
+condition are merged together (presedence is given to `any()`).
-The `values(...)` form enables checking the values within list-valued conditions. It has this
-form:
+## Well known names and values
-```bash
-rustc --check-cfg `values(name, "value1", "value2", ... "valueN")'
-```
+`rustc` has a internal list of well known names and their corresponding values.
+Those well known names and values follows the same stability as what they refer to.
-where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal
-string. `name` specifies the name of the condition, such as `feature` or `target_os`.
+Well known values checking is always enabled as long as a `--check-cfg` argument is present.
-When the `values(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]`
-attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]`
-and `cfg!(name = "value")` call. It will check that the `"value"` specified is present in the
-list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs`
-lint diagnostic. The default diagnostic level for this lint is `Warn`.
+Well known names checking is always enable as long as a `--check-cfg` argument is present
+**unless** any `cfg(any())` argument is passed.
-To enable checking of values, but to provide an empty set of valid values, use this form:
+To disable checking of well known names, use this form:
```bash
-rustc --check-cfg `values(name)`
+rustc --check-cfg 'cfg(any())'
```
-The `--check-cfg values(...)` option can be repeated, both for the same condition name and for
-different names. If it is repeated for the same condition name, then the sets of values for that
-condition are merged together.
-
-If `values()` is specified, then `rustc` will enable the checking of well-known values defined
-by itself. Note that it's necessary to specify the `values()` form to enable the checking of
-well known values, specifying the other forms doesn't implicitly enable it.
+NOTE: If one want to enable values and names checking without having any cfg to declare, one
+can use an empty `cfg()` argument.
## Examples
Consider this command line:
```bash
-rustc --check-cfg 'names(feature)' \
- --check-cfg 'values(feature, "lion", "zebra")' \
+rustc --check-cfg 'cfg(feature, values("lion", "zebra"))' \
--cfg 'feature="lion"' -Z unstable-options \
example.rs
```
This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
-feature is enabled, while the `zebra` feature is disabled. Consider compiling this code:
+feature is enabled, while the `zebra` feature is disabled. Exhaustive checking of names and
+values are enabled by default. Consider compiling this code:
```rust
// This is expected, and tame_lion() will be compiled
@@ -119,35 +102,36 @@ fn poke_platypus() {}
// and will cause a compiler warning (by default).
#[cfg(feechure = "lion")]
fn tame_lion() {}
-```
-> Note: The `--check-cfg names(feature)` option is necessary only to enable checking the condition
-> name, as in the last example. `feature` is a well-known (always-expected) condition name, and so
-> it is not necessary to specify it in a `--check-cfg 'names(...)'` option. That option can be
-> shortened to > `--check-cfg names()` in order to enable checking well-known condition names.
+// This is UNEXPECTED, because 'windows' is a well known condition name,
+// and because 'windows' doens't take any values,
+// and will cause a compiler warning (by default).
+#[cfg(windows = "unix")]
+fn tame_windows() {}
+```
### Example: Checking condition names, but not values
```bash
# This turns on checking for condition names, but not values, such as 'feature' values.
-rustc --check-cfg 'names(is_embedded, has_feathers)' \
+rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \
--cfg has_feathers -Z unstable-options
```
```rust
-#[cfg(is_embedded)] // This is expected as "is_embedded" was provided in names()
-fn do_embedded() {}
+#[cfg(is_embedded)] // This is expected as "is_embedded" was provided in cfg()
+fn do_embedded() {} // and because names exhaustiveness was not disabled
-#[cfg(has_feathers)] // This is expected as "has_feathers" was provided in names()
-fn do_features() {}
+#[cfg(has_feathers)] // This is expected as "has_feathers" was provided in cfg()
+fn do_features() {} // and because names exhaustiveness was not disabled
-#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in names()
+#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in cfg()
// and because no value checking was enable for "has_feathers"
// no warning is emitted for the value "zapping"
fn do_zapping() {}
#[cfg(has_mumble_frotz)] // This is UNEXPECTED because names checking is enable and
- // "has_mumble_frotz" was not provided in names()
+ // "has_mumble_frotz" was not provided in cfg()
fn do_mumble_frotz() {}
```
@@ -155,25 +139,25 @@ fn do_mumble_frotz() {}
```bash
# This turns on checking for feature values, but not for condition names.
-rustc --check-cfg 'values(feature, "zapping", "lasers")' \
+rustc --check-cfg 'cfg(feature, values("zapping", "lasers"))' \
+ --check-cfg 'cfg(any())' \
--cfg 'feature="zapping"' -Z unstable-options
```
```rust
-#[cfg(is_embedded)] // This is doesn't raise a warning, because names checking was not
- // enable (ie not names())
+#[cfg(is_embedded)] // This is doesn't raise a warning, because names checking was
+ // disabled by 'cfg(any())'
fn do_embedded() {}
-#[cfg(has_feathers)] // Same as above, --check-cfg names(...) was never used so no name
+#[cfg(has_feathers)] // Same as above, 'cfg(any())' was provided so no name
// checking is performed
fn do_features() {}
-
-#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list
+#[cfg(feature = "lasers")] // This is expected, "lasers" is in the cfg(feature) list
fn shoot_lasers() {}
#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in the
- // --check-cfg values(feature) list
+ // cfg(feature) list
fn write_shakespeare() {}
```
@@ -181,26 +165,92 @@ fn write_shakespeare() {}
```bash
# This turns on checking for feature values and for condition names.
-rustc --check-cfg 'names(is_embedded, has_feathers)' \
- --check-cfg 'values(feature, "zapping", "lasers")' \
+rustc --check-cfg 'cfg(is_embedded, has_feathers)' \
+ --check-cfg 'cfg(feature, values("zapping", "lasers"))' \
--cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options
```
```rust
-#[cfg(is_embedded)] // This is expected because "is_embedded" was provided in names()
-fn do_embedded() {}
+#[cfg(is_embedded)] // This is expected because "is_embedded" was provided in cfg()
+fn do_embedded() {} // and doesn't take any value
-#[cfg(has_feathers)] // This is expected because "has_feathers" was provided in names()
-fn do_features() {}
+#[cfg(has_feathers)] // This is expected because "has_feathers" was provided in cfg()
+fn do_features() {} // and deosn't take any value
-#[cfg(has_mumble_frotz)] // This is UNEXPECTED, because has_mumble_frotz is not in the
- // --check-cfg names(...) list
+#[cfg(has_mumble_frotz)] // This is UNEXPECTED, because "has_mumble_frotz" was never provided
fn do_mumble_frotz() {}
-#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list
+#[cfg(feature = "lasers")] // This is expected, "lasers" is in the cfg(feature) list
fn shoot_lasers() {}
#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in
- // the values(feature) list
+ // the cfg(feature) list
fn write_shakespeare() {}
```
+
+## The deprecated `names(...)` form
+
+The `names(...)` form enables checking the names. This form uses a named list:
+
+```bash
+rustc --check-cfg 'names(name1, name2, ... nameN)'
+```
+
+where each `name` is a bare identifier (has no quotes). The order of the names is not significant.
+
+If `--check-cfg names(...)` is specified at least once, then `rustc` will check all references to
+condition names. `rustc` will check every `#[cfg]` attribute, `#[cfg_attr]` attribute, `cfg` clause
+inside `#[link]` attribute and `cfg!(...)` call against the provided list of expected condition
+names. If a name is not present in this list, then `rustc` will report an `unexpected_cfgs` lint
+diagnostic. The default diagnostic level for this lint is `Warn`.
+
+If `--check-cfg names(...)` is not specified, then `rustc` will not check references to condition
+names.
+
+`--check-cfg names(...)` may be specified more than once. The result is that the list of valid
+condition names is merged across all options. It is legal for a condition name to be specified
+more than once; redundantly specifying a condition name has no effect.
+
+To enable checking condition names with an empty set of valid condition names, use the following
+form. The parentheses are required.
+
+```bash
+rustc --check-cfg 'names()'
+```
+
+Note that `--check-cfg 'names()'` is _not_ equivalent to omitting the option entirely.
+The first form enables checking condition names, while specifying that there are no valid
+condition names (outside of the set of well-known names defined by `rustc`). Omitting the
+`--check-cfg 'names(...)'` option does not enable checking condition names.
+
+## The deprecated `values(...)` form
+
+The `values(...)` form enables checking the values within list-valued conditions. It has this
+form:
+
+```bash
+rustc --check-cfg `values(name, "value1", "value2", ... "valueN")'
+```
+
+where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal
+string. `name` specifies the name of the condition, such as `feature` or `target_os`.
+
+When the `values(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]`
+attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]`
+and `cfg!(name = "value")` call. It will check that the `"value"` specified is present in the
+list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs`
+lint diagnostic. The default diagnostic level for this lint is `Warn`.
+
+To enable checking of values, but to provide an empty set of valid values, use this form:
+
+```bash
+rustc --check-cfg `values(name)`
+```
+
+The `--check-cfg values(...)` option can be repeated, both for the same condition name and for
+different names. If it is repeated for the same condition name, then the sets of values for that
+condition are merged together.
+
+If `values()` is specified, then `rustc` will enable the checking of well-known values defined
+by itself. Note that it's necessary to specify the `values()` form to enable the checking of
+well known values, specifying the other forms doesn't implicitly enable it.
diff --git a/src/doc/unstable-book/src/compiler-flags/no-jump-tables.md b/src/doc/unstable-book/src/compiler-flags/no-jump-tables.md
new file mode 100644
index 000000000..f096c20f4
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/no-jump-tables.md
@@ -0,0 +1,19 @@
+# `no-jump-tables`
+
+The tracking issue for this feature is [#116592](https://github.com/rust-lang/rust/issues/116592)
+
+---
+
+This option enables the `-fno-jump-tables` flag for LLVM, which makes the
+codegen backend avoid generating jump tables when lowering switches.
+
+This option adds the LLVM `no-jump-tables=true` attribute to every function.
+
+The option can be used to help provide protection against
+jump-oriented-programming (JOP) attacks, such as with the linux kernel's [IBT].
+
+```sh
+RUSTFLAGS="-Zno-jump-tables" cargo +nightly build -Z build-std
+```
+
+[IBT]: https://www.phoronix.com/news/Linux-IBT-By-Default-Tip
diff --git a/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md b/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md
new file mode 100644
index 000000000..13349ff6b
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md
@@ -0,0 +1,24 @@
+# `remap-path-scope`
+
+The tracking issue for this feature is: [#111540](https://github.com/rust-lang/rust/issues/111540).
+
+------------------------
+
+When the `--remap-path-prefix` option is passed to rustc, source path prefixes in all output will be affected by default.
+The `--remap-path-scope` argument can be used in conjunction with `--remap-path-prefix` to determine paths in which output context should be affected.
+This flag accepts a comma-separated list of values and may be specified multiple times, in which case the scopes are aggregated together. The valid scopes are:
+
+- `macro` - apply remappings to the expansion of `std::file!()` macro. This is where paths in embedded panic messages come from
+- `diagnostics` - apply remappings to printed compiler diagnostics
+- `unsplit-debuginfo` - apply remappings to debug information only when they are written to compiled executables or libraries, but not when they are in split debuginfo files
+- `split-debuginfo` - apply remappings to debug information only when they are written to split debug information files, but not in compiled executables or libraries
+- `split-debuginfo-path` - apply remappings to the paths pointing to split debug information files. Does nothing when these files are not generated.
+- `object` - an alias for `macro,unsplit-debuginfo,split-debuginfo-path`. This ensures all paths in compiled executables or libraries are remapped, but not elsewhere.
+- `all` and `true` - an alias for all of the above, also equivalent to supplying only `--remap-path-prefix` without `--remap-path-scope`.
+
+## Example
+```sh
+# This would produce an absolute path to main.rs in build outputs of
+# "./main.rs".
+rustc --remap-path-prefix=$(PWD)=/remapped -Zremap-path-prefix=object main.rs
+```
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index 49389b28c..502853f39 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -197,22 +197,26 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
# ControlFlowIntegrity
-The LLVM Control Flow Integrity (CFI) support in the Rust compiler provides
-forward-edge control flow protection for both Rust-compiled code only and for C
-or C++ and Rust -compiled code mixed-language binaries, also known as “mixed
-binaries” (i.e., for when C or C++ and Rust -compiled code share the same
-virtual address space), by aggregating function pointers in groups identified by
-their return and parameter types.
-
-LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e., `-Clto`).
-Cross-language LLVM CFI can be enabled with `-Zsanitizer=cfi`, and requires the
-`-Zsanitizer-cfi-normalize-integers` option to be used with Clang
-`-fsanitize-cfi-icall-normalize-integers` for normalizing integer types, and
-proper (i.e., non-rustc) LTO (i.e., `-Clinker-plugin-lto`).
+The LLVM CFI support in the Rust compiler provides forward-edge control flow
+protection for both Rust-compiled code only and for C or C++ and Rust -compiled
+code mixed-language binaries, also known as “mixed binaries” (i.e., for when C
+or C++ and Rust -compiled code share the same virtual address space), by
+aggregating function pointers in groups identified by their return and parameter
+types.
+
+LLVM CFI can be enabled with `-Zsanitizer=cfi` and requires LTO (i.e.,
+`-Clinker-plugin-lto` or `-Clto`). Cross-language LLVM CFI can be enabled with
+`-Zsanitizer=cfi`, and requires the `-Zsanitizer-cfi-normalize-integers` option
+to be used with Clang `-fsanitize-cfi-icall-experimental-normalize-integers`
+option for cross-language LLVM CFI support, and proper (i.e., non-rustc) LTO
+(i.e., `-Clinker-plugin-lto`).
+
+It is recommended to rebuild the standard library with CFI enabled by using the
+Cargo build-std feature (i.e., `-Zbuild-std`) when enabling CFI.
See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details.
-## Example
+## Example 1: Redirecting control flow using an indirect branch/call to an invalid destination
```rust,ignore (making doc tests pass cross-platform is hard)
#![feature(naked_functions)]
@@ -239,7 +243,7 @@ pub extern "C" fn add_two(x: i32) {
nop
nop
nop
- lea eax, [edi+2]
+ lea eax, [rdi+2]
ret
",
options(noreturn)
@@ -258,8 +262,9 @@ fn main() {
println!("With CFI enabled, you should not see the next answer");
let f: fn(i32) -> i32 = unsafe {
- // Offsets 0-8 make it land in the landing pad/nop block, and offsets 1-8 are
- // invalid branch/call destinations (i.e., within the body of the function).
+ // Offset 0 is a valid branch/call destination (i.e., the function entry
+ // point), but offsets 1-8 within the landing pad/nop block are invalid
+ // branch/call destinations (i.e., within the body of the function).
mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5))
};
let next_answer = do_twice(f, 5);
@@ -267,38 +272,40 @@ fn main() {
println!("The next answer is: {}", next_answer);
}
```
-Fig. 1. Modified example from the [Advanced Functions and
-Closures][rust-book-ch19-05] chapter of the [The Rust Programming
-Language][rust-book] book.
+Fig. 1. Redirecting control flow using an indirect branch/call to an invalid
+destination (i.e., within the body of the function).
```shell
$ cargo run --release
Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
- Finished release [optimized] target(s) in 0.76s
+ Finished release [optimized] target(s) in 0.42s
Running `target/release/rust-cfi-1`
The answer is: 12
With CFI enabled, you should not see the next answer
The next answer is: 14
$
```
-Fig. 2. Build and execution of the modified example with LLVM CFI disabled.
+Fig. 2. Build and execution of Fig. 1 with LLVM CFI disabled.
```shell
-$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
+$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
+ ...
Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
- Finished release [optimized] target(s) in 3.39s
- Running `target/release/rust-cfi-1`
+ Finished release [optimized] target(s) in 1m 08s
+ Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-1`
The answer is: 12
With CFI enabled, you should not see the next answer
Illegal instruction
$
```
-Fig. 3. Build and execution of the modified example with LLVM CFI enabled.
+Fig. 3. Build and execution of Fig. 1 with LLVM CFI enabled.
When LLVM CFI is enabled, if there are any attempts to change/hijack control
flow using an indirect branch/call to an invalid destination, the execution is
terminated (see Fig. 3).
+## Example 2: Redirecting control flow using an indirect branch/call to a function with a different number of parameters
+
```rust
use std::mem;
@@ -327,39 +334,42 @@ fn main() {
println!("The next answer is: {}", next_answer);
}
```
-Fig. 4. Another modified example from the [Advanced Functions and
-Closures][rust-book-ch19-05] chapter of the [The Rust Programming
-Language][rust-book] book.
+Fig. 4. Redirecting control flow using an indirect branch/call to a function
+with a different number of parameters than arguments intended/passed in the
+call/branch site.
```shell
$ cargo run --release
Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
- Finished release [optimized] target(s) in 0.76s
+ Finished release [optimized] target(s) in 0.43s
Running `target/release/rust-cfi-2`
The answer is: 12
With CFI enabled, you should not see the next answer
The next answer is: 14
$
```
-Fig. 5. Build and execution of the modified example with LLVM CFI disabled.
+Fig. 5. Build and execution of Fig. 4 with LLVM CFI disabled.
```shell
-$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release
+$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
+ ...
Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
- Finished release [optimized] target(s) in 3.38s
- Running `target/release/rust-cfi-2`
+ Finished release [optimized] target(s) in 1m 08s
+ Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-2`
The answer is: 12
With CFI enabled, you should not see the next answer
Illegal instruction
$
```
-Fig. 6. Build and execution of the modified example with LLVM CFI enabled.
+Fig. 6. Build and execution of Fig. 4 with LLVM CFI enabled.
When LLVM CFI is enabled, if there are any attempts to change/hijack control
flow using an indirect branch/call to a function with different number of
parameters than arguments intended/passed in the call/branch site, the
execution is also terminated (see Fig. 6).
+## Example 3: Redirecting control flow using an indirect branch/call to a function with different return and parameter types
+
```rust
use std::mem;
@@ -388,42 +398,46 @@ fn main() {
println!("The next answer is: {}", next_answer);
}
```
-Fig. 7. Another modified example from the [Advanced Functions and
-Closures][rust-book-ch19-05] chapter of the [The Rust Programming
-Language][rust-book] book.
+Fig. 7. Redirecting control flow using an indirect branch/call to a function
+with different return and parameter types than the return type expected and
+arguments intended/passed at the call/branch site.
```shell
$ cargo run --release
Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
- Finished release [optimized] target(s) in 0.74s
+ Finished release [optimized] target(s) in 0.44s
Running `target/release/rust-cfi-3`
The answer is: 12
With CFI enabled, you should not see the next answer
The next answer is: 14
$
```
-Fig. 8. Build and execution of the modified example with LLVM CFI disabled.
+Fig. 8. Build and execution of Fig. 7 with LLVM CFI disabled.
```shell
-$ RUSTFLAGS="-Cembed-bitcode=yes -Clto -Zsanitizer=cfi" cargo run --release
+$ RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi" cargo run -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
+ ...
Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
- Finished release [optimized] target(s) in 3.40s
- Running `target/release/rust-cfi-3`
+ Finished release [optimized] target(s) in 1m 07s
+ Running `target/x86_64-unknown-linux-gnu/release/rust-cfi-3`
The answer is: 12
With CFI enabled, you should not see the next answer
Illegal instruction
$
```
-Fig. 9. Build and execution of the modified example with LLVM CFI enabled.
+Fig. 9. Build and execution of Fig. 7 with LLVM CFI enabled.
When LLVM CFI is enabled, if there are any attempts to change/hijack control
flow using an indirect branch/call to a function with different return and
parameter types than the return type expected and arguments intended/passed in
the call/branch site, the execution is also terminated (see Fig. 9).
+## Example 4: Redirecting control flow using an indirect branch/call to a function with different return and parameter types across the FFI boundary
+
```ignore (cannot-test-this-because-uses-custom-build)
int
-do_twice(int (*fn)(int), int arg) {
+do_twice(int (*fn)(int), int arg)
+{
return fn(arg) + fn(arg);
}
```
@@ -459,54 +473,49 @@ fn main() {
println!("The next answer is: {}", next_answer);
}
```
-Fig. 11. Another modified example from the [Advanced Functions and
-Closures][rust-book-ch19-05] chapter of the [The Rust Programming
-Language][rust-book] book.
+Fig. 11. Redirecting control flow using an indirect branch/call to a function
+with different return and parameter types than the return type expected and
+arguments intended/passed in the call/branch site, across the FFI boundary.
```shell
$ make
-mkdir -p target/debug
-clang -I. -Isrc -Wall -flto -fvisibility=hidden -c -emit-llvm src/foo.c -o target/debug/libfoo.bc
-llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc
-RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build
- Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1)
- Finished dev [unoptimized + debuginfo] target(s) in 0.45s
-$ ./target/debug/main
+mkdir -p target/release
+clang -I. -Isrc -Wall -c src/foo.c -o target/release/libfoo.o
+llvm-ar rcs target/release/libfoo.a target/release/libfoo.o
+RUSTFLAGS="-L./target/release -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build --release
+ Compiling rust-cfi-4 v0.1.0 (/home/rcvalle/rust-cfi-4)
+ Finished release [optimized] target(s) in 0.49s
+$ ./target/release/rust-cfi-4
The answer is: 12
With CFI enabled, you should not see the next answer
The next answer is: 14
$
```
-Fig. 12. Build and execution of the modified example with LLVM CFI disabled.
+Fig. 12. Build and execution of Figs. 10–11 with LLVM CFI disabled.
```shell
$ make
-mkdir -p target/debug
-clang -I. -Isrc -Wall -flto -fvisibility=hidden -fsanitize=cfi -fsanitize-cfi-icall-normalize-integers -c -emit-llvm src/foo.c -o target/debug/libfoo.bc
-llvm-ar rcs target/debug/libfoo.a target/debug/libfoo.bc
-RUSTFLAGS="-L./target/debug -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build
- Compiling main v0.1.0 (/home/rcvalle/rust-cross-cfi-1)
- Finished dev [unoptimized + debuginfo] target(s) in 0.45s
-$ ./target/debug/main
+mkdir -p target/release
+clang -I. -Isrc -Wall -flto -fsanitize=cfi -fsanitize-cfi-icall-experimental-normalize-integers -fvisibility=hidden -c -emit-llvm src/foo.c -o target/release/libfoo.bc
+llvm-ar rcs target/release/libfoo.a target/release/libfoo.bc
+RUSTFLAGS="-L./target/release -Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers" cargo build -Zbuild-std -Zbuild-std-features --release --target x86_64-unknown-linux-gnu
+ ...
+ Compiling rust-cfi-4 v0.1.0 (/home/rcvalle/rust-cfi-4)
+ Finished release [optimized] target(s) in 1m 06s
+$ ./target/x86_64-unknown-linux-gnu/release/rust-cfi-4
The answer is: 12
With CFI enabled, you should not see the next answer
Illegal instruction
$
```
-Fig. 13. Build and execution of the modified example with LLVM CFI enabled.
-
-When LLVM CFI is enabled, if there are any attempts to change/hijack control
-flow using an indirect branch/call to a function with different return and
-parameter types than the return type expected and arguments intended/passed in
-the call/branch site, even across the FFI boundary and for extern "C" function
-types indirectly called (i.e., callbacks/function pointers) across the FFI
-boundary, in C or C++ and Rust -compiled code mixed-language binaries, also
-known as “mixed binaries” (i.e., for when C or C++ and Rust -compiled code share
-the same virtual address space), the execution is also terminated (see Fig. 13).
-
-
-[rust-book-ch19-05]: https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html
-[rust-book]: https://doc.rust-lang.org/book/title-page.html
+Fig. 13. Build and execution of FIgs. 10–11 with LLVM CFI enabled.
+
+When LLVM CFI is enabled, if there are any attempts to redirect control flow
+using an indirect branch/call to a function with different return and parameter
+types than the return type expected and arguments intended/passed in the
+call/branch site, even across the FFI boundary and for extern "C" function types
+indirectly called (i.e., callbacks/function pointers) across the FFI boundary,
+the execution is also terminated (see Fig. 13).
# HWAddressSanitizer
diff --git a/src/doc/unstable-book/src/language-features/closure-track-caller.md b/src/doc/unstable-book/src/language-features/closure-track-caller.md
index c948810d3..997452231 100644
--- a/src/doc/unstable-book/src/language-features/closure-track-caller.md
+++ b/src/doc/unstable-book/src/language-features/closure-track-caller.md
@@ -6,7 +6,7 @@ The tracking issue for this feature is: [#87417]
------------------------
-Allows using the `#[track_caller]` attribute on closures and generators.
-Calls made to the closure or generator will have caller information
+Allows using the `#[track_caller]` attribute on closures and coroutines.
+Calls made to the closure or coroutine will have caller information
available through `std::panic::Location::caller()`, just like using
`#[track_caller]` on a function.
diff --git a/src/doc/unstable-book/src/language-features/coroutines.md b/src/doc/unstable-book/src/language-features/coroutines.md
new file mode 100644
index 000000000..f8e5a22fb
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/coroutines.md
@@ -0,0 +1,246 @@
+# `coroutines`
+
+The tracking issue for this feature is: [#43122]
+
+[#43122]: https://github.com/rust-lang/rust/issues/43122
+
+------------------------
+
+The `coroutines` feature gate in Rust allows you to define coroutine or
+coroutine literals. A coroutine is a "resumable function" that syntactically
+resembles a closure but compiles to much different semantics in the compiler
+itself. The primary feature of a coroutine is that it can be suspended during
+execution to be resumed at a later date. Coroutines use the `yield` keyword to
+"return", and then the caller can `resume` a coroutine to resume execution just
+after the `yield` keyword.
+
+Coroutines are an extra-unstable feature in the compiler right now. Added in
+[RFC 2033] they're mostly intended right now as a information/constraint
+gathering phase. The intent is that experimentation can happen on the nightly
+compiler before actual stabilization. A further RFC will be required to
+stabilize coroutines and will likely contain at least a few small
+tweaks to the overall design.
+
+[RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033
+
+A syntactical example of a coroutine is:
+
+```rust
+#![feature(coroutines, coroutine_trait)]
+
+use std::ops::{Coroutine, CoroutineState};
+use std::pin::Pin;
+
+fn main() {
+ let mut coroutine = || {
+ yield 1;
+ return "foo"
+ };
+
+ match Pin::new(&mut coroutine).resume(()) {
+ CoroutineState::Yielded(1) => {}
+ _ => panic!("unexpected value from resume"),
+ }
+ match Pin::new(&mut coroutine).resume(()) {
+ CoroutineState::Complete("foo") => {}
+ _ => panic!("unexpected value from resume"),
+ }
+}
+```
+
+Coroutines are closure-like literals which can contain a `yield` statement. The
+`yield` statement takes an optional expression of a value to yield out of the
+coroutine. All coroutine literals implement the `Coroutine` trait in the
+`std::ops` module. The `Coroutine` trait has one main method, `resume`, which
+resumes execution of the coroutine at the previous suspension point.
+
+An example of the control flow of coroutines is that the following example
+prints all numbers in order:
+
+```rust
+#![feature(coroutines, coroutine_trait)]
+
+use std::ops::Coroutine;
+use std::pin::Pin;
+
+fn main() {
+ let mut coroutine = || {
+ println!("2");
+ yield;
+ println!("4");
+ };
+
+ println!("1");
+ Pin::new(&mut coroutine).resume(());
+ println!("3");
+ Pin::new(&mut coroutine).resume(());
+ println!("5");
+}
+```
+
+At this time the main intended use case of coroutines is an implementation
+primitive for async/await syntax, but coroutines will likely be extended to
+ergonomic implementations of iterators and other primitives in the future.
+Feedback on the design and usage is always appreciated!
+
+### The `Coroutine` trait
+
+The `Coroutine` trait in `std::ops` currently looks like:
+
+```rust
+# #![feature(arbitrary_self_types, coroutine_trait)]
+# use std::ops::CoroutineState;
+# use std::pin::Pin;
+
+pub trait Coroutine<R = ()> {
+ type Yield;
+ type Return;
+ fn resume(self: Pin<&mut Self>, resume: R) -> CoroutineState<Self::Yield, Self::Return>;
+}
+```
+
+The `Coroutine::Yield` type is the type of values that can be yielded with the
+`yield` statement. The `Coroutine::Return` type is the returned type of the
+coroutine. This is typically the last expression in a coroutine's definition or
+any value passed to `return` in a coroutine. The `resume` function is the entry
+point for executing the `Coroutine` itself.
+
+The return value of `resume`, `CoroutineState`, looks like:
+
+```rust
+pub enum CoroutineState<Y, R> {
+ Yielded(Y),
+ Complete(R),
+}
+```
+
+The `Yielded` variant indicates that the coroutine can later be resumed. This
+corresponds to a `yield` point in a coroutine. The `Complete` variant indicates
+that the coroutine is complete and cannot be resumed again. Calling `resume`
+after a coroutine has returned `Complete` will likely result in a panic of the
+program.
+
+### Closure-like semantics
+
+The closure-like syntax for coroutines alludes to the fact that they also have
+closure-like semantics. Namely:
+
+* When created, a coroutine executes no code. A closure literal does not
+ actually execute any of the closure's code on construction, and similarly a
+ coroutine literal does not execute any code inside the coroutine when
+ constructed.
+
+* Coroutines can capture outer variables by reference or by move, and this can
+ be tweaked with the `move` keyword at the beginning of the closure. Like
+ closures all coroutines will have an implicit environment which is inferred by
+ the compiler. Outer variables can be moved into a coroutine for use as the
+ coroutine progresses.
+
+* Coroutine literals produce a value with a unique type which implements the
+ `std::ops::Coroutine` trait. This allows actual execution of the coroutine
+ through the `Coroutine::resume` method as well as also naming it in return
+ types and such.
+
+* Traits like `Send` and `Sync` are automatically implemented for a `Coroutine`
+ depending on the captured variables of the environment. Unlike closures,
+ coroutines also depend on variables live across suspension points. This means
+ that although the ambient environment may be `Send` or `Sync`, the coroutine
+ itself may not be due to internal variables live across `yield` points being
+ not-`Send` or not-`Sync`. Note that coroutines do
+ not implement traits like `Copy` or `Clone` automatically.
+
+* Whenever a coroutine is dropped it will drop all captured environment
+ variables.
+
+### Coroutines as state machines
+
+In the compiler, coroutines are currently compiled as state machines. Each
+`yield` expression will correspond to a different state that stores all live
+variables over that suspension point. Resumption of a coroutine will dispatch on
+the current state and then execute internally until a `yield` is reached, at
+which point all state is saved off in the coroutine and a value is returned.
+
+Let's take a look at an example to see what's going on here:
+
+```rust
+#![feature(coroutines, coroutine_trait)]
+
+use std::ops::Coroutine;
+use std::pin::Pin;
+
+fn main() {
+ let ret = "foo";
+ let mut coroutine = move || {
+ yield 1;
+ return ret
+ };
+
+ Pin::new(&mut coroutine).resume(());
+ Pin::new(&mut coroutine).resume(());
+}
+```
+
+This coroutine literal will compile down to something similar to:
+
+```rust
+#![feature(arbitrary_self_types, coroutines, coroutine_trait)]
+
+use std::ops::{Coroutine, CoroutineState};
+use std::pin::Pin;
+
+fn main() {
+ let ret = "foo";
+ let mut coroutine = {
+ enum __Coroutine {
+ Start(&'static str),
+ Yield1(&'static str),
+ Done,
+ }
+
+ impl Coroutine for __Coroutine {
+ type Yield = i32;
+ type Return = &'static str;
+
+ fn resume(mut self: Pin<&mut Self>, resume: ()) -> CoroutineState<i32, &'static str> {
+ use std::mem;
+ match mem::replace(&mut *self, __Coroutine::Done) {
+ __Coroutine::Start(s) => {
+ *self = __Coroutine::Yield1(s);
+ CoroutineState::Yielded(1)
+ }
+
+ __Coroutine::Yield1(s) => {
+ *self = __Coroutine::Done;
+ CoroutineState::Complete(s)
+ }
+
+ __Coroutine::Done => {
+ panic!("coroutine resumed after completion")
+ }
+ }
+ }
+ }
+
+ __Coroutine::Start(ret)
+ };
+
+ Pin::new(&mut coroutine).resume(());
+ Pin::new(&mut coroutine).resume(());
+}
+```
+
+Notably here we can see that the compiler is generating a fresh type,
+`__Coroutine` in this case. This type has a number of states (represented here
+as an `enum`) corresponding to each of the conceptual states of the coroutine.
+At the beginning we're closing over our outer variable `foo` and then that
+variable is also live over the `yield` point, so it's stored in both states.
+
+When the coroutine starts it'll immediately yield 1, but it saves off its state
+just before it does so indicating that it has reached the yield point. Upon
+resuming again we'll execute the `return ret` which returns the `Complete`
+state.
+
+Here we can also note that the `Done` state, if resumed, panics immediately as
+it's invalid to resume a completed coroutine. It's also worth noting that this
+is just a rough desugaring, not a normative specification for what the compiler
+does.
diff --git a/src/doc/unstable-book/src/language-features/diagnostic-namespace.md b/src/doc/unstable-book/src/language-features/diagnostic-namespace.md
new file mode 100644
index 000000000..7c46811a2
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/diagnostic-namespace.md
@@ -0,0 +1,84 @@
+# `diagnostic_namespace`
+
+The tracking issue for this feature is: [#111996]
+
+[#111996]: https://github.com/rust-lang/rust/issues/111996
+
+------------------------
+
+The `diagnostic_namespace` feature permits customization of compilation errors.
+
+## diagnostic::on_unimplemented
+
+With [#114452] support for `diagnostic::on_unimplemented` was added.
+
+When used on a trait declaration, the following options are available:
+
+* `message` to customize the primary error message
+* `note` to add a customized note message to an error message
+* `label` to customize the label part of the error message
+
+The attribute will hint to the compiler to use these in error messages:
+```rust
+// some library
+#![feature(diagnostic_namespace)]
+
+#[diagnostic::on_unimplemented(
+ message = "cannot insert element",
+ label = "cannot be put into a table",
+ note = "see <link> for more information about the Table api"
+)]
+pub trait Element {
+ // ...
+}
+```
+
+```rust,compile_fail,E0277
+# #![feature(diagnostic_namespace)]
+#
+# #[diagnostic::on_unimplemented(
+# message = "cannot insert element",
+# label = "cannot be put into a table",
+# note = "see <link> for more information about the Table api"
+# )]
+# pub trait Element {
+# // ...
+# }
+# struct Table;
+# impl Table {
+# fn insert<T: Element>(&self, element: T) {
+# // ..
+# }
+# }
+# fn main() {
+# let table = Table;
+# let element = ();
+// user code
+table.insert(element);
+# }
+```
+
+```text
+error[E0277]: cannot insert element
+ --> src/main.rs:24:18
+ |
+24 | table.insert(element);
+ | ------ ^^^^^^^ cannot be put into a table
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Element` is not implemented for `<type>`
+ = note: see <link> for more information about the Table api
+note: required by a bound in `Table::insert`
+ --> src/main.rs:15:18
+ |
+15 | fn insert<T: Element>(&self, element: T) {
+ | ^^^^^^^ required by this bound in `Table::insert`
+
+For more information about this error, try `rustc --explain E0277`.
+```
+
+See [RFC 3368] for more information.
+
+[#114452]: https://github.com/rust-lang/rust/pull/114452
+[RFC 3368]: https://github.com/rust-lang/rfcs/blob/master/text/3368-diagnostic-attribute-namespace.md
diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md
deleted file mode 100644
index 7b865c9c6..000000000
--- a/src/doc/unstable-book/src/language-features/generators.md
+++ /dev/null
@@ -1,246 +0,0 @@
-# `generators`
-
-The tracking issue for this feature is: [#43122]
-
-[#43122]: https://github.com/rust-lang/rust/issues/43122
-
-------------------------
-
-The `generators` feature gate in Rust allows you to define generator or
-coroutine literals. A generator is a "resumable function" that syntactically
-resembles a closure but compiles to much different semantics in the compiler
-itself. The primary feature of a generator is that it can be suspended during
-execution to be resumed at a later date. Generators use the `yield` keyword to
-"return", and then the caller can `resume` a generator to resume execution just
-after the `yield` keyword.
-
-Generators are an extra-unstable feature in the compiler right now. Added in
-[RFC 2033] they're mostly intended right now as a information/constraint
-gathering phase. The intent is that experimentation can happen on the nightly
-compiler before actual stabilization. A further RFC will be required to
-stabilize generators/coroutines and will likely contain at least a few small
-tweaks to the overall design.
-
-[RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033
-
-A syntactical example of a generator is:
-
-```rust
-#![feature(generators, generator_trait)]
-
-use std::ops::{Generator, GeneratorState};
-use std::pin::Pin;
-
-fn main() {
- let mut generator = || {
- yield 1;
- return "foo"
- };
-
- match Pin::new(&mut generator).resume(()) {
- GeneratorState::Yielded(1) => {}
- _ => panic!("unexpected value from resume"),
- }
- match Pin::new(&mut generator).resume(()) {
- GeneratorState::Complete("foo") => {}
- _ => panic!("unexpected value from resume"),
- }
-}
-```
-
-Generators are closure-like literals which can contain a `yield` statement. The
-`yield` statement takes an optional expression of a value to yield out of the
-generator. All generator literals implement the `Generator` trait in the
-`std::ops` module. The `Generator` trait has one main method, `resume`, which
-resumes execution of the generator at the previous suspension point.
-
-An example of the control flow of generators is that the following example
-prints all numbers in order:
-
-```rust
-#![feature(generators, generator_trait)]
-
-use std::ops::Generator;
-use std::pin::Pin;
-
-fn main() {
- let mut generator = || {
- println!("2");
- yield;
- println!("4");
- };
-
- println!("1");
- Pin::new(&mut generator).resume(());
- println!("3");
- Pin::new(&mut generator).resume(());
- println!("5");
-}
-```
-
-At this time the main intended use case of generators is an implementation
-primitive for async/await syntax, but generators will likely be extended to
-ergonomic implementations of iterators and other primitives in the future.
-Feedback on the design and usage is always appreciated!
-
-### The `Generator` trait
-
-The `Generator` trait in `std::ops` currently looks like:
-
-```rust
-# #![feature(arbitrary_self_types, generator_trait)]
-# use std::ops::GeneratorState;
-# use std::pin::Pin;
-
-pub trait Generator<R = ()> {
- type Yield;
- type Return;
- fn resume(self: Pin<&mut Self>, resume: R) -> GeneratorState<Self::Yield, Self::Return>;
-}
-```
-
-The `Generator::Yield` type is the type of values that can be yielded with the
-`yield` statement. The `Generator::Return` type is the returned type of the
-generator. This is typically the last expression in a generator's definition or
-any value passed to `return` in a generator. The `resume` function is the entry
-point for executing the `Generator` itself.
-
-The return value of `resume`, `GeneratorState`, looks like:
-
-```rust
-pub enum GeneratorState<Y, R> {
- Yielded(Y),
- Complete(R),
-}
-```
-
-The `Yielded` variant indicates that the generator can later be resumed. This
-corresponds to a `yield` point in a generator. The `Complete` variant indicates
-that the generator is complete and cannot be resumed again. Calling `resume`
-after a generator has returned `Complete` will likely result in a panic of the
-program.
-
-### Closure-like semantics
-
-The closure-like syntax for generators alludes to the fact that they also have
-closure-like semantics. Namely:
-
-* When created, a generator executes no code. A closure literal does not
- actually execute any of the closure's code on construction, and similarly a
- generator literal does not execute any code inside the generator when
- constructed.
-
-* Generators can capture outer variables by reference or by move, and this can
- be tweaked with the `move` keyword at the beginning of the closure. Like
- closures all generators will have an implicit environment which is inferred by
- the compiler. Outer variables can be moved into a generator for use as the
- generator progresses.
-
-* Generator literals produce a value with a unique type which implements the
- `std::ops::Generator` trait. This allows actual execution of the generator
- through the `Generator::resume` method as well as also naming it in return
- types and such.
-
-* Traits like `Send` and `Sync` are automatically implemented for a `Generator`
- depending on the captured variables of the environment. Unlike closures,
- generators also depend on variables live across suspension points. This means
- that although the ambient environment may be `Send` or `Sync`, the generator
- itself may not be due to internal variables live across `yield` points being
- not-`Send` or not-`Sync`. Note that generators do
- not implement traits like `Copy` or `Clone` automatically.
-
-* Whenever a generator is dropped it will drop all captured environment
- variables.
-
-### Generators as state machines
-
-In the compiler, generators are currently compiled as state machines. Each
-`yield` expression will correspond to a different state that stores all live
-variables over that suspension point. Resumption of a generator will dispatch on
-the current state and then execute internally until a `yield` is reached, at
-which point all state is saved off in the generator and a value is returned.
-
-Let's take a look at an example to see what's going on here:
-
-```rust
-#![feature(generators, generator_trait)]
-
-use std::ops::Generator;
-use std::pin::Pin;
-
-fn main() {
- let ret = "foo";
- let mut generator = move || {
- yield 1;
- return ret
- };
-
- Pin::new(&mut generator).resume(());
- Pin::new(&mut generator).resume(());
-}
-```
-
-This generator literal will compile down to something similar to:
-
-```rust
-#![feature(arbitrary_self_types, generators, generator_trait)]
-
-use std::ops::{Generator, GeneratorState};
-use std::pin::Pin;
-
-fn main() {
- let ret = "foo";
- let mut generator = {
- enum __Generator {
- Start(&'static str),
- Yield1(&'static str),
- Done,
- }
-
- impl Generator for __Generator {
- type Yield = i32;
- type Return = &'static str;
-
- fn resume(mut self: Pin<&mut Self>, resume: ()) -> GeneratorState<i32, &'static str> {
- use std::mem;
- match mem::replace(&mut *self, __Generator::Done) {
- __Generator::Start(s) => {
- *self = __Generator::Yield1(s);
- GeneratorState::Yielded(1)
- }
-
- __Generator::Yield1(s) => {
- *self = __Generator::Done;
- GeneratorState::Complete(s)
- }
-
- __Generator::Done => {
- panic!("generator resumed after completion")
- }
- }
- }
- }
-
- __Generator::Start(ret)
- };
-
- Pin::new(&mut generator).resume(());
- Pin::new(&mut generator).resume(());
-}
-```
-
-Notably here we can see that the compiler is generating a fresh type,
-`__Generator` in this case. This type has a number of states (represented here
-as an `enum`) corresponding to each of the conceptual states of the generator.
-At the beginning we're closing over our outer variable `foo` and then that
-variable is also live over the `yield` point, so it's stored in both states.
-
-When the generator starts it'll immediately yield 1, but it saves off its state
-just before it does so indicating that it has reached the yield point. Upon
-resuming again we'll execute the `return ret` which returns the `Complete`
-state.
-
-Here we can also note that the `Done` state, if resumed, panics immediately as
-it's invalid to resume a completed generator. It's also worth noting that this
-is just a rough desugaring, not a normative specification for what the compiler
-does.
diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md
deleted file mode 100644
index 189cc910a..000000000
--- a/src/doc/unstable-book/src/language-features/plugin.md
+++ /dev/null
@@ -1,114 +0,0 @@
-# `plugin`
-
-The tracking issue for this feature is: [#29597]
-
-[#29597]: https://github.com/rust-lang/rust/issues/29597
-
-
-This feature is part of "compiler plugins." It will often be used with the
-`rustc_private` feature.
-
-------------------------
-
-`rustc` can load compiler plugins, which are user-provided libraries that
-extend the compiler's behavior with new lint checks, etc.
-
-A plugin is a dynamic library crate with a designated *registrar* function that
-registers extensions with `rustc`. Other crates can load these extensions using
-the crate attribute `#![plugin(...)]`. See the
-`rustc_driver::plugin` documentation for more about the
-mechanics of defining and loading a plugin.
-
-In the vast majority of cases, a plugin should *only* be used through
-`#![plugin]` and not through an `extern crate` item. Linking a plugin would
-pull in all of librustc_ast and librustc as dependencies of your crate. This is
-generally unwanted unless you are building another plugin.
-
-The usual practice is to put compiler plugins in their own crate, separate from
-any `macro_rules!` macros or ordinary Rust code meant to be used by consumers
-of a library.
-
-# Lint plugins
-
-Plugins can extend [Rust's lint
-infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with
-additional checks for code style, safety, etc. Now let's write a plugin
-[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui-fulldeps/auxiliary/lint-plugin-test.rs)
-that warns about any item named `lintme`.
-
-```rust,ignore (requires-stage-2)
-#![feature(rustc_private)]
-
-extern crate rustc_ast;
-
-// Load rustc as a plugin to get macros
-extern crate rustc_driver;
-extern crate rustc_lint;
-#[macro_use]
-extern crate rustc_session;
-
-use rustc_ast::ast;
-use rustc_driver::plugin::Registry;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
-
-declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
-
-declare_lint_pass!(Pass => [TEST_LINT]);
-
-impl EarlyLintPass for Pass {
- fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
- if it.ident.name.as_str() == "lintme" {
- cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span));
- }
- }
-}
-
-#[no_mangle]
-fn __rustc_plugin_registrar(reg: &mut Registry) {
- reg.lint_store.register_lints(&[&TEST_LINT]);
- reg.lint_store.register_early_pass(|| Box::new(Pass));
-}
-```
-
-Then code like
-
-```rust,ignore (requires-plugin)
-#![feature(plugin)]
-#![plugin(lint_plugin_test)]
-
-fn lintme() { }
-```
-
-will produce a compiler warning:
-
-```txt
-foo.rs:4:1: 4:16 warning: item is named 'lintme', #[warn(test_lint)] on by default
-foo.rs:4 fn lintme() { }
- ^~~~~~~~~~~~~~~
-```
-
-The components of a lint plugin are:
-
-* one or more `declare_lint!` invocations, which define static `Lint` structs;
-
-* a struct holding any state needed by the lint pass (here, none);
-
-* a `LintPass`
- implementation defining how to check each syntax element. A single
- `LintPass` may call `span_lint` for several different `Lint`s, but should
- register them all through the `get_lints` method.
-
-Lint passes are syntax traversals, but they run at a late stage of compilation
-where type information is available. `rustc`'s [built-in
-lints](https://github.com/rust-lang/rust/blob/master/compiler/rustc_lint_defs/src/builtin.rs)
-mostly use the same infrastructure as lint plugins, and provide examples of how
-to access type information.
-
-Lints defined by plugins are controlled by the usual [attributes and compiler
-flags](../../reference/attributes/diagnostics.md#lint-check-attributes), e.g.
-`#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the
-first argument to `declare_lint!`, with appropriate case and punctuation
-conversion.
-
-You can run `rustc -W help foo.rs` to see a list of lints known to `rustc`,
-including those provided by plugins loaded by `foo.rs`.
diff --git a/src/doc/unstable-book/src/language-features/string-deref-patterns.md b/src/doc/unstable-book/src/language-features/string-deref-patterns.md
new file mode 100644
index 000000000..372383075
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/string-deref-patterns.md
@@ -0,0 +1,45 @@
+# `string_deref_patterns`
+
+The tracking issue for this feature is: [#87121]
+
+[#87121]: https://github.com/rust-lang/rust/issues/87121
+
+------------------------
+
+This feature permits pattern matching `String` to `&str` through [its `Deref` implementation].
+
+```rust
+#![feature(string_deref_patterns)]
+
+pub enum Value {
+ String(String),
+ Number(u32),
+}
+
+pub fn is_it_the_answer(value: Value) -> bool {
+ match value {
+ Value::String("42") => true,
+ Value::Number(42) => true,
+ _ => false,
+ }
+}
+```
+
+Without this feature other constructs such as match guards have to be used.
+
+```rust
+# pub enum Value {
+# String(String),
+# Number(u32),
+# }
+#
+pub fn is_it_the_answer(value: Value) -> bool {
+ match value {
+ Value::String(s) if s == "42" => true,
+ Value::Number(42) => true,
+ _ => false,
+ }
+}
+```
+
+[its `Deref` implementation]: https://doc.rust-lang.org/std/string/struct.String.html#impl-Deref-for-String
diff --git a/src/doc/unstable-book/src/the-unstable-book.md b/src/doc/unstable-book/src/the-unstable-book.md
index 9090b134d..0f4fb4056 100644
--- a/src/doc/unstable-book/src/the-unstable-book.md
+++ b/src/doc/unstable-book/src/the-unstable-book.md
@@ -5,31 +5,31 @@ each one organized by a "feature flag." That is, when using an unstable
feature of Rust, you must use a flag, like this:
```rust
-#![feature(generators, generator_trait)]
+#![feature(coroutines, coroutine_trait)]
-use std::ops::{Generator, GeneratorState};
+use std::ops::{Coroutine, CoroutineState};
use std::pin::Pin;
fn main() {
- let mut generator = || {
+ let mut coroutine = || {
yield 1;
return "foo"
};
- match Pin::new(&mut generator).resume(()) {
- GeneratorState::Yielded(1) => {}
+ match Pin::new(&mut coroutine).resume(()) {
+ CoroutineState::Yielded(1) => {}
_ => panic!("unexpected value from resume"),
}
- match Pin::new(&mut generator).resume(()) {
- GeneratorState::Complete("foo") => {}
+ match Pin::new(&mut coroutine).resume(()) {
+ CoroutineState::Complete("foo") => {}
_ => panic!("unexpected value from resume"),
}
}
```
-The `generators` feature [has a chapter][generators] describing how to use it.
+The `coroutines` feature [has a chapter][coroutines] describing how to use it.
-[generators]: language-features/generators.md
+[coroutines]: language-features/coroutines.md
Because this documentation relates to unstable features, we make no guarantees
that what is contained here is accurate or up to date. It's developed on a