summaryrefslogtreecommitdiffstats
path: root/src/doc/unstable-book
diff options
context:
space:
mode:
Diffstat (limited to 'src/doc/unstable-book')
-rw-r--r--src/doc/unstable-book/book.toml6
-rw-r--r--src/doc/unstable-book/src/compiler-flags.md1
-rw-r--r--src/doc/unstable-book/src/compiler-flags/branch-protection.md18
-rw-r--r--src/doc/unstable-book/src/compiler-flags/cf-protection.md40
-rw-r--r--src/doc/unstable-book/src/compiler-flags/check-cfg.md206
-rw-r--r--src/doc/unstable-book/src/compiler-flags/codegen-backend.md31
-rw-r--r--src/doc/unstable-book/src/compiler-flags/control-flow-guard.md59
-rw-r--r--src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md35
-rw-r--r--src/doc/unstable-book/src/compiler-flags/dwarf-version.md9
-rw-r--r--src/doc/unstable-book/src/compiler-flags/emit-stack-sizes.md167
-rw-r--r--src/doc/unstable-book/src/compiler-flags/extern-options.md27
-rw-r--r--src/doc/unstable-book/src/compiler-flags/location-detail.md44
-rw-r--r--src/doc/unstable-book/src/compiler-flags/move-size-limit.md10
-rw-r--r--src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md9
-rw-r--r--src/doc/unstable-book/src/compiler-flags/profile.md27
-rw-r--r--src/doc/unstable-book/src/compiler-flags/profile_sample_use.md10
-rw-r--r--src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md24
-rw-r--r--src/doc/unstable-book/src/compiler-flags/report-time.md77
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md684
-rw-r--r--src/doc/unstable-book/src/compiler-flags/self-profile-events.md74
-rw-r--r--src/doc/unstable-book/src/compiler-flags/self-profile.md47
-rw-r--r--src/doc/unstable-book/src/compiler-flags/src-hash-algorithm.md11
-rw-r--r--src/doc/unstable-book/src/compiler-flags/temps-dir.md10
-rw-r--r--src/doc/unstable-book/src/compiler-flags/tls-model.md25
-rw-r--r--src/doc/unstable-book/src/compiler-flags/unsound-mir-opts.md8
-rw-r--r--src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md39
-rw-r--r--src/doc/unstable-book/src/language-features.md1
-rw-r--r--src/doc/unstable-book/src/language-features/abi-c-cmse-nonsecure-call.md88
-rw-r--r--src/doc/unstable-book/src/language-features/abi-msp430-interrupt.md42
-rw-r--r--src/doc/unstable-book/src/language-features/abi-ptx.md60
-rw-r--r--src/doc/unstable-book/src/language-features/abi-thiscall.md12
-rw-r--r--src/doc/unstable-book/src/language-features/allocator-internals.md7
-rw-r--r--src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md37
-rw-r--r--src/doc/unstable-book/src/language-features/asm-const.md11
-rw-r--r--src/doc/unstable-book/src/language-features/asm-experimental-arch.md132
-rw-r--r--src/doc/unstable-book/src/language-features/asm-sym.md13
-rw-r--r--src/doc/unstable-book/src/language-features/asm-unwind.md9
-rw-r--r--src/doc/unstable-book/src/language-features/auto-traits.md106
-rw-r--r--src/doc/unstable-book/src/language-features/box-patterns.md32
-rw-r--r--src/doc/unstable-book/src/language-features/box-syntax.md22
-rw-r--r--src/doc/unstable-book/src/language-features/c-unwind.md26
-rw-r--r--src/doc/unstable-book/src/language-features/c-variadic.md24
-rw-r--r--src/doc/unstable-book/src/language-features/cfg-sanitize.md34
-rw-r--r--src/doc/unstable-book/src/language-features/cfg-version.md35
-rw-r--r--src/doc/unstable-book/src/language-features/closure-track-caller.md12
-rw-r--r--src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md81
-rw-r--r--src/doc/unstable-book/src/language-features/compiler-builtins.md5
-rw-r--r--src/doc/unstable-book/src/language-features/const-eval-limit.md7
-rw-r--r--src/doc/unstable-book/src/language-features/custom-test-frameworks.md32
-rw-r--r--src/doc/unstable-book/src/language-features/debugger-visualizer.md27
-rw-r--r--src/doc/unstable-book/src/language-features/doc-cfg.md46
-rw-r--r--src/doc/unstable-book/src/language-features/doc-masked.md24
-rw-r--r--src/doc/unstable-book/src/language-features/doc-notable-trait.md33
-rw-r--r--src/doc/unstable-book/src/language-features/exclusive-range-pattern.md26
-rw-r--r--src/doc/unstable-book/src/language-features/ffi-const.md52
-rw-r--r--src/doc/unstable-book/src/language-features/ffi-pure.md56
-rw-r--r--src/doc/unstable-book/src/language-features/generators.md246
-rw-r--r--src/doc/unstable-book/src/language-features/half-open-range-patterns.md27
-rw-r--r--src/doc/unstable-book/src/language-features/inline-const-pat.md24
-rw-r--r--src/doc/unstable-book/src/language-features/inline-const.md32
-rw-r--r--src/doc/unstable-book/src/language-features/intra-doc-pointers.md15
-rw-r--r--src/doc/unstable-book/src/language-features/intrinsics.md29
-rw-r--r--src/doc/unstable-book/src/language-features/lang-items.md297
-rw-r--r--src/doc/unstable-book/src/language-features/link-cfg.md5
-rw-r--r--src/doc/unstable-book/src/language-features/marker-trait-attr.md35
-rw-r--r--src/doc/unstable-book/src/language-features/more-qualified-paths.md29
-rw-r--r--src/doc/unstable-book/src/language-features/native-link-modifiers-as-needed.md18
-rw-r--r--src/doc/unstable-book/src/language-features/native-link-modifiers-verbatim.md20
-rw-r--r--src/doc/unstable-book/src/language-features/negative-impls.md57
-rw-r--r--src/doc/unstable-book/src/language-features/no-coverage.md30
-rw-r--r--src/doc/unstable-book/src/language-features/no-sanitize.md29
-rw-r--r--src/doc/unstable-book/src/language-features/plugin.md116
-rw-r--r--src/doc/unstable-book/src/language-features/profiler-runtime.md5
-rw-r--r--src/doc/unstable-book/src/language-features/raw-dylib.md34
-rw-r--r--src/doc/unstable-book/src/language-features/repr128.md18
-rw-r--r--src/doc/unstable-book/src/language-features/rustc-attrs.md53
-rw-r--r--src/doc/unstable-book/src/language-features/strict-provenance.md22
-rw-r--r--src/doc/unstable-book/src/language-features/trait-alias.md34
-rw-r--r--src/doc/unstable-book/src/language-features/trait-upcasting.md27
-rw-r--r--src/doc/unstable-book/src/language-features/transparent-unions.md83
-rw-r--r--src/doc/unstable-book/src/language-features/try-blocks.md30
-rw-r--r--src/doc/unstable-book/src/language-features/type-changing-struct-update.md33
-rw-r--r--src/doc/unstable-book/src/language-features/unboxed-closures.md25
-rw-r--r--src/doc/unstable-book/src/language-features/unsized-locals.md175
-rw-r--r--src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md27
-rw-r--r--src/doc/unstable-book/src/language-features/yeet-expr.md26
-rw-r--r--src/doc/unstable-book/src/library-features.md1
-rw-r--r--src/doc/unstable-book/src/library-features/allocator-api.md15
-rw-r--r--src/doc/unstable-book/src/library-features/c-variadic.md26
-rw-r--r--src/doc/unstable-book/src/library-features/c-void-variant.md5
-rw-r--r--src/doc/unstable-book/src/library-features/char-error-internals.md5
-rw-r--r--src/doc/unstable-book/src/library-features/concat-idents.md22
-rw-r--r--src/doc/unstable-book/src/library-features/core-intrinsics.md5
-rw-r--r--src/doc/unstable-book/src/library-features/core-panic.md5
-rw-r--r--src/doc/unstable-book/src/library-features/core-private-bignum.md5
-rw-r--r--src/doc/unstable-book/src/library-features/core-private-diy-float.md5
-rw-r--r--src/doc/unstable-book/src/library-features/dec2flt.md5
-rw-r--r--src/doc/unstable-book/src/library-features/default-free-fn.md47
-rw-r--r--src/doc/unstable-book/src/library-features/derive-clone-copy.md5
-rw-r--r--src/doc/unstable-book/src/library-features/derive-eq.md5
-rw-r--r--src/doc/unstable-book/src/library-features/fd-read.md5
-rw-r--r--src/doc/unstable-book/src/library-features/fd.md5
-rw-r--r--src/doc/unstable-book/src/library-features/flt2dec.md5
-rw-r--r--src/doc/unstable-book/src/library-features/fmt-internals.md5
-rw-r--r--src/doc/unstable-book/src/library-features/fn-traits.md35
-rw-r--r--src/doc/unstable-book/src/library-features/int-error-internals.md5
-rw-r--r--src/doc/unstable-book/src/library-features/internal-output-capture.md5
-rw-r--r--src/doc/unstable-book/src/library-features/is-sorted.md11
-rw-r--r--src/doc/unstable-book/src/library-features/libstd-sys-internals.md5
-rw-r--r--src/doc/unstable-book/src/library-features/libstd-thread-internals.md5
-rw-r--r--src/doc/unstable-book/src/library-features/print-internals.md5
-rw-r--r--src/doc/unstable-book/src/library-features/profiler-runtime-lib.md5
-rw-r--r--src/doc/unstable-book/src/library-features/rt.md5
-rw-r--r--src/doc/unstable-book/src/library-features/sort-internals.md5
-rw-r--r--src/doc/unstable-book/src/library-features/str-internals.md5
-rw-r--r--src/doc/unstable-book/src/library-features/test.md158
-rw-r--r--src/doc/unstable-book/src/library-features/thread-local-internals.md5
-rw-r--r--src/doc/unstable-book/src/library-features/trace-macros.md39
-rw-r--r--src/doc/unstable-book/src/library-features/update-panic-count.md5
-rw-r--r--src/doc/unstable-book/src/library-features/windows-c.md5
-rw-r--r--src/doc/unstable-book/src/library-features/windows-handle.md5
-rw-r--r--src/doc/unstable-book/src/library-features/windows-net.md5
-rw-r--r--src/doc/unstable-book/src/library-features/windows-stdio.md5
-rw-r--r--src/doc/unstable-book/src/the-unstable-book.md22
124 files changed, 4907 insertions, 0 deletions
diff --git a/src/doc/unstable-book/book.toml b/src/doc/unstable-book/book.toml
new file mode 100644
index 000000000..0cd56d094
--- /dev/null
+++ b/src/doc/unstable-book/book.toml
@@ -0,0 +1,6 @@
+[book]
+title = "The Rust Unstable Book"
+author = "The Rust Community"
+
+[output.html]
+git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/unstable-book"
diff --git a/src/doc/unstable-book/src/compiler-flags.md b/src/doc/unstable-book/src/compiler-flags.md
new file mode 100644
index 000000000..43eadb351
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags.md
@@ -0,0 +1 @@
+# Compiler flags
diff --git a/src/doc/unstable-book/src/compiler-flags/branch-protection.md b/src/doc/unstable-book/src/compiler-flags/branch-protection.md
new file mode 100644
index 000000000..85403748e
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/branch-protection.md
@@ -0,0 +1,18 @@
+# `branch-protection`
+
+This option lets you enable branch authentication instructions on AArch64.
+This option is ignored for non-AArch64 architectures.
+It takes some combination of the following values, separated by a `,`.
+
+- `pac-ret` - Enable pointer authentication for non-leaf functions.
+- `leaf` - Enable pointer authentication for all functions, including leaf functions.
+- `b-key` - Sign return addresses with key B, instead of the default key A.
+- `bti` - Enable branch target identification.
+
+`leaf` and `b-key` are only valid if `pac-ret` was previously specified.
+For example, `-Z branch-protection=bti,pac-ret,leaf` is valid, but
+`-Z branch-protection=bti,leaf,pac-ret` is not.
+
+Rust's standard library does not ship with BTI or pointer authentication enabled by default.
+In Cargo projects the standard library can be recompiled with pointer authentication using the nightly
+[build-std](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std) feature.
diff --git a/src/doc/unstable-book/src/compiler-flags/cf-protection.md b/src/doc/unstable-book/src/compiler-flags/cf-protection.md
new file mode 100644
index 000000000..ab698c82b
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/cf-protection.md
@@ -0,0 +1,40 @@
+# `cf-protection`
+
+This option enables control-flow enforcement technology (CET) on x86; a more detailed description of
+CET is available [here]. Similar to `clang`, this flag takes one of the following values:
+
+- `none` - Disable CET completely (this is the default).
+- `branch` - Enable indirect branch tracking (`IBT`).
+- `return` - Enable shadow stack (`SHSTK`).
+- `full` - Enable both `branch` and `return`.
+
+[here]: https://www.intel.com/content/www/us/en/develop/articles/technical-look-control-flow-enforcement-technology.html
+
+This flag only applies to the LLVM backend: it sets the `cf-protection-branch` and
+`cf-protection-return` flags on LLVM modules. Note, however, that all compiled modules linked
+together must have the flags set for the compiled output to be CET-enabled. Currently, Rust's
+standard library does not ship with CET enabled by default, so you may need to rebuild all standard
+modules with a `cargo` command like:
+
+```sh
+$ RUSTFLAGS="-Z cf-protection=full" cargo +nightly build -Z build-std --target x86_64-unknown-linux-gnu
+```
+
+### Detection
+
+An ELF binary is CET-enabled if it has the `IBT` and `SHSTK` tags, e.g.:
+
+```sh
+$ readelf -a target/x86_64-unknown-linux-gnu/debug/example | grep feature:
+ Properties: x86 feature: IBT, SHSTK
+```
+
+### Troubleshooting
+
+To display modules that are not CET enabled, examine the linker errors available when `cet-report` is enabled:
+
+```sh
+$ RUSTC_LOG=rustc_codegen_ssa::back::link=info rustc-custom -v -Z cf-protection=full -C link-arg="-Wl,-z,cet-report=warning" -o example example.rs
+...
+/usr/bin/ld: /.../build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-d73f7266be14cb8b.rlib(std-d73f7266be14cb8b.std.f7443020-cgu.12.rcgu.o): warning: missing IBT and SHSTK properties
+```
diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md
new file mode 100644
index 000000000..bfa92e7d3
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md
@@ -0,0 +1,206 @@
+# `check-cfg`
+
+The tracking issue for this feature is: [#82450](https://github.com/rust-lang/rust/issues/82450).
+
+------------------------
+
+This feature allows you to enable complete or partial checking of configuration.
+
+`rustc` accepts the `--check-cfg` option, which specifies whether to check conditions and how to
+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:
+
+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.
+
+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(...)`.
+
+## The `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 `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.
+
+## Examples
+
+Consider this command line:
+
+```bash
+rustc --check-cfg 'names(feature)' \
+ --check-cfg 'values(feature, "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:
+
+```rust
+// This is expected, and tame_lion() will be compiled
+#[cfg(feature = "lion")]
+fn tame_lion(lion: Lion) {}
+
+// This is expected, and ride_zebra() will NOT be compiled.
+#[cfg(feature = "zebra")]
+fn ride_zebra(zebra: Zebra) {}
+
+// This is UNEXPECTED, and will cause a compiler warning (by default).
+#[cfg(feature = "platypus")]
+fn poke_platypus() {}
+
+// This is UNEXPECTED, because 'feechure' is not a known condition name,
+// 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.
+
+### 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)' \
+ --cfg has_feathers -Z unstable-options
+```
+
+```rust
+#[cfg(is_embedded)] // This is expected as "is_embedded" was provided in names()
+fn do_embedded() {}
+
+#[cfg(has_feathers)] // This is expected as "has_feathers" was provided in names()
+fn do_features() {}
+
+#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in names()
+ // and because no value checking was enable for "has_feathers"
+ // no warning is emited 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()
+fn do_mumble_frotz() {}
+```
+
+### Example: Checking feature values, but not condition names
+
+```bash
+# This turns on checking for feature values, but not for condition names.
+rustc --check-cfg 'values(feature, "zapping", "lasers")' \
+ --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())
+fn do_embedded() {}
+
+#[cfg(has_feathers)] // Same as above, --check-cfg names(...) was never used so no name
+ // checking is performed
+fn do_features() {}
+
+
+#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list
+fn shoot_lasers() {}
+
+#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in the
+ // --check-cfg values(feature) list
+fn write_shakespeare() {}
+```
+
+### Example: Checking both condition names and feature values
+
+```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")' \
+ --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(has_feathers)] // This is expected because "has_feathers" was provided in names()
+fn do_features() {}
+
+#[cfg(has_mumble_frotz)] // This is UNEXPECTED, because has_mumble_frotz is not in the
+ // --check-cfg names(...) list
+fn do_mumble_frotz() {}
+
+#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list
+fn shoot_lasers() {}
+
+#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in
+ // the values(feature) list
+fn write_shakespear() {}
+```
diff --git a/src/doc/unstable-book/src/compiler-flags/codegen-backend.md b/src/doc/unstable-book/src/compiler-flags/codegen-backend.md
new file mode 100644
index 000000000..3c0cd32fa
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/codegen-backend.md
@@ -0,0 +1,31 @@
+# `codegen-backend`
+
+The tracking issue for this feature is: [#77933](https://github.com/rust-lang/rust/issues/77933).
+
+------------------------
+
+This feature allows you to specify a path to a dynamic library to use as rustc's
+code generation backend at runtime.
+
+Set the `-Zcodegen-backend=<path>` compiler flag to specify the location of the
+backend. The library must be of crate type `dylib` and must contain a function
+named `__rustc_codegen_backend` with a signature of `fn() -> Box<dyn rustc_codegen_ssa::traits::CodegenBackend>`.
+
+## Example
+See also the [`hotplug_codegen_backend`](https://github.com/rust-lang/rust/tree/master/src/test/run-make-fulldeps/hotplug_codegen_backend) test
+for a full example.
+
+```rust,ignore (partial-example)
+use rustc_codegen_ssa::traits::CodegenBackend;
+
+struct MyBackend;
+
+impl CodegenBackend for MyBackend {
+ // Implement codegen methods
+}
+
+#[no_mangle]
+pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
+ Box::new(MyBackend)
+}
+```
diff --git a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md
new file mode 100644
index 000000000..08c16d95f
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md
@@ -0,0 +1,59 @@
+# `control-flow-guard`
+
+The tracking issue for this feature is: [#68793](https://github.com/rust-lang/rust/issues/68793).
+
+------------------------
+
+The rustc flag `-Z control-flow-guard` enables the Windows [Control Flow Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) (CFG) platform security feature.
+
+CFG is an exploit mitigation designed to enforce control-flow integrity for software running on supported [Windows platforms (Windows 8.1 onwards)](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard). Specifically, CFG uses runtime checks to validate the target address of every indirect call/jump before allowing the call to complete.
+
+During compilation, the compiler identifies all indirect calls/jumps and adds CFG checks. It also emits metadata containing the relative addresses of all address-taken functions. At runtime, if the binary is run on a CFG-aware operating system, the loader uses the CFG metadata to generate a bitmap of the address space and marks those addresses that contain valid targets. On each indirect call, the inserted check determines whether the target address is marked in this bitmap. If the target is not valid, the process is terminated.
+
+In terms of interoperability:
+- Code compiled with CFG enabled can be linked with libraries and object files that are not compiled with CFG. In this case, a CFG-aware linker can identify address-taken functions in the non-CFG libraries.
+- Libraries compiled with CFG can linked into non-CFG programs. In this case, the CFG runtime checks in the libraries are not used (i.e. the mitigation is completely disabled).
+
+CFG functionality is completely implemented in the LLVM backend and is supported for X86 (32-bit and 64-bit), ARM, and Aarch64 targets. The rustc flag adds the relevant LLVM module flags to enable the feature. This flag will be ignored for all non-Windows targets.
+
+
+## When to use Control Flow Guard
+
+The primary motivation for enabling CFG in Rust is to enhance security when linking against non-Rust code, especially C/C++ code. To achieve full CFG protection, all indirect calls (including any from Rust code) must have the appropriate CFG checks, as added by this flag. CFG can also improve security for Rust code that uses the `unsafe` keyword.
+
+Another motivation behind CFG is to harden programs against [return-oriented programming (ROP)](https://en.wikipedia.org/wiki/Return-oriented_programming) attacks. CFG disallows an attacker from taking advantage of the program's own instructions while redirecting control flow in unexpected ways.
+
+## Overhead of Control Flow Guard
+
+The CFG checks and metadata can potentially increase binary size and runtime overhead. The magnitude of any increase depends on the number and frequency of indirect calls. For example, enabling CFG for the Rust standard library increases binary size by approximately 0.14%. Enabling CFG in the SPEC CPU 2017 Integer Speed benchmark suite (compiled with Clang/LLVM) incurs approximate runtime overheads of between 0% and 8%, with a geometric mean of 2.9%.
+
+
+## Testing Control Flow Guard
+
+The rustc flag `-Z control-flow-guard=nochecks` instructs LLVM to emit the list of valid call targets without inserting runtime checks. This flag should only be used for testing purposes as it does not provide security enforcement.
+
+
+## Control Flow Guard in libraries
+
+It is strongly recommended to also enable CFG checks for all linked libraries, including the standard library.
+
+To enable CFG in the standard library, use the [cargo `-Z build-std` functionality][build-std] to recompile the standard library with the same configuration options as the main program.
+
+[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
+
+For example:
+```cmd
+rustup toolchain install --force nightly
+rustup component add rust-src
+SET RUSTFLAGS=-Z control-flow-guard
+cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
+```
+
+```PowerShell
+rustup toolchain install --force nightly
+rustup component add rust-src
+$Env:RUSTFLAGS = "-Z control-flow-guard"
+cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc
+```
+
+Alternatively, if you are building the standard library from source, you can set `control-flow-guard = true` in the config.toml file.
diff --git a/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md b/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md
new file mode 100644
index 000000000..ee72b6adf
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md
@@ -0,0 +1,35 @@
+# `debug-info-for-profiling`
+
+---
+
+## Introduction
+
+Automatic Feedback Directed Optimization (AFDO) is a method for using sampling
+based profiles to guide optimizations. This is contrasted with other methods of
+FDO or profile-guided optimization (PGO) which use instrumented profiling.
+
+Unlike PGO (controlled by the `rustc` flags `-Cprofile-generate` and
+`-Cprofile-use`), a binary being profiled does not perform significantly worse,
+and thus it's possible to profile binaries used in real workflows and not
+necessary to construct artificial workflows.
+
+## Use
+
+In order to use AFDO, the target platform must be Linux running on an `x86_64`
+architecture with the performance profiler `perf` available. In addition, the
+external tool `create_llvm_prof` from [this repository] must be used.
+
+Given a Rust file `main.rs`, we can produce an optimized binary as follows:
+
+```shell
+rustc -O -Zdebug-info-for-profiling main.rs -o main
+perf record -b ./main
+create_llvm_prof --binary=main --out=code.prof
+rustc -O -Zprofile-sample-use=code.prof main.rs -o main2
+```
+
+The `perf` command produces a profile `perf.data`, which is then used by the
+`create_llvm_prof` command to create `code.prof`. This final profile is then
+used by `rustc` to guide optimizations in producing the binary `main2`.
+
+[this repository]: https://github.com/google/autofdo
diff --git a/src/doc/unstable-book/src/compiler-flags/dwarf-version.md b/src/doc/unstable-book/src/compiler-flags/dwarf-version.md
new file mode 100644
index 000000000..c5e86f17d
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/dwarf-version.md
@@ -0,0 +1,9 @@
+## `dwarf-version`
+
+This option controls the version of DWARF that the compiler emits, on platforms
+that use DWARF to encode debug information. It takes one of the following
+values:
+
+* `2`: DWARF version 2 (the default on certain platforms, like macOS).
+* `4`: DWARF version 4 (the default on certain platforms, like Linux).
+* `5`: DWARF version 5.
diff --git a/src/doc/unstable-book/src/compiler-flags/emit-stack-sizes.md b/src/doc/unstable-book/src/compiler-flags/emit-stack-sizes.md
new file mode 100644
index 000000000..47f45a0b9
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/emit-stack-sizes.md
@@ -0,0 +1,167 @@
+# `emit-stack-sizes`
+
+The tracking issue for this feature is: [#54192]
+
+[#54192]: https://github.com/rust-lang/rust/issues/54192
+
+------------------------
+
+The rustc flag `-Z emit-stack-sizes` makes LLVM emit stack size metadata.
+
+> **NOTE**: This LLVM feature only supports the ELF object format as of LLVM
+> 8.0. Using this flag with targets that use other object formats (e.g. macOS
+> and Windows) will result in it being ignored.
+
+Consider this crate:
+
+```
+#![crate_type = "lib"]
+
+use std::ptr;
+
+pub fn foo() {
+ // this function doesn't use the stack
+}
+
+pub fn bar() {
+ let xs = [0u32; 2];
+
+ // force LLVM to allocate `xs` on the stack
+ unsafe { ptr::read_volatile(&xs.as_ptr()); }
+}
+```
+
+Using the `-Z emit-stack-sizes` flag produces extra linker sections in the
+output *object file*.
+
+``` console
+$ rustc -C opt-level=3 --emit=obj foo.rs
+
+$ size -A foo.o
+foo.o :
+section size addr
+.text 0 0
+.text._ZN3foo3foo17he211d7b4a3a0c16eE 1 0
+.text._ZN3foo3bar17h1acb594305f70c2eE 22 0
+.note.GNU-stack 0 0
+.eh_frame 72 0
+Total 95
+
+$ rustc -C opt-level=3 --emit=obj -Z emit-stack-sizes foo.rs
+
+$ size -A foo.o
+foo.o :
+section size addr
+.text 0 0
+.text._ZN3foo3foo17he211d7b4a3a0c16eE 1 0
+.stack_sizes 9 0
+.text._ZN3foo3bar17h1acb594305f70c2eE 22 0
+.stack_sizes 9 0
+.note.GNU-stack 0 0
+.eh_frame 72 0
+Total 113
+```
+
+As of LLVM 7.0 the data will be written into a section named `.stack_sizes` and
+the format is "an array of pairs of function symbol values (pointer size) and
+stack sizes (unsigned LEB128)".
+
+``` console
+$ objdump -d foo.o
+
+foo.o: file format elf64-x86-64
+
+Disassembly of section .text._ZN3foo3foo17he211d7b4a3a0c16eE:
+
+0000000000000000 <_ZN3foo3foo17he211d7b4a3a0c16eE>:
+ 0: c3 retq
+
+Disassembly of section .text._ZN3foo3bar17h1acb594305f70c2eE:
+
+0000000000000000 <_ZN3foo3bar17h1acb594305f70c2eE>:
+ 0: 48 83 ec 10 sub $0x10,%rsp
+ 4: 48 8d 44 24 08 lea 0x8(%rsp),%rax
+ 9: 48 89 04 24 mov %rax,(%rsp)
+ d: 48 8b 04 24 mov (%rsp),%rax
+ 11: 48 83 c4 10 add $0x10,%rsp
+ 15: c3 retq
+
+$ objdump -s -j .stack_sizes foo.o
+
+foo.o: file format elf64-x86-64
+
+Contents of section .stack_sizes:
+ 0000 00000000 00000000 00 .........
+Contents of section .stack_sizes:
+ 0000 00000000 00000000 10 .........
+```
+
+It's important to note that linkers will discard this linker section by default.
+To preserve the section you can use a linker script like the one shown below.
+
+``` text
+/* file: keep-stack-sizes.x */
+SECTIONS
+{
+ /* `INFO` makes the section not allocatable so it won't be loaded into memory */
+ .stack_sizes (INFO) :
+ {
+ KEEP(*(.stack_sizes));
+ }
+}
+```
+
+The linker script must be passed to the linker using a rustc flag like `-C
+link-arg`.
+
+```
+// file: src/main.rs
+use std::ptr;
+
+#[inline(never)]
+fn main() {
+ let xs = [0u32; 2];
+
+ // force LLVM to allocate `xs` on the stack
+ unsafe { ptr::read_volatile(&xs.as_ptr()); }
+}
+```
+
+``` console
+$ RUSTFLAGS="-Z emit-stack-sizes" cargo build --release
+
+$ size -A target/release/hello | grep stack_sizes || echo section was not found
+section was not found
+
+$ RUSTFLAGS="-Z emit-stack-sizes" cargo rustc --release -- \
+ -C link-arg=-Wl,-Tkeep-stack-sizes.x \
+ -C link-arg=-N
+
+$ size -A target/release/hello | grep stack_sizes
+.stack_sizes 90 176272
+
+$ # non-allocatable section (flags don't contain the "A" (alloc) flag)
+$ readelf -S target/release/hello
+Section Headers:
+ [Nr] Name Type Address Offset
+ Size EntSize Flags Link Info Align
+(..)
+ [1031] .stack_sizes PROGBITS 000000000002b090 0002b0f0
+ 000000000000005a 0000000000000000 L 5 0 1
+
+$ objdump -s -j .stack_sizes target/release/hello
+
+target/release/hello: file format elf64-x86-64
+
+Contents of section .stack_sizes:
+ 2b090 c0040000 00000000 08f00400 00000000 ................
+ 2b0a0 00080005 00000000 00000810 05000000 ................
+ 2b0b0 00000000 20050000 00000000 10400500 .... ........@..
+ 2b0c0 00000000 00087005 00000000 00000080 ......p.........
+ 2b0d0 05000000 00000000 90050000 00000000 ................
+ 2b0e0 00a00500 00000000 0000 ..........
+```
+
+> Author note: I'm not entirely sure why, in *this* case, `-N` is required in
+> addition to `-Tkeep-stack-sizes.x`. For example, it's not required when
+> producing statically linked files for the ARM Cortex-M architecture.
diff --git a/src/doc/unstable-book/src/compiler-flags/extern-options.md b/src/doc/unstable-book/src/compiler-flags/extern-options.md
new file mode 100644
index 000000000..dfc1de77b
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/extern-options.md
@@ -0,0 +1,27 @@
+# `--extern` Options
+
+* Tracking issue for `--extern` crate modifiers: [#98405](https://github.com/rust-lang/rust/issues/98405)
+* Tracking issue for `noprelude`: [#98398](https://github.com/rust-lang/rust/issues/98398)
+* Tracking issue for `priv`: [#98399](https://github.com/rust-lang/rust/issues/98399)
+* Tracking issue for `nounused`: [#98400](https://github.com/rust-lang/rust/issues/98400)
+
+The behavior of the `--extern` flag can be modified with `noprelude`, `priv` or `nounused` options.
+
+This is unstable feature, so you have to provide `-Zunstable-options` to enable it.
+
+## Examples
+
+Use your own build of the `core` crate.
+
+`rustc main.rs -Z unstable-options --extern noprelude:core=libcore.rlib`
+
+To use multiple options, separate them with a comma:
+
+`rustc main.rs -Z unstable-options --extern noprelude,priv,nounused:mydep=mydep.rlib`
+
+## Options
+
+* `noprelude`: Do not add the crate to the external prelude. If used, it will need to be imported using `extern crate`.
+ This is used by the [build-std project](https://github.com/rust-lang/wg-cargo-std-aware/) to simulate compatibility with sysroot-only crates.
+* `priv`: Mark the crate as a private dependency for the [`exported_private_dependencies`](../../rustc/lints/listing/warn-by-default.html#exported-private-dependencies) lint.
+* `nounused`: Suppress [`unused-crate-dependencies`](../../rustc/lints/listing/allowed-by-default.html#unused-crate-dependencies) warnings for the crate.
diff --git a/src/doc/unstable-book/src/compiler-flags/location-detail.md b/src/doc/unstable-book/src/compiler-flags/location-detail.md
new file mode 100644
index 000000000..db0706199
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/location-detail.md
@@ -0,0 +1,44 @@
+# `location-detail`
+
+The tracking issue for this feature is: [#70580](https://github.com/rust-lang/rust/issues/70580).
+
+------------------------
+
+Option `-Z location-detail=val` controls what location details are tracked when
+using `caller_location`. This allows users to control what location details
+are printed as part of panic messages, by allowing them to exclude any combination
+of filenames, line numbers, and column numbers. This option is intended to provide
+users with a way to mitigate the size impact of `#[track_caller]`.
+
+This option supports a comma separated list of location details to be included. Valid options
+within this list are:
+
+- `file` - the filename of the panic will be included in the panic output
+- `line` - the source line of the panic will be included in the panic output
+- `column` - the source column of the panic will be included in the panic output
+
+Any combination of these three options are supported. Alternatively, you can pass
+`none` to this option, which results in no location details being tracked.
+If this option is not specified, all three are included by default.
+
+An example of a panic output when using `-Z location-detail=line`:
+```text
+panicked at 'Process blink had a fault', <redacted>:323:0
+```
+
+The code size savings from this option are two-fold. First, the `&'static str` values
+for each path to a file containing a panic are removed from the binary. For projects
+with deep directory structures and many files with panics, this can add up. This category
+of savings can only be realized by excluding filenames from the panic output. Second,
+savings can be realized by allowing multiple panics to be fused into a single panicking
+branch. It is often the case that within a single file, multiple panics with the same
+panic message exist -- e.g. two calls to `Option::unwrap()` in a single line, or
+two calls to `Result::expect()` on adjacent lines. If column and line information
+are included in the `Location` struct passed to the panic handler, these branches cannot
+be fused, as the output is different depending on which panic occurs. However if line
+and column information is identical for all panics, these branches can be fused, which
+can lead to substantial code size savings, especially for small embedded binaries with
+many panics.
+
+The savings from this option are amplified when combined with the use of `-Zbuild-std`, as
+otherwise paths for panics within the standard library are still included in your binary.
diff --git a/src/doc/unstable-book/src/compiler-flags/move-size-limit.md b/src/doc/unstable-book/src/compiler-flags/move-size-limit.md
new file mode 100644
index 000000000..88f022af2
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/move-size-limit.md
@@ -0,0 +1,10 @@
+# `move_size_limit`
+
+--------------------
+
+The `-Zmove-size-limit=N` compiler flag enables `large_assignments` lints which
+will warn when moving objects whose size exceeds `N` bytes.
+
+Lint warns only about moves in functions that participate in code generation.
+Consequently it will be ineffective for compiler invocatation that emit
+metadata only, i.e., `cargo check` like workflows.
diff --git a/src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md b/src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md
new file mode 100644
index 000000000..5c1c7cda7
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/no-unique-section-names.md
@@ -0,0 +1,9 @@
+# `no-unique-section-names`
+
+------------------------
+
+This flag currently applies only to ELF-based targets using the LLVM codegen backend. It prevents the generation of unique ELF section names for each separate code and data item when `-Z function-sections` is also in use, which is the default for most targets. This option can reduce the size of object files, and depending on the linker, the final ELF binary as well.
+
+For example, a function `func` will by default generate a code section called `.text.func`. Normally this is fine because the linker will merge all those `.text.*` sections into a single one in the binary. However, starting with [LLVM 12](https://github.com/llvm/llvm-project/commit/ee5d1a04), the backend will also generate unique section names for exception handling, so you would see a section name of `.gcc_except_table.func` in the object file and potentially in the final ELF binary, which could add significant bloat to programs that contain many functions.
+
+This flag instructs LLVM to use the same `.text` and `.gcc_except_table` section name for each function, and it is analogous to Clang's `-fno-unique-section-names` option.
diff --git a/src/doc/unstable-book/src/compiler-flags/profile.md b/src/doc/unstable-book/src/compiler-flags/profile.md
new file mode 100644
index 000000000..71303bfaf
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/profile.md
@@ -0,0 +1,27 @@
+# `profile`
+
+The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524).
+
+------------------------
+
+This feature allows the generation of code coverage reports.
+
+Set the `-Zprofile` compiler flag in order to enable gcov profiling.
+
+For example:
+```Bash
+cargo new testgcov --bin
+cd testgcov
+export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
+export CARGO_INCREMENTAL=0
+cargo build
+cargo run
+```
+
+Once you've built and run your program, files with the `gcno` (after build) and `gcda` (after execution) extensions will be created.
+You can parse them with [llvm-cov gcov](https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-gcov) or [grcov](https://github.com/mozilla/grcov).
+
+Please note that `RUSTFLAGS` by default applies to everything that cargo builds and runs during a build!
+When the `--target` flag is explicitly passed to cargo, the `RUSTFLAGS` no longer apply to build scripts and procedural macros.
+For more fine-grained control consider passing a `RUSTC_WRAPPER` program to cargo that only adds the profiling flags to
+rustc for the specific crates you want to profile.
diff --git a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md
new file mode 100644
index 000000000..ce894ce6a
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md
@@ -0,0 +1,10 @@
+# `profile-sample-use
+
+---
+
+`-Zprofile-sample-use=code.prof` directs `rustc` to use the profile
+`code.prof` as a source for Automatic Feedback Directed Optimization (AFDO).
+See the documentation of [`-Zdebug-info-for-profiling`] for more information
+on using AFDO.
+
+[`-Zdebug-info-for-profiling`]: debug_info_for_profiling.html
diff --git a/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md b/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md
new file mode 100644
index 000000000..977d25852
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md
@@ -0,0 +1,24 @@
+# `remap-cwd-prefix`
+
+The tracking issue for this feature is: [#87325](https://github.com/rust-lang/rust/issues/87325).
+
+------------------------
+
+This flag will rewrite absolute paths under the current working directory,
+replacing the current working directory prefix with a specified value.
+
+The given value may be absolute or relative, or empty. This switch takes
+precidence over `--remap-path-prefix` in case they would both match a given
+path.
+
+This flag helps to produce deterministic output, by removing the current working
+directory from build output, while allowing the command line to be universally
+reproducible, such that the same execution will work on all machines, regardless
+of build environment.
+
+## Example
+```sh
+# This would produce an absolute path to main.rs in build outputs of
+# "./main.rs".
+rustc -Z remap-cwd-prefix=. main.rs
+```
diff --git a/src/doc/unstable-book/src/compiler-flags/report-time.md b/src/doc/unstable-book/src/compiler-flags/report-time.md
new file mode 100644
index 000000000..9e6a1fb00
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/report-time.md
@@ -0,0 +1,77 @@
+# `report-time`
+
+The tracking issue for this feature is: [#64888]
+
+[#64888]: https://github.com/rust-lang/rust/issues/64888
+
+------------------------
+
+The `report-time` feature adds a possibility to report execution time of the
+tests generated via `libtest`.
+
+This is unstable feature, so you have to provide `-Zunstable-options` to get
+this feature working.
+
+Sample usage command:
+
+```sh
+./test_executable -Zunstable-options --report-time
+```
+
+Available options:
+
+```sh
+--report-time
+ Show execution time of each test.
+ Threshold values for colorized output can be
+ configured via
+ `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION`
+ and
+ `RUST_TEST_TIME_DOCTEST` environment variables.
+ Expected format of environment variable is
+ `VARIABLE=WARN_TIME,CRITICAL_TIME`.
+ Not available for --format=terse
+--ensure-time
+ Treat excess of the test execution time limit as
+ error.
+ Threshold values for this option can be configured via
+ `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION`
+ and
+ `RUST_TEST_TIME_DOCTEST` environment variables.
+ Expected format of environment variable is
+ `VARIABLE=WARN_TIME,CRITICAL_TIME`.
+ `CRITICAL_TIME` here means the limit that should not be
+ exceeded by test.
+```
+
+Example of the environment variable format:
+
+```sh
+RUST_TEST_TIME_UNIT=100,200
+```
+
+where 100 stands for warn time, and 200 stands for critical time.
+
+## Examples
+
+```sh
+cargo test --tests -- -Zunstable-options --report-time
+ Finished dev [unoptimized + debuginfo] target(s) in 0.02s
+ Running target/debug/deps/example-27fb188025bec02c
+
+running 3 tests
+test tests::unit_test_quick ... ok <0.000s>
+test tests::unit_test_warn ... ok <0.055s>
+test tests::unit_test_critical ... ok <0.110s>
+
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
+ Running target/debug/deps/tests-cedb06f6526d15d9
+
+running 3 tests
+test unit_test_quick ... ok <0.000s>
+test unit_test_warn ... ok <0.550s>
+test unit_test_critical ... ok <1.100s>
+
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+```
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
new file mode 100644
index 000000000..7f7549aaf
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -0,0 +1,684 @@
+# `sanitizer`
+
+The tracking issues for this feature are:
+
+* [#39699](https://github.com/rust-lang/rust/issues/39699).
+* [#89653](https://github.com/rust-lang/rust/issues/89653).
+
+------------------------
+
+This feature allows for use of one of following sanitizers:
+
+* [AddressSanitizer][clang-asan] a fast memory error detector.
+* [ControlFlowIntegrity][clang-cfi] LLVM Control Flow Integrity (CFI) provides
+ forward-edge control flow protection.
+* [HWAddressSanitizer][clang-hwasan] a memory error detector similar to
+ AddressSanitizer, but based on partial hardware assistance.
+* [LeakSanitizer][clang-lsan] a run-time memory leak detector.
+* [MemorySanitizer][clang-msan] a detector of uninitialized reads.
+* [MemTagSanitizer][clang-memtag] fast memory error detector based on
+ Armv8.5-A Memory Tagging Extension.
+* [ShadowCallStack][clang-scs] provides backward-edge control flow protection.
+* [ThreadSanitizer][clang-tsan] a fast data race detector.
+
+To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`,
+`-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`,
+`-Zsanitizer=memtag`, `-Zsanitizer=shadow-call-stack`, or `-Zsanitizer=thread`.
+You might also need the `--target` and `build-std` flags. Example:
+```shell
+$ RUSTFLAGS=-Zsanitizer=address cargo build -Zbuild-std --target x86_64-unknown-linux-gnu
+```
+
+# AddressSanitizer
+
+AddressSanitizer is a memory error detector. It can detect the following types
+of bugs:
+
+* Out of bound accesses to heap, stack and globals
+* Use after free
+* Use after return (runtime flag `ASAN_OPTIONS=detect_stack_use_after_return=1`)
+* Use after scope
+* Double-free, invalid free
+* Memory leaks
+
+The memory leak detection is enabled by default on Linux, and can be enabled
+with runtime flag `ASAN_OPTIONS=detect_leaks=1` on macOS.
+
+AddressSanitizer is supported on the following targets:
+
+* `aarch64-apple-darwin`
+* `aarch64-fuchsia`
+* `aarch64-unknown-linux-gnu`
+* `x86_64-apple-darwin`
+* `x86_64-fuchsia`
+* `x86_64-unknown-freebsd`
+* `x86_64-unknown-linux-gnu`
+
+AddressSanitizer works with non-instrumented code although it will impede its
+ability to detect some bugs. It is not expected to produce false positive
+reports.
+
+## Examples
+
+Stack buffer overflow:
+
+```rust
+fn main() {
+ let xs = [0, 1, 2, 3];
+ let _y = unsafe { *xs.as_ptr().offset(4) };
+}
+```
+
+```shell
+$ export RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address
+$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
+==37882==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe400e6250 at pc 0x5609a841fb20 bp 0x7ffe400e6210 sp 0x7ffe400e6208
+READ of size 4 at 0x7ffe400e6250 thread T0
+ #0 0x5609a841fb1f in example::main::h628ffc6626ed85b2 /.../src/main.rs:3:23
+ ...
+
+Address 0x7ffe400e6250 is located in stack of thread T0 at offset 48 in frame
+ #0 0x5609a841f8af in example::main::h628ffc6626ed85b2 /.../src/main.rs:1
+
+ This frame has 1 object(s):
+ [32, 48) 'xs' (line 2) <== Memory access at offset 48 overflows this variable
+HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
+ (longjmp and C++ exceptions *are* supported)
+SUMMARY: AddressSanitizer: stack-buffer-overflow /.../src/main.rs:3:23 in example::main::h628ffc6626ed85b2
+Shadow bytes around the buggy address:
+ 0x100048014bf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0x100048014c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0x100048014c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0x100048014c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0x100048014c30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+=>0x100048014c40: 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00
+ 0x100048014c50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0x100048014c60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0x100048014c70: f1 f1 f1 f1 00 00 f3 f3 00 00 00 00 00 00 00 00
+ 0x100048014c80: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
+ 0x100048014c90: 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
+Shadow byte legend (one shadow byte represents 8 application bytes):
+ Addressable: 00
+ Partially addressable: 01 02 03 04 05 06 07
+ Heap left redzone: fa
+ Freed heap region: fd
+ Stack left redzone: f1
+ Stack mid redzone: f2
+ Stack right redzone: f3
+ Stack after return: f5
+ Stack use after scope: f8
+ Global redzone: f9
+ Global init order: f6
+ Poisoned by user: f7
+ Container overflow: fc
+ Array cookie: ac
+ Intra object redzone: bb
+ ASan internal: fe
+ Left alloca redzone: ca
+ Right alloca redzone: cb
+ Shadow gap: cc
+==37882==ABORTING
+```
+
+Use of a stack object after its scope has already ended:
+
+```rust
+static mut P: *mut usize = std::ptr::null_mut();
+
+fn main() {
+ unsafe {
+ {
+ let mut x = 0;
+ P = &mut x;
+ }
+ std::ptr::write_volatile(P, 123);
+ }
+}
+```
+
+```shell
+$ export RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address
+$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
+=================================================================
+==39249==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffc7ed3e1a0 at pc 0x55c98b262a8e bp 0x7ffc7ed3e050 sp 0x7ffc7ed3e048
+WRITE of size 8 at 0x7ffc7ed3e1a0 thread T0
+ #0 0x55c98b262a8d in core::ptr::write_volatile::he21f1df5a82f329a /.../src/rust/src/libcore/ptr/mod.rs:1048:5
+ #1 0x55c98b262cd2 in example::main::h628ffc6626ed85b2 /.../src/main.rs:9:9
+ ...
+
+Address 0x7ffc7ed3e1a0 is located in stack of thread T0 at offset 32 in frame
+ #0 0x55c98b262bdf in example::main::h628ffc6626ed85b2 /.../src/main.rs:3
+
+ This frame has 1 object(s):
+ [32, 40) 'x' (line 6) <== Memory access at offset 32 is inside this variable
+HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
+ (longjmp and C++ exceptions *are* supported)
+SUMMARY: AddressSanitizer: stack-use-after-scope /.../src/rust/src/libcore/ptr/mod.rs:1048:5 in core::ptr::write_volatile::he21f1df5a82f329a
+Shadow bytes around the buggy address:
+ 0x10000fd9fbe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0x10000fd9fbf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0x10000fd9fc00: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
+ 0x10000fd9fc10: f8 f8 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
+ 0x10000fd9fc20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+=>0x10000fd9fc30: f1 f1 f1 f1[f8]f3 f3 f3 00 00 00 00 00 00 00 00
+ 0x10000fd9fc40: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
+ 0x10000fd9fc50: 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
+ 0x10000fd9fc60: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 f3 f3
+ 0x10000fd9fc70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0x10000fd9fc80: 00 00 00 00 f1 f1 f1 f1 00 00 f3 f3 00 00 00 00
+Shadow byte legend (one shadow byte represents 8 application bytes):
+ Addressable: 00
+ Partially addressable: 01 02 03 04 05 06 07
+ Heap left redzone: fa
+ Freed heap region: fd
+ Stack left redzone: f1
+ Stack mid redzone: f2
+ Stack right redzone: f3
+ Stack after return: f5
+ Stack use after scope: f8
+ Global redzone: f9
+ Global init order: f6
+ Poisoned by user: f7
+ Container overflow: fc
+ Array cookie: ac
+ Intra object redzone: bb
+ ASan internal: fe
+ Left alloca redzone: ca
+ Right alloca redzone: cb
+ Shadow gap: cc
+==39249==ABORTING
+```
+
+# ControlFlowIntegrity
+
+The LLVM Control Flow Integrity (CFI) support in the Rust compiler initially
+provides forward-edge control flow protection for Rust-compiled code only by
+aggregating function pointers in groups identified by their return and parameter
+types.
+
+Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed
+binaries" (i.e., for when C or C++ and Rust -compiled code share the same
+virtual address space) will be provided in later work by defining and using
+compatible type identifiers (see Type metadata in the design document in the
+tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
+
+LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto).
+
+## Example
+
+```text
+#![feature(naked_functions)]
+
+use std::arch::asm;
+use std::mem;
+
+fn add_one(x: i32) -> i32 {
+ x + 1
+}
+
+#[naked]
+pub extern "C" fn add_two(x: i32) {
+ // x + 2 preceded by a landing pad/nop block
+ unsafe {
+ asm!(
+ "
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ lea rax, [rdi+2]
+ ret
+ ",
+ options(noreturn)
+ );
+ }
+}
+
+fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
+ f(arg) + f(arg)
+}
+
+fn main() {
+ let answer = do_twice(add_one, 5);
+
+ println!("The answer is: {}", answer);
+
+ 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).
+ mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5))
+ };
+ let next_answer = do_twice(f, 5);
+
+ 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.
+
+```shell
+$ cargo run --release
+ Compiling rust-cfi-1 v0.1.0 (/home/rcvalle/rust-cfi-1)
+ Finished release [optimized] target(s) in 0.76s
+ 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.
+
+```shell
+$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
+ 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`
+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.
+
+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).
+
+```rust
+use std::mem;
+
+fn add_one(x: i32) -> i32 {
+ x + 1
+}
+
+fn add_two(x: i32, _y: i32) -> i32 {
+ x + 2
+}
+
+fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
+ f(arg) + f(arg)
+}
+
+fn main() {
+ let answer = do_twice(add_one, 5);
+
+ println!("The answer is: {}", answer);
+
+ println!("With CFI enabled, you should not see the next answer");
+ let f: fn(i32) -> i32 =
+ unsafe { mem::transmute::<*const u8, fn(i32) -> i32>(add_two as *const u8) };
+ let next_answer = do_twice(f, 5);
+
+ 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.
+
+```shell
+$ cargo run --release
+ Compiling rust-cfi-2 v0.1.0 (/home/rcvalle/rust-cfi-2)
+ Finished release [optimized] target(s) in 0.76s
+ 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.
+
+```shell
+$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
+ 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`
+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.
+
+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).
+
+```rust
+use std::mem;
+
+fn add_one(x: i32) -> i32 {
+ x + 1
+}
+
+fn add_two(x: i64) -> i64 {
+ x + 2
+}
+
+fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
+ f(arg) + f(arg)
+}
+
+fn main() {
+ let answer = do_twice(add_one, 5);
+
+ println!("The answer is: {}", answer);
+
+ println!("With CFI enabled, you should not see the next answer");
+ let f: fn(i32) -> i32 =
+ unsafe { mem::transmute::<*const u8, fn(i32) -> i32>(add_two as *const u8) };
+ let next_answer = do_twice(f, 5);
+
+ 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.
+
+```shell
+ cargo run --release
+ Compiling rust-cfi-3 v0.1.0 (/home/rcvalle/rust-cfi-3)
+ Finished release [optimized] target(s) in 0.74s
+ 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.
+
+```shell
+$ RUSTFLAGS="-Zsanitizer=cfi -Cembed-bitcode=yes -Clto" cargo run --release
+ 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`
+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.
+
+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).
+
+[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
+
+# HWAddressSanitizer
+
+HWAddressSanitizer is a newer variant of AddressSanitizer that consumes much
+less memory.
+
+HWAddressSanitizer is supported on the following targets:
+
+* `aarch64-linux-android`
+* `aarch64-unknown-linux-gnu`
+
+HWAddressSanitizer requires `tagged-globals` target feature to instrument
+globals. To enable this target feature compile with `-C
+target-feature=+tagged-globals`
+
+## Example
+
+Heap buffer overflow:
+
+```rust
+fn main() {
+ let xs = vec![0, 1, 2, 3];
+ let _y = unsafe { *xs.as_ptr().offset(4) };
+}
+```
+
+```shell
+$ rustc main.rs -Zsanitizer=hwaddress -C target-feature=+tagged-globals -C
+linker=aarch64-linux-gnu-gcc -C link-arg=-fuse-ld=lld --target
+aarch64-unknown-linux-gnu
+```
+
+```shell
+$ ./main
+==241==ERROR: HWAddressSanitizer: tag-mismatch on address 0xefdeffff0050 at pc 0xaaaae0ae4a98
+READ of size 4 at 0xefdeffff0050 tags: 2c/00 (ptr/mem) in thread T0
+ #0 0xaaaae0ae4a94 (/.../main+0x54a94)
+ ...
+
+[0xefdeffff0040,0xefdeffff0060) is a small allocated heap chunk; size: 32 offset: 16
+0xefdeffff0050 is located 0 bytes to the right of 16-byte region [0xefdeffff0040,0xefdeffff0050)
+allocated here:
+ #0 0xaaaae0acb80c (/.../main+0x3b80c)
+ ...
+
+Thread: T0 0xeffe00002000 stack: [0xffffc28ad000,0xffffc30ad000) sz: 8388608 tls: [0xffffaa10a020,0xffffaa10a7d0)
+Memory tags around the buggy address (one tag corresponds to 16 bytes):
+ 0xfefcefffef80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefcefffef90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefcefffefa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefcefffefb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefcefffefc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefcefffefd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefcefffefe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefcefffeff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+=>0xfefceffff000: d7 d7 05 00 2c [00] 00 00 00 00 00 00 00 00 00 00
+ 0xfefceffff010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefceffff020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefceffff030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefceffff040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefceffff050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefceffff060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefceffff070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ 0xfefceffff080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+Tags for short granules around the buggy address (one tag corresponds to 16 bytes):
+ 0xfefcefffeff0: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
+=>0xfefceffff000: .. .. 8c .. .. [..] .. .. .. .. .. .. .. .. .. ..
+ 0xfefceffff010: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
+See https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#short-granules for a description of short granule tags
+Registers where the failure occurred (pc 0xaaaae0ae4a98):
+ x0 2c00efdeffff0050 x1 0000000000000004 x2 0000000000000004 x3 0000000000000000
+ x4 0000fffefc30ac37 x5 000000000000005d x6 00000ffffc30ac37 x7 0000efff00000000
+ x8 2c00efdeffff0050 x9 0200efff00000000 x10 0000000000000000 x11 0200efff00000000
+ x12 0200effe00000310 x13 0200effe00000310 x14 0000000000000008 x15 5d00ffffc30ac360
+ x16 0000aaaae0ad062c x17 0000000000000003 x18 0000000000000001 x19 0000ffffc30ac658
+ x20 4e00ffffc30ac6e0 x21 0000aaaae0ac5e10 x22 0000000000000000 x23 0000000000000000
+ x24 0000000000000000 x25 0000000000000000 x26 0000000000000000 x27 0000000000000000
+ x28 0000000000000000 x29 0000ffffc30ac5a0 x30 0000aaaae0ae4a98
+SUMMARY: HWAddressSanitizer: tag-mismatch (/.../main+0x54a94)
+```
+
+# LeakSanitizer
+
+LeakSanitizer is run-time memory leak detector.
+
+LeakSanitizer is supported on the following targets:
+
+* `aarch64-apple-darwin`
+* `aarch64-unknown-linux-gnu`
+* `x86_64-apple-darwin`
+* `x86_64-unknown-linux-gnu`
+
+# MemorySanitizer
+
+MemorySanitizer is detector of uninitialized reads.
+
+MemorySanitizer is supported on the following targets:
+
+* `aarch64-unknown-linux-gnu`
+* `x86_64-unknown-freebsd`
+* `x86_64-unknown-linux-gnu`
+
+MemorySanitizer requires all program code to be instrumented. C/C++ dependencies
+need to be recompiled using Clang with `-fsanitize=memory` option. Failing to
+achieve that will result in false positive reports.
+
+## Example
+
+Detecting the use of uninitialized memory. The `-Zbuild-std` flag rebuilds and
+instruments the standard library, and is strictly necessary for the correct
+operation of the tool. The `-Zsanitizer-memory-track-origins` enables tracking
+of the origins of uninitialized memory:
+
+```rust
+use std::mem::MaybeUninit;
+
+fn main() {
+ unsafe {
+ let a = MaybeUninit::<[usize; 4]>::uninit();
+ let a = a.assume_init();
+ println!("{}", a[2]);
+ }
+}
+```
+
+```shell
+$ export \
+ RUSTFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins' \
+ RUSTDOCFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins'
+$ cargo clean
+$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
+==9416==WARNING: MemorySanitizer: use-of-uninitialized-value
+ #0 0x560c04f7488a in core::fmt::num::imp::fmt_u64::haa293b0b098501ca $RUST/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/src/libcore/fmt/num.rs:202:16
+...
+ Uninitialized value was stored to memory at
+ #0 0x560c04ae898a in __msan_memcpy.part.0 $RUST/src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cc:1558:3
+ #1 0x560c04b2bf88 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:6:16
+
+ Uninitialized value was created by an allocation of 'a' in the stack frame of function '_ZN6memory4main17hd2333c1899d997f5E'
+ #0 0x560c04b2bc50 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:3
+```
+
+# MemTagSanitizer
+
+MemTagSanitizer detects a similar class of errors as AddressSanitizer and HardwareAddressSanitizer, but with lower overhead suitable for use as hardening for production binaries.
+
+MemTagSanitizer is supported on the following targets:
+
+* `aarch64-linux-android`
+* `aarch64-unknown-linux-gnu`
+
+MemTagSanitizer requires hardware support and the `mte` target feature.
+To enable this target feature compile with `-C target-feature="+mte"`.
+
+More information can be found in the associated [LLVM documentation](https://llvm.org/docs/MemTagSanitizer.html).
+
+# ShadowCallStack
+
+ShadowCallStack provides backward edge control flow protection by storing a function's return address in a separately allocated 'shadow call stack' and loading the return address from that shadow call stack.
+
+ShadowCallStack requires a platform ABI which reserves `x18` as the instrumentation makes use of this register.
+
+ShadowCallStack can be enabled with `-Zsanitizer=shadow-call-stack` option and is supported on the following targets:
+
+* `aarch64-linux-android`
+
+A runtime must be provided by the application or operating system. See the [LLVM documentation][clang-scs] for further details.
+
+# ThreadSanitizer
+
+ThreadSanitizer is a data race detection tool. It is supported on the following
+targets:
+
+* `aarch64-apple-darwin`
+* `aarch64-unknown-linux-gnu`
+* `x86_64-apple-darwin`
+* `x86_64-unknown-freebsd`
+* `x86_64-unknown-linux-gnu`
+
+To work correctly ThreadSanitizer needs to be "aware" of all synchronization
+operations in a program. It generally achieves that through combination of
+library interception (for example synchronization performed through
+`pthread_mutex_lock` / `pthread_mutex_unlock`) and compile time instrumentation
+(e.g. atomic operations). Using it without instrumenting all the program code
+can lead to false positive reports.
+
+ThreadSanitizer does not support atomic fences `std::sync::atomic::fence`,
+nor synchronization performed using inline assembly code.
+
+## Example
+
+```rust
+static mut A: usize = 0;
+
+fn main() {
+ let t = std::thread::spawn(|| {
+ unsafe { A += 1 };
+ });
+ unsafe { A += 1 };
+
+ t.join().unwrap();
+}
+```
+
+```shell
+$ export RUSTFLAGS=-Zsanitizer=thread RUSTDOCFLAGS=-Zsanitizer=thread
+$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
+==================
+WARNING: ThreadSanitizer: data race (pid=10574)
+ Read of size 8 at 0x5632dfe3d030 by thread T1:
+ #0 example::main::_$u7b$$u7b$closure$u7d$$u7d$::h23f64b0b2f8c9484 ../src/main.rs:5:18 (example+0x86cec)
+ ...
+
+ Previous write of size 8 at 0x5632dfe3d030 by main thread:
+ #0 example::main::h628ffc6626ed85b2 /.../src/main.rs:7:14 (example+0x868c8)
+ ...
+ #11 main <null> (example+0x86a1a)
+
+ Location is global 'example::A::h43ac149ddf992709' of size 8 at 0x5632dfe3d030 (example+0x000000bd9030)
+```
+
+# Instrumentation of external dependencies and std
+
+The sanitizers to varying degrees work correctly with partially instrumented
+code. On the one extreme is LeakSanitizer that doesn't use any compile time
+instrumentation, on the other is MemorySanitizer that requires that all program
+code to be instrumented (failing to achieve that will inevitably result in
+false positives).
+
+It is strongly recommended to combine sanitizers with recompiled and
+instrumented standard library, for example using [cargo `-Zbuild-std`
+functionality][build-std].
+
+[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
+
+# Build scripts and procedural macros
+
+Use of sanitizers together with build scripts and procedural macros is
+technically possible, but in almost all cases it would be best avoided. This
+is especially true for procedural macros which would require an instrumented
+version of rustc.
+
+In more practical terms when using cargo always remember to pass `--target`
+flag, so that rustflags will not be applied to build scripts and procedural
+macros.
+
+# Symbolizing the Reports
+
+Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PATH`.
+
+# Additional Information
+
+* [Sanitizers project page](https://github.com/google/sanitizers/wiki/)
+* [AddressSanitizer in Clang][clang-asan]
+* [ControlFlowIntegrity in Clang][clang-cfi]
+* [HWAddressSanitizer in Clang][clang-hwasan]
+* [LeakSanitizer in Clang][clang-lsan]
+* [MemorySanitizer in Clang][clang-msan]
+* [ThreadSanitizer in Clang][clang-tsan]
+
+[clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
+[clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html
+[clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
+[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
+[clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
+[clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html
+[clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html
diff --git a/src/doc/unstable-book/src/compiler-flags/self-profile-events.md b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md
new file mode 100644
index 000000000..3ce18743b
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md
@@ -0,0 +1,74 @@
+# `self-profile-events`
+
+---------------------
+
+The `-Zself-profile-events` compiler flag controls what events are recorded by the self-profiler when it is enabled via the `-Zself-profile` flag.
+
+This flag takes a comma delimited list of event types to record.
+
+For example:
+
+```console
+$ rustc -Zself-profile -Zself-profile-events=default,args
+```
+
+## Event types
+
+- `query-provider`
+ - Traces each query used internally by the compiler.
+
+- `generic-activity`
+ - Traces other parts of the compiler not covered by the query system.
+
+- `query-cache-hit`
+ - Adds tracing information that records when the in-memory query cache is "hit" and does not need to re-execute a query which has been cached.
+ - Disabled by default because this significantly increases the trace file size.
+
+- `query-blocked`
+ - Tracks time that a query tries to run but is blocked waiting on another thread executing the same query to finish executing.
+ - Query blocking only occurs when the compiler is built with parallel mode support.
+
+- `incr-cache-load`
+ - Tracks time that is spent loading and deserializing query results from the incremental compilation on-disk cache.
+
+- `query-keys`
+ - Adds a serialized representation of each query's query key to the tracing data.
+ - Disabled by default because this significantly increases the trace file size.
+
+- `function-args`
+ - Adds additional tracing data to some `generic-activity` events.
+ - Disabled by default for parity with `query-keys`.
+
+- `llvm`
+ - Adds tracing information about LLVM passes and codegeneration.
+ - Disabled by default because this only works when `-Znew-llvm-pass-manager` is enabled.
+
+## Event synonyms
+
+- `none`
+ - Disables all events.
+ Equivalent to the self-profiler being disabled.
+
+- `default`
+ - The default set of events which stikes a balance between providing detailed tracing data and adding additional overhead to the compilation.
+
+- `args`
+ - Equivalent to `query-keys` and `function-args`.
+
+- `all`
+ - Enables all events.
+
+## Examples
+
+Enable the profiler and capture the default set of events (both invocations are equivalent):
+
+```console
+$ rustc -Zself-profile
+$ rustc -Zself-profile -Zself-profile-events=default
+```
+
+Enable the profiler and capture the default events and their arguments:
+
+```console
+$ rustc -Zself-profile -Zself-profile-events=default,args
+```
diff --git a/src/doc/unstable-book/src/compiler-flags/self-profile.md b/src/doc/unstable-book/src/compiler-flags/self-profile.md
new file mode 100644
index 000000000..7305141a4
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/self-profile.md
@@ -0,0 +1,47 @@
+# `self-profile`
+
+--------------------
+
+The `-Zself-profile` compiler flag enables rustc's internal profiler.
+When enabled, the compiler will output three binary files in the specified directory (or the current working directory if no directory is specified).
+These files can be analyzed by using the tools in the [`measureme`] repository.
+
+To control the data recorded in the trace files, use the `-Zself-profile-events` flag.
+
+For example:
+
+First, run a compilation session and provide the `-Zself-profile` flag:
+
+```console
+$ rustc --crate-name foo -Zself-profile
+```
+
+This will generate three files in the working directory such as:
+
+- `foo-1234.events`
+- `foo-1234.string_data`
+- `foo-1234.string_index`
+
+Where `foo` is the name of the crate and `1234` is the process id of the rustc process.
+
+To get a summary of where the compiler is spending its time:
+
+```console
+$ ../measureme/target/release/summarize summarize foo-1234
+```
+
+To generate a flamegraph of the same data:
+
+```console
+$ ../measureme/target/release/inferno foo-1234
+```
+
+To dump the event data in a Chromium-profiler compatible format:
+
+```console
+$ ../measureme/target/release/crox foo-1234
+```
+
+For more information, consult the [`measureme`] documentation.
+
+[`measureme`]: https://github.com/rust-lang/measureme.git
diff --git a/src/doc/unstable-book/src/compiler-flags/src-hash-algorithm.md b/src/doc/unstable-book/src/compiler-flags/src-hash-algorithm.md
new file mode 100644
index 000000000..ff776741b
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/src-hash-algorithm.md
@@ -0,0 +1,11 @@
+# `src-hash-algorithm`
+
+The tracking issue for this feature is: [#70401](https://github.com/rust-lang/rust/issues/70401).
+
+------------------------
+
+The `-Z src-hash-algorithm` compiler flag controls which algorithm is used when hashing each source file. The hash is stored in the debug info and can be used by a debugger to verify the source code matches the executable.
+
+Supported hash algorithms are: `md5`, `sha1`, and `sha256`. Note that not all hash algorithms are supported by all debug info formats.
+
+By default, the compiler chooses the hash algorithm based on the target specification.
diff --git a/src/doc/unstable-book/src/compiler-flags/temps-dir.md b/src/doc/unstable-book/src/compiler-flags/temps-dir.md
new file mode 100644
index 000000000..e25011f71
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/temps-dir.md
@@ -0,0 +1,10 @@
+# `temps-dir`
+
+--------------------
+
+The `-Ztemps-dir` compiler flag specifies the directory to write the
+intermediate files in. If not set, the output directory is used. This option is
+useful if you are running more than one instance of `rustc` (e.g. with different
+`--crate-type` settings), and you need to make sure they are not overwriting
+each other's intermediate files. No files are kept unless `-C save-temps=yes` is
+also set.
diff --git a/src/doc/unstable-book/src/compiler-flags/tls-model.md b/src/doc/unstable-book/src/compiler-flags/tls-model.md
new file mode 100644
index 000000000..8b19e785c
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/tls-model.md
@@ -0,0 +1,25 @@
+# `tls_model`
+
+The tracking issue for this feature is: None.
+
+------------------------
+
+Option `-Z tls-model` controls [TLS model](https://www.akkadia.org/drepper/tls.pdf) used to
+generate code for accessing `#[thread_local]` `static` items.
+
+Supported values for this option are:
+
+- `global-dynamic` - General Dynamic TLS Model (alternatively called Global Dynamic) is the most
+general option usable in all circumstances, even if the TLS data is defined in a shared library
+loaded at runtime and is accessed from code outside of that library.
+This is the default for most targets.
+- `local-dynamic` - model usable if the TLS data is only accessed from the shared library or
+executable it is defined in. The TLS data may be in a library loaded after startup (via `dlopen`).
+- `initial-exec` - model usable if the TLS data is defined in the executable or in a shared library
+loaded at program startup.
+The TLS data must not be in a library loaded after startup (via `dlopen`).
+- `local-exec` - model usable only if the TLS data is defined directly in the executable,
+but not in a shared library, and is accessed only from that executable.
+
+`rustc` and LLVM may use a more optimized model than specified if they know that we are producing
+an executable rather than a library, or that the `static` item is private enough.
diff --git a/src/doc/unstable-book/src/compiler-flags/unsound-mir-opts.md b/src/doc/unstable-book/src/compiler-flags/unsound-mir-opts.md
new file mode 100644
index 000000000..8e46e227c
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/unsound-mir-opts.md
@@ -0,0 +1,8 @@
+# `unsound-mir-opts`
+
+--------------------
+
+The `-Zunsound-mir-opts` compiler flag enables [MIR optimization passes] which can cause unsound behavior.
+This flag should only be used by MIR optimization tests in the rustc test suite.
+
+[MIR optimization passes]: https://rustc-dev-guide.rust-lang.org/mir/optimizations.html
diff --git a/src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md b/src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md
new file mode 100644
index 000000000..c6516d838
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/virtual-function-elimination.md
@@ -0,0 +1,39 @@
+# `virtual-function-elimination`
+
+This option controls whether LLVM runs the Virtual Function Elimination (VFE)
+optimization. This optimization in only available with LTO, so this flag can
+only be passed if [`-Clto`][Clto] is also passed.
+
+VFE makes it possible to remove functions from vtables that are never
+dynamically called by the rest of the code. Without this flag, LLVM makes the
+really conservative assumption, that if any function in a vtable is called, no
+function that is referenced by this vtable can be removed. With this flag
+additional information are given to LLVM, so that it can determine which
+functions are actually called and remove the unused functions.
+
+## Limitations
+
+At the time of writing this flag may remove vtable functions too eagerly. One
+such example is in this code:
+
+```rust
+trait Foo { fn foo(&self) { println!("foo") } }
+
+impl Foo for usize {}
+
+pub struct FooBox(Box<dyn Foo>);
+
+pub fn make_foo() -> FooBox { FooBox(Box::new(0)) }
+
+#[inline]
+pub fn f(a: FooBox) { a.0.foo() }
+```
+
+In the above code the `Foo` trait is private, so an assumption is made that its
+functions can only be seen/called from the current crate and can therefore get
+optimized out, if unused. However, with `make_foo` you can produce a wrapped
+`dyn Foo` type outside of the current crate, which can then be used in `f`. Due
+to inlining of `f`, `Foo::foo` can then be called from a foreign crate. This can
+lead to miscompilations.
+
+[Clto]: https://doc.rust-lang.org/rustc/codegen-options/index.html#lto
diff --git a/src/doc/unstable-book/src/language-features.md b/src/doc/unstable-book/src/language-features.md
new file mode 100644
index 000000000..a27514df9
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features.md
@@ -0,0 +1 @@
+# Language features
diff --git a/src/doc/unstable-book/src/language-features/abi-c-cmse-nonsecure-call.md b/src/doc/unstable-book/src/language-features/abi-c-cmse-nonsecure-call.md
new file mode 100644
index 000000000..79a177cb2
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/abi-c-cmse-nonsecure-call.md
@@ -0,0 +1,88 @@
+# `abi_c_cmse_nonsecure_call`
+
+The tracking issue for this feature is: [#81391]
+
+[#81391]: https://github.com/rust-lang/rust/issues/81391
+
+------------------------
+
+The [TrustZone-M
+feature](https://developer.arm.com/documentation/100690/latest/) is available
+for targets with the Armv8-M architecture profile (`thumbv8m` in their target
+name).
+LLVM, the Rust compiler and the linker are providing
+[support](https://developer.arm.com/documentation/ecm0359818/latest/) for the
+TrustZone-M feature.
+
+One of the things provided, with this unstable feature, is the
+`C-cmse-nonsecure-call` function ABI. This ABI is used on function pointers to
+non-secure code to mark a non-secure function call (see [section
+5.5](https://developer.arm.com/documentation/ecm0359818/latest/) for details).
+
+With this ABI, the compiler will do the following to perform the call:
+* save registers needed after the call to Secure memory
+* clear all registers that might contain confidential information
+* clear the Least Significant Bit of the function address
+* branches using the BLXNS instruction
+
+To avoid using the non-secure stack, the compiler will constrain the number and
+type of parameters/return value.
+
+The `extern "C-cmse-nonsecure-call"` ABI is otherwise equivalent to the
+`extern "C"` ABI.
+
+<!-- NOTE(ignore) this example is specific to thumbv8m targets -->
+
+``` rust,ignore
+#![no_std]
+#![feature(abi_c_cmse_nonsecure_call)]
+
+#[no_mangle]
+pub fn call_nonsecure_function(addr: usize) -> u32 {
+ let non_secure_function =
+ unsafe { core::mem::transmute::<usize, extern "C-cmse-nonsecure-call" fn() -> u32>(addr) };
+ non_secure_function()
+}
+```
+
+``` text
+$ rustc --emit asm --crate-type lib --target thumbv8m.main-none-eabi function.rs
+
+call_nonsecure_function:
+ .fnstart
+ .save {r7, lr}
+ push {r7, lr}
+ .setfp r7, sp
+ mov r7, sp
+ .pad #16
+ sub sp, #16
+ str r0, [sp, #12]
+ ldr r0, [sp, #12]
+ str r0, [sp, #8]
+ b .LBB0_1
+.LBB0_1:
+ ldr r0, [sp, #8]
+ push.w {r4, r5, r6, r7, r8, r9, r10, r11}
+ bic r0, r0, #1
+ mov r1, r0
+ mov r2, r0
+ mov r3, r0
+ mov r4, r0
+ mov r5, r0
+ mov r6, r0
+ mov r7, r0
+ mov r8, r0
+ mov r9, r0
+ mov r10, r0
+ mov r11, r0
+ mov r12, r0
+ msr apsr_nzcvq, r0
+ blxns r0
+ pop.w {r4, r5, r6, r7, r8, r9, r10, r11}
+ str r0, [sp, #4]
+ b .LBB0_2
+.LBB0_2:
+ ldr r0, [sp, #4]
+ add sp, #16
+ pop {r7, pc}
+```
diff --git a/src/doc/unstable-book/src/language-features/abi-msp430-interrupt.md b/src/doc/unstable-book/src/language-features/abi-msp430-interrupt.md
new file mode 100644
index 000000000..b10bc41cb
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/abi-msp430-interrupt.md
@@ -0,0 +1,42 @@
+# `abi_msp430_interrupt`
+
+The tracking issue for this feature is: [#38487]
+
+[#38487]: https://github.com/rust-lang/rust/issues/38487
+
+------------------------
+
+In the MSP430 architecture, interrupt handlers have a special calling
+convention. You can use the `"msp430-interrupt"` ABI to make the compiler apply
+the right calling convention to the interrupt handlers you define.
+
+<!-- NOTE(ignore) this example is specific to the msp430 target -->
+
+``` rust,ignore
+#![feature(abi_msp430_interrupt)]
+#![no_std]
+
+// Place the interrupt handler at the appropriate memory address
+// (Alternatively, you can use `#[used]` and remove `pub` and `#[no_mangle]`)
+#[link_section = "__interrupt_vector_10"]
+#[no_mangle]
+pub static TIM0_VECTOR: extern "msp430-interrupt" fn() = tim0;
+
+// The interrupt handler
+extern "msp430-interrupt" fn tim0() {
+ // ..
+}
+```
+
+``` text
+$ msp430-elf-objdump -CD ./target/msp430/release/app
+Disassembly of section __interrupt_vector_10:
+
+0000fff2 <TIM0_VECTOR>:
+ fff2: 00 c0 interrupt service routine at 0xc000
+
+Disassembly of section .text:
+
+0000c000 <int::tim0>:
+ c000: 00 13 reti
+```
diff --git a/src/doc/unstable-book/src/language-features/abi-ptx.md b/src/doc/unstable-book/src/language-features/abi-ptx.md
new file mode 100644
index 000000000..0ded3ceea
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/abi-ptx.md
@@ -0,0 +1,60 @@
+# `abi_ptx`
+
+The tracking issue for this feature is: [#38788]
+
+[#38788]: https://github.com/rust-lang/rust/issues/38788
+
+------------------------
+
+When emitting PTX code, all vanilla Rust functions (`fn`) get translated to
+"device" functions. These functions are *not* callable from the host via the
+CUDA API so a crate with only device functions is not too useful!
+
+OTOH, "global" functions *can* be called by the host; you can think of them
+as the real public API of your crate. To produce a global function use the
+`"ptx-kernel"` ABI.
+
+<!-- NOTE(ignore) this example is specific to the nvptx targets -->
+
+``` rust,ignore
+#![feature(abi_ptx)]
+#![no_std]
+
+pub unsafe extern "ptx-kernel" fn global_function() {
+ device_function();
+}
+
+pub fn device_function() {
+ // ..
+}
+```
+
+``` text
+$ xargo rustc --target nvptx64-nvidia-cuda --release -- --emit=asm
+
+$ cat $(find -name '*.s')
+//
+// Generated by LLVM NVPTX Back-End
+//
+
+.version 3.2
+.target sm_20
+.address_size 64
+
+ // .globl _ZN6kernel15global_function17h46111ebe6516b382E
+
+.visible .entry _ZN6kernel15global_function17h46111ebe6516b382E()
+{
+
+
+ ret;
+}
+
+ // .globl _ZN6kernel15device_function17hd6a0e4993bbf3f78E
+.visible .func _ZN6kernel15device_function17hd6a0e4993bbf3f78E()
+{
+
+
+ ret;
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/abi-thiscall.md b/src/doc/unstable-book/src/language-features/abi-thiscall.md
new file mode 100644
index 000000000..73bc6eacf
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/abi-thiscall.md
@@ -0,0 +1,12 @@
+# `abi_thiscall`
+
+The tracking issue for this feature is: [#42202]
+
+[#42202]: https://github.com/rust-lang/rust/issues/42202
+
+------------------------
+
+The MSVC ABI on x86 Windows uses the `thiscall` calling convention for C++
+instance methods by default; it is identical to the usual (C) calling
+convention on x86 Windows except that the first parameter of the method,
+the `this` pointer, is passed in the ECX register.
diff --git a/src/doc/unstable-book/src/language-features/allocator-internals.md b/src/doc/unstable-book/src/language-features/allocator-internals.md
new file mode 100644
index 000000000..2023d758f
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/allocator-internals.md
@@ -0,0 +1,7 @@
+# `allocator_internals`
+
+This feature does not have a tracking issue, it is an unstable implementation
+detail of the `global_allocator` feature not intended for use outside the
+compiler.
+
+------------------------
diff --git a/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md b/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md
new file mode 100644
index 000000000..e0bb78227
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md
@@ -0,0 +1,37 @@
+# `arbitrary_enum_discriminant`
+
+The tracking issue for this feature is: [#60553]
+
+[#60553]: https://github.com/rust-lang/rust/issues/60553
+
+------------------------
+
+The `arbitrary_enum_discriminant` feature permits tuple-like and
+struct-like enum variants with `#[repr(<int-type>)]` to have explicit discriminants.
+
+## Examples
+
+```rust
+#![feature(arbitrary_enum_discriminant)]
+
+#[allow(dead_code)]
+#[repr(u8)]
+enum Enum {
+ Unit = 3,
+ Tuple(u16) = 2,
+ Struct {
+ a: u8,
+ b: u16,
+ } = 1,
+}
+
+impl Enum {
+ fn tag(&self) -> u8 {
+ unsafe { *(self as *const Self as *const u8) }
+ }
+}
+
+assert_eq!(3, Enum::Unit.tag());
+assert_eq!(2, Enum::Tuple(5).tag());
+assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag());
+```
diff --git a/src/doc/unstable-book/src/language-features/asm-const.md b/src/doc/unstable-book/src/language-features/asm-const.md
new file mode 100644
index 000000000..670c4df41
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/asm-const.md
@@ -0,0 +1,11 @@
+# `asm_const`
+
+The tracking issue for this feature is: [#93332]
+
+[#93332]: https://github.com/rust-lang/rust/issues/93332
+
+------------------------
+
+This feature adds a `const <expr>` operand type to `asm!` and `global_asm!`.
+- `<expr>` must be an integer constant expression.
+- The value of the expression is formatted as a string and substituted directly into the asm template string.
diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
new file mode 100644
index 000000000..0a48eb4f8
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
@@ -0,0 +1,132 @@
+# `asm_experimental_arch`
+
+The tracking issue for this feature is: [#93335]
+
+[#93335]: https://github.com/rust-lang/rust/issues/93335
+
+------------------------
+
+This feature tracks `asm!` and `global_asm!` support for the following architectures:
+- NVPTX
+- PowerPC
+- Hexagon
+- MIPS32r2 and MIPS64r2
+- wasm32
+- BPF
+- SPIR-V
+- AVR
+- MSP430
+
+## Register classes
+
+| Architecture | Register class | Registers | LLVM constraint code |
+| ------------ | -------------- | ---------------------------------- | -------------------- |
+| MIPS | `reg` | `$[2-25]` | `r` |
+| MIPS | `freg` | `$f[0-31]` | `f` |
+| NVPTX | `reg16` | None\* | `h` |
+| NVPTX | `reg32` | None\* | `r` |
+| NVPTX | `reg64` | None\* | `l` |
+| Hexagon | `reg` | `r[0-28]` | `r` |
+| PowerPC | `reg` | `r[0-31]` | `r` |
+| PowerPC | `reg_nonzero` | `r[1-31]` | `b` |
+| PowerPC | `freg` | `f[0-31]` | `f` |
+| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers |
+| PowerPC | `xer` | `xer` | Only clobbers |
+| wasm32 | `local` | None\* | `r` |
+| BPF | `reg` | `r[0-10]` | `r` |
+| BPF | `wreg` | `w[0-10]` | `w` |
+| AVR | `reg` | `r[2-25]`, `XH`, `XL`, `ZH`, `ZL` | `r` |
+| AVR | `reg_upper` | `r[16-25]`, `XH`, `XL`, `ZH`, `ZL` | `d` |
+| AVR | `reg_pair` | `r3r2` .. `r25r24`, `X`, `Z` | `r` |
+| AVR | `reg_iw` | `r25r24`, `X`, `Z` | `w` |
+| AVR | `reg_ptr` | `X`, `Z` | `e` |
+| MSP430 | `reg` | `r[0-15]` | `r` |
+
+> **Notes**:
+> - NVPTX doesn't have a fixed register set, so named registers are not supported.
+>
+> - WebAssembly doesn't have registers, so named registers are not supported.
+
+# Register class supported types
+
+| Architecture | Register class | Target feature | Allowed types |
+| ------------ | ------------------------------- | -------------- | --------------------------------------- |
+| MIPS32 | `reg` | None | `i8`, `i16`, `i32`, `f32` |
+| MIPS32 | `freg` | None | `f32`, `f64` |
+| MIPS64 | `reg` | None | `i8`, `i16`, `i32`, `i64`, `f32`, `f64` |
+| MIPS64 | `freg` | None | `f32`, `f64` |
+| NVPTX | `reg16` | None | `i8`, `i16` |
+| NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` |
+| NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
+| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` |
+| PowerPC | `reg` | None | `i8`, `i16`, `i32` |
+| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
+| PowerPC | `freg` | None | `f32`, `f64` |
+| PowerPC | `cr` | N/A | Only clobbers |
+| PowerPC | `xer` | N/A | Only clobbers |
+| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
+| BPF | `reg` | None | `i8` `i16` `i32` `i64` |
+| BPF | `wreg` | `alu32` | `i8` `i16` `i32` |
+| AVR | `reg`, `reg_upper` | None | `i8` |
+| AVR | `reg_pair`, `reg_iw`, `reg_ptr` | None | `i16` |
+| MSP430 | `reg` | None | `i8`, `i16` |
+
+## Register aliases
+
+| Architecture | Base register | Aliases |
+| ------------ | ------------- | --------- |
+| Hexagon | `r29` | `sp` |
+| Hexagon | `r30` | `fr` |
+| Hexagon | `r31` | `lr` |
+| BPF | `r[0-10]` | `w[0-10]` |
+| AVR | `XH` | `r27` |
+| AVR | `XL` | `r26` |
+| AVR | `ZH` | `r31` |
+| AVR | `ZL` | `r30` |
+| MSP430 | `r0` | `pc` |
+| MSP430 | `r1` | `sp` |
+| MSP430 | `r2` | `sr` |
+| MSP430 | `r3` | `cg` |
+| MSP430 | `r4` | `fp` |
+
+> **Notes**:
+> - TI does not mandate a frame pointer for MSP430, but toolchains are allowed
+ to use one; LLVM uses `r4`.
+
+## Unsupported registers
+
+| Architecture | Unsupported register | Reason |
+| ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. |
+| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430) | The frame pointer cannot be used as an input or output. |
+| All | `r19` (Hexagon) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. |
+| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
+| MIPS | `$1` or `$at` | Reserved for assembler. |
+| MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. |
+| MIPS | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. |
+| MIPS | `$ra` | Return address cannot be used as inputs or outputs. |
+| Hexagon | `lr` | This is the link register which cannot be used as an input or output. |
+| AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. |
+|MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. |
+
+## Template modifiers
+
+| Architecture | Register class | Modifier | Example output | LLVM modifier |
+| ------------ | -------------- | -------- | -------------- | ------------- |
+| MIPS | `reg` | None | `$2` | None |
+| MIPS | `freg` | None | `$f0` | None |
+| NVPTX | `reg16` | None | `rs0` | None |
+| NVPTX | `reg32` | None | `r0` | None |
+| NVPTX | `reg64` | None | `rd0` | None |
+| Hexagon | `reg` | None | `r0` | None |
+| PowerPC | `reg` | None | `0` | None |
+| PowerPC | `reg_nonzero` | None | `3` | `b` |
+| PowerPC | `freg` | None | `0` | None |
+
+# Flags covered by `preserves_flags`
+
+These flags registers must be restored upon exiting the asm block if the `preserves_flags` option is set:
+- AVR
+ - The status register `SREG`.
+- MSP430
+ - The status register `r2`.
diff --git a/src/doc/unstable-book/src/language-features/asm-sym.md b/src/doc/unstable-book/src/language-features/asm-sym.md
new file mode 100644
index 000000000..103d91caf
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/asm-sym.md
@@ -0,0 +1,13 @@
+# `asm_sym`
+
+The tracking issue for this feature is: [#93333]
+
+[#93333]: https://github.com/rust-lang/rust/issues/93333
+
+------------------------
+
+This feature adds a `sym <path>` operand type to `asm!` and `global_asm!`.
+- `<path>` must refer to a `fn` or `static`.
+- A mangled symbol name referring to the item is substituted into the asm template string.
+- The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc).
+- `<path>` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data.
diff --git a/src/doc/unstable-book/src/language-features/asm-unwind.md b/src/doc/unstable-book/src/language-features/asm-unwind.md
new file mode 100644
index 000000000..809e6d75b
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/asm-unwind.md
@@ -0,0 +1,9 @@
+# `asm_unwind`
+
+The tracking issue for this feature is: [#93334]
+
+[#93334]: https://github.com/rust-lang/rust/issues/93334
+
+------------------------
+
+This feature adds a `may_unwind` option to `asm!` which allows an `asm` block to unwind stack and be part of the stack unwinding process. This option is only supported by the LLVM backend right now.
diff --git a/src/doc/unstable-book/src/language-features/auto-traits.md b/src/doc/unstable-book/src/language-features/auto-traits.md
new file mode 100644
index 000000000..f967c11fc
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/auto-traits.md
@@ -0,0 +1,106 @@
+# `auto_traits`
+
+The tracking issue for this feature is [#13231]
+
+[#13231]: https://github.com/rust-lang/rust/issues/13231
+
+----
+
+The `auto_traits` feature gate allows you to define auto traits.
+
+Auto traits, like [`Send`] or [`Sync`] in the standard library, are marker traits
+that are automatically implemented for every type, unless the type, or a type it contains,
+has explicitly opted out via a negative impl. (Negative impls are separately controlled
+by the `negative_impls` feature.)
+
+[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
+[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
+
+```rust,ignore (partial-example)
+impl !Trait for Type {}
+```
+
+Example:
+
+```rust
+#![feature(negative_impls)]
+#![feature(auto_traits)]
+
+auto trait Valid {}
+
+struct True;
+struct False;
+
+impl !Valid for False {}
+
+struct MaybeValid<T>(T);
+
+fn must_be_valid<T: Valid>(_t: T) { }
+
+fn main() {
+ // works
+ must_be_valid( MaybeValid(True) );
+
+ // compiler error - trait bound not satisfied
+ // must_be_valid( MaybeValid(False) );
+}
+```
+
+## Automatic trait implementations
+
+When a type is declared as an `auto trait`, we will automatically
+create impls for every struct/enum/union, unless an explicit impl is
+provided. These automatic impls contain a where clause for each field
+of the form `T: AutoTrait`, where `T` is the type of the field and
+`AutoTrait` is the auto trait in question. As an example, consider the
+struct `List` and the auto trait `Send`:
+
+```rust
+struct List<T> {
+ data: T,
+ next: Option<Box<List<T>>>,
+}
+```
+
+Presuming that there is no explicit impl of `Send` for `List`, the
+compiler will supply an automatic impl of the form:
+
+```rust
+struct List<T> {
+ data: T,
+ next: Option<Box<List<T>>>,
+}
+
+unsafe impl<T> Send for List<T>
+where
+ T: Send, // from the field `data`
+ Option<Box<List<T>>>: Send, // from the field `next`
+{ }
+```
+
+Explicit impls may be either positive or negative. They take the form:
+
+```rust,ignore (partial-example)
+impl<...> AutoTrait for StructName<..> { }
+impl<...> !AutoTrait for StructName<..> { }
+```
+
+## Coinduction: Auto traits permit cyclic matching
+
+Unlike ordinary trait matching, auto traits are **coinductive**. This
+means, in short, that cycles which occur in trait matching are
+considered ok. As an example, consider the recursive struct `List`
+introduced in the previous section. In attempting to determine whether
+`List: Send`, we would wind up in a cycle: to apply the impl, we must
+show that `Option<Box<List>>: Send`, which will in turn require
+`Box<List>: Send` and then finally `List: Send` again. Under ordinary
+trait matching, this cycle would be an error, but for an auto trait it
+is considered a successful match.
+
+## Items
+
+Auto traits cannot have any trait items, such as methods or associated types. This ensures that we can generate default implementations.
+
+## Supertraits
+
+Auto traits cannot have supertraits. This is for soundness reasons, as the interaction of coinduction with implied bounds is difficult to reconcile.
diff --git a/src/doc/unstable-book/src/language-features/box-patterns.md b/src/doc/unstable-book/src/language-features/box-patterns.md
new file mode 100644
index 000000000..584f4295c
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/box-patterns.md
@@ -0,0 +1,32 @@
+# `box_patterns`
+
+The tracking issue for this feature is: [#29641]
+
+[#29641]: https://github.com/rust-lang/rust/issues/29641
+
+See also [`box_syntax`](box-syntax.md)
+
+------------------------
+
+Box patterns let you match on `Box<T>`s:
+
+
+```rust
+#![feature(box_patterns)]
+
+fn main() {
+ let b = Some(Box::new(5));
+ match b {
+ Some(box n) if n < 0 => {
+ println!("Box contains negative number {n}");
+ },
+ Some(box n) if n >= 0 => {
+ println!("Box contains non-negative number {n}");
+ },
+ None => {
+ println!("No box");
+ },
+ _ => unreachable!()
+ }
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/box-syntax.md b/src/doc/unstable-book/src/language-features/box-syntax.md
new file mode 100644
index 000000000..9569974d2
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/box-syntax.md
@@ -0,0 +1,22 @@
+# `box_syntax`
+
+The tracking issue for this feature is: [#49733]
+
+[#49733]: https://github.com/rust-lang/rust/issues/49733
+
+See also [`box_patterns`](box-patterns.md)
+
+------------------------
+
+Currently the only stable way to create a `Box` is via the `Box::new` method.
+Also it is not possible in stable Rust to destructure a `Box` in a match
+pattern. The unstable `box` keyword can be used to create a `Box`. An example
+usage would be:
+
+```rust
+#![feature(box_syntax)]
+
+fn main() {
+ let b = box 5;
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/c-unwind.md b/src/doc/unstable-book/src/language-features/c-unwind.md
new file mode 100644
index 000000000..fb32918d5
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/c-unwind.md
@@ -0,0 +1,26 @@
+# `c_unwind`
+
+The tracking issue for this feature is: [#74990]
+
+[#74990]: https://github.com/rust-lang/rust/issues/74990
+
+------------------------
+
+Introduces new ABI strings:
+- "C-unwind"
+- "cdecl-unwind"
+- "stdcall-unwind"
+- "fastcall-unwind"
+- "vectorcall-unwind"
+- "thiscall-unwind"
+- "aapcs-unwind"
+- "win64-unwind"
+- "sysv64-unwind"
+- "system-unwind"
+
+These enable unwinding from other languages (such as C++) into Rust frames and
+from Rust into other languages.
+
+See [RFC 2945] for more information.
+
+[RFC 2945]: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md
diff --git a/src/doc/unstable-book/src/language-features/c-variadic.md b/src/doc/unstable-book/src/language-features/c-variadic.md
new file mode 100644
index 000000000..001c1bfa9
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/c-variadic.md
@@ -0,0 +1,24 @@
+# `c_variadic`
+
+The tracking issue for this feature is: [#44930]
+
+[#44930]: https://github.com/rust-lang/rust/issues/44930
+
+------------------------
+
+The `c_variadic` language feature enables C-variadic functions to be
+defined in Rust. They may be called both from within Rust and via FFI.
+
+## Examples
+
+```rust
+#![feature(c_variadic)]
+
+pub unsafe extern "C" fn add(n: usize, mut args: ...) -> usize {
+ let mut sum = 0;
+ for _ in 0..n {
+ sum += args.arg::<usize>();
+ }
+ sum
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/cfg-sanitize.md b/src/doc/unstable-book/src/language-features/cfg-sanitize.md
new file mode 100644
index 000000000..3442abf46
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/cfg-sanitize.md
@@ -0,0 +1,34 @@
+# `cfg_sanitize`
+
+The tracking issue for this feature is: [#39699]
+
+[#39699]: https://github.com/rust-lang/rust/issues/39699
+
+------------------------
+
+The `cfg_sanitize` feature makes it possible to execute different code
+depending on whether a particular sanitizer is enabled or not.
+
+## Examples
+
+```rust
+#![feature(cfg_sanitize)]
+
+#[cfg(sanitize = "thread")]
+fn a() {
+ // ...
+}
+
+#[cfg(not(sanitize = "thread"))]
+fn a() {
+ // ...
+}
+
+fn b() {
+ if cfg!(sanitize = "leak") {
+ // ...
+ } else {
+ // ...
+ }
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/cfg-version.md b/src/doc/unstable-book/src/language-features/cfg-version.md
new file mode 100644
index 000000000..a6ec42cec
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/cfg-version.md
@@ -0,0 +1,35 @@
+# `cfg_version`
+
+The tracking issue for this feature is: [#64796]
+
+[#64796]: https://github.com/rust-lang/rust/issues/64796
+
+------------------------
+
+The `cfg_version` feature makes it possible to execute different code
+depending on the compiler version. It will return true if the compiler
+version is greater than or equal to the specified version.
+
+## Examples
+
+```rust
+#![feature(cfg_version)]
+
+#[cfg(version("1.42"))] // 1.42 and above
+fn a() {
+ // ...
+}
+
+#[cfg(not(version("1.42")))] // 1.41 and below
+fn a() {
+ // ...
+}
+
+fn b() {
+ if cfg!(version("1.42")) {
+ // ...
+ } else {
+ // ...
+ }
+}
+```
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
new file mode 100644
index 000000000..c948810d3
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/closure-track-caller.md
@@ -0,0 +1,12 @@
+# `closure_track_caller`
+
+The tracking issue for this feature is: [#87417]
+
+[#87417]: https://github.com/rust-lang/rust/issues/87417
+
+------------------------
+
+Allows using the `#[track_caller]` attribute on closures and generators.
+Calls made to the closure or generator 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/cmse-nonsecure-entry.md b/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md
new file mode 100644
index 000000000..338fbc4b2
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md
@@ -0,0 +1,81 @@
+# `cmse_nonsecure_entry`
+
+The tracking issue for this feature is: [#75835]
+
+[#75835]: https://github.com/rust-lang/rust/issues/75835
+
+------------------------
+
+The [TrustZone-M
+feature](https://developer.arm.com/documentation/100690/latest/) is available
+for targets with the Armv8-M architecture profile (`thumbv8m` in their target
+name).
+LLVM, the Rust compiler and the linker are providing
+[support](https://developer.arm.com/documentation/ecm0359818/latest/) for the
+TrustZone-M feature.
+
+One of the things provided, with this unstable feature, is the
+`cmse_nonsecure_entry` attribute. This attribute marks a Secure function as an
+entry function (see [section
+5.4](https://developer.arm.com/documentation/ecm0359818/latest/) for details).
+With this attribute, the compiler will do the following:
+* add a special symbol on the function which is the `__acle_se_` prefix and the
+ standard function name
+* constrain the number of parameters to avoid using the Non-Secure stack
+* before returning from the function, clear registers that might contain Secure
+ information
+* use the `BXNS` instruction to return
+
+Because the stack can not be used to pass parameters, there will be compilation
+errors if:
+* the total size of all parameters is too big (for example more than four 32
+ bits integers)
+* the entry function is not using a C ABI
+
+The special symbol `__acle_se_` will be used by the linker to generate a secure
+gateway veneer.
+
+<!-- NOTE(ignore) this example is specific to thumbv8m targets -->
+
+``` rust,ignore
+#![feature(cmse_nonsecure_entry)]
+
+#[no_mangle]
+#[cmse_nonsecure_entry]
+pub extern "C" fn entry_function(input: u32) -> u32 {
+ input + 6
+}
+```
+
+``` text
+$ rustc --emit obj --crate-type lib --target thumbv8m.main-none-eabi function.rs
+$ arm-none-eabi-objdump -D function.o
+
+00000000 <entry_function>:
+ 0: b580 push {r7, lr}
+ 2: 466f mov r7, sp
+ 4: b082 sub sp, #8
+ 6: 9001 str r0, [sp, #4]
+ 8: 1d81 adds r1, r0, #6
+ a: 460a mov r2, r1
+ c: 4281 cmp r1, r0
+ e: 9200 str r2, [sp, #0]
+ 10: d30b bcc.n 2a <entry_function+0x2a>
+ 12: e7ff b.n 14 <entry_function+0x14>
+ 14: 9800 ldr r0, [sp, #0]
+ 16: b002 add sp, #8
+ 18: e8bd 4080 ldmia.w sp!, {r7, lr}
+ 1c: 4671 mov r1, lr
+ 1e: 4672 mov r2, lr
+ 20: 4673 mov r3, lr
+ 22: 46f4 mov ip, lr
+ 24: f38e 8800 msr CPSR_f, lr
+ 28: 4774 bxns lr
+ 2a: f240 0000 movw r0, #0
+ 2e: f2c0 0000 movt r0, #0
+ 32: f240 0200 movw r2, #0
+ 36: f2c0 0200 movt r2, #0
+ 3a: 211c movs r1, #28
+ 3c: f7ff fffe bl 0 <_ZN4core9panicking5panic17h5c028258ca2fb3f5E>
+ 40: defe udf #254 ; 0xfe
+```
diff --git a/src/doc/unstable-book/src/language-features/compiler-builtins.md b/src/doc/unstable-book/src/language-features/compiler-builtins.md
new file mode 100644
index 000000000..52fac575b
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/compiler-builtins.md
@@ -0,0 +1,5 @@
+# `compiler_builtins`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/language-features/const-eval-limit.md b/src/doc/unstable-book/src/language-features/const-eval-limit.md
new file mode 100644
index 000000000..df68e83bc
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/const-eval-limit.md
@@ -0,0 +1,7 @@
+# `const_eval_limit`
+
+The tracking issue for this feature is: [#67217]
+
+[#67217]: https://github.com/rust-lang/rust/issues/67217
+
+The `const_eval_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`.
diff --git a/src/doc/unstable-book/src/language-features/custom-test-frameworks.md b/src/doc/unstable-book/src/language-features/custom-test-frameworks.md
new file mode 100644
index 000000000..53ecac931
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/custom-test-frameworks.md
@@ -0,0 +1,32 @@
+# `custom_test_frameworks`
+
+The tracking issue for this feature is: [#50297]
+
+[#50297]: https://github.com/rust-lang/rust/issues/50297
+
+------------------------
+
+The `custom_test_frameworks` feature allows the use of `#[test_case]` and `#![test_runner]`.
+Any function, const, or static can be annotated with `#[test_case]` causing it to be aggregated (like `#[test]`)
+and be passed to the test runner determined by the `#![test_runner]` crate attribute.
+
+```rust
+#![feature(custom_test_frameworks)]
+#![test_runner(my_runner)]
+
+fn my_runner(tests: &[&i32]) {
+ for t in tests {
+ if **t == 0 {
+ println!("PASSED");
+ } else {
+ println!("FAILED");
+ }
+ }
+}
+
+#[test_case]
+const WILL_PASS: i32 = 0;
+
+#[test_case]
+const WILL_FAIL: i32 = 4;
+```
diff --git a/src/doc/unstable-book/src/language-features/debugger-visualizer.md b/src/doc/unstable-book/src/language-features/debugger-visualizer.md
new file mode 100644
index 000000000..c7a0414b6
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/debugger-visualizer.md
@@ -0,0 +1,27 @@
+# `debugger_visualizer`
+
+The tracking issue for this feature is: [#95939]
+
+[#95939]: https://github.com/rust-lang/rust/issues/95939
+
+------------------------
+
+The `debugger_visualizer` attribute can be used to instruct the compiler
+to embed a debugger visualizer file into the PDB/ELF generated by `rustc`.
+
+## Examples
+
+``` rust,ignore (partial-example)
+#![feature(debugger_visualizer)]
+#![debugger_visualizer(natvis_file = "foo.natvis")]
+#![debugger_visualizer(gdb_script_file = "foo.py")]
+struct Foo {
+
+}
+```
+
+## Limitations
+
+Currently, this feature only supports embedding Natvis files on `-windows-msvc`
+targets via the `natvis_file` meta item. `-windows-gnu` targets are not currently
+supported.
diff --git a/src/doc/unstable-book/src/language-features/doc-cfg.md b/src/doc/unstable-book/src/language-features/doc-cfg.md
new file mode 100644
index 000000000..b15f5ee66
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/doc-cfg.md
@@ -0,0 +1,46 @@
+# `doc_cfg`
+
+The tracking issue for this feature is: [#43781]
+
+------
+
+The `doc_cfg` feature allows an API be documented as only available in some specific platforms.
+This attribute has two effects:
+
+1. In the annotated item's documentation, there will be a message saying "Available on
+ (platform) only".
+
+2. The item's doc-tests will only run on the specific platform.
+
+In addition to allowing the use of the `#[doc(cfg)]` attribute, this feature enables the use of a
+special conditional compilation flag, `#[cfg(doc)]`, set whenever building documentation on your
+crate.
+
+This feature was introduced as part of PR [#43348] to allow the platform-specific parts of the
+standard library be documented.
+
+```rust
+#![feature(doc_cfg)]
+
+#[cfg(any(windows, doc))]
+#[doc(cfg(windows))]
+/// The application's icon in the notification area (a.k.a. system tray).
+///
+/// # Examples
+///
+/// ```no_run
+/// extern crate my_awesome_ui_library;
+/// use my_awesome_ui_library::current_app;
+/// use my_awesome_ui_library::windows::notification;
+///
+/// let icon = current_app().get::<notification::Icon>();
+/// icon.show();
+/// icon.show_message("Hello");
+/// ```
+pub struct Icon {
+ // ...
+}
+```
+
+[#43781]: https://github.com/rust-lang/rust/issues/43781
+[#43348]: https://github.com/rust-lang/rust/issues/43348
diff --git a/src/doc/unstable-book/src/language-features/doc-masked.md b/src/doc/unstable-book/src/language-features/doc-masked.md
new file mode 100644
index 000000000..609939bfc
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/doc-masked.md
@@ -0,0 +1,24 @@
+# `doc_masked`
+
+The tracking issue for this feature is: [#44027]
+
+-----
+
+The `doc_masked` feature allows a crate to exclude types from a given crate from appearing in lists
+of trait implementations. The specifics of the feature are as follows:
+
+1. When rustdoc encounters an `extern crate` statement annotated with a `#[doc(masked)]` attribute,
+ it marks the crate as being masked.
+
+2. When listing traits a given type implements, rustdoc ensures that traits from masked crates are
+ not emitted into the documentation.
+
+3. When listing types that implement a given trait, rustdoc ensures that types from masked crates
+ are not emitted into the documentation.
+
+This feature was introduced in PR [#44026] to ensure that compiler-internal and
+implementation-specific types and traits were not included in the standard library's documentation.
+Such types would introduce broken links into the documentation.
+
+[#44026]: https://github.com/rust-lang/rust/pull/44026
+[#44027]: https://github.com/rust-lang/rust/pull/44027
diff --git a/src/doc/unstable-book/src/language-features/doc-notable-trait.md b/src/doc/unstable-book/src/language-features/doc-notable-trait.md
new file mode 100644
index 000000000..dc402ed42
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/doc-notable-trait.md
@@ -0,0 +1,33 @@
+# `doc_notable_trait`
+
+The tracking issue for this feature is: [#45040]
+
+The `doc_notable_trait` feature allows the use of the `#[doc(notable_trait)]`
+attribute, which will display the trait in a "Notable traits" dialog for
+functions returning types that implement the trait. For example, this attribute
+is applied to the `Iterator`, `Future`, `io::Read`, and `io::Write` traits in
+the standard library.
+
+You can do this on your own traits like so:
+
+```
+#![feature(doc_notable_trait)]
+
+#[doc(notable_trait)]
+pub trait MyTrait {}
+
+pub struct MyStruct;
+impl MyTrait for MyStruct {}
+
+/// The docs for this function will have a button that displays a dialog about
+/// `MyStruct` implementing `MyTrait`.
+pub fn my_fn() -> MyStruct { MyStruct }
+```
+
+This feature was originally implemented in PR [#45039].
+
+See also its documentation in [the rustdoc book][rustdoc-book-notable_trait].
+
+[#45040]: https://github.com/rust-lang/rust/issues/45040
+[#45039]: https://github.com/rust-lang/rust/pull/45039
+[rustdoc-book-notable_trait]: ../../rustdoc/unstable-features.html#adding-your-trait-to-the-notable-traits-dialog
diff --git a/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md
new file mode 100644
index 000000000..d26512703
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/exclusive-range-pattern.md
@@ -0,0 +1,26 @@
+# `exclusive_range_pattern`
+
+The tracking issue for this feature is: [#37854].
+
+
+[#67264]: https://github.com/rust-lang/rust/issues/67264
+[#37854]: https://github.com/rust-lang/rust/issues/37854
+-----
+
+The `exclusive_range_pattern` feature allows non-inclusive range
+patterns (`0..10`) to be used in appropriate pattern matching
+contexts. It also can be combined with `#![feature(half_open_range_patterns]`
+to be able to use RangeTo patterns (`..10`).
+
+It also enabled RangeFrom patterns but that has since been
+stabilized.
+
+```rust
+#![feature(exclusive_range_pattern)]
+ let x = 5;
+ match x {
+ 0..10 => println!("single digit"),
+ 10 => println!("ten isn't part of the above range"),
+ _ => println!("nor is everything else.")
+ }
+```
diff --git a/src/doc/unstable-book/src/language-features/ffi-const.md b/src/doc/unstable-book/src/language-features/ffi-const.md
new file mode 100644
index 000000000..24a304437
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/ffi-const.md
@@ -0,0 +1,52 @@
+# `ffi_const`
+
+The tracking issue for this feature is: [#58328]
+
+------
+
+The `#[ffi_const]` attribute applies clang's `const` attribute to foreign
+functions declarations.
+
+That is, `#[ffi_const]` functions shall have no effects except for its return
+value, which can only depend on the values of the function parameters, and is
+not affected by changes to the observable state of the program.
+
+Applying the `#[ffi_const]` attribute to a function that violates these
+requirements is undefined behaviour.
+
+This attribute enables Rust to perform common optimizations, like sub-expression
+elimination, and it can avoid emitting some calls in repeated invocations of the
+function with the same argument values regardless of other operations being
+performed in between these functions calls (as opposed to `#[ffi_pure]`
+functions).
+
+## Pitfalls
+
+A `#[ffi_const]` function can only read global memory that would not affect
+its return value for the whole execution of the program (e.g. immutable global
+memory). `#[ffi_const]` functions are referentially-transparent and therefore
+more strict than `#[ffi_pure]` functions.
+
+A common pitfall involves applying the `#[ffi_const]` attribute to a
+function that reads memory through pointer arguments which do not necessarily
+point to immutable global memory.
+
+A `#[ffi_const]` function that returns unit has no effect on the abstract
+machine's state, and a `#[ffi_const]` function cannot be `#[ffi_pure]`.
+
+A `#[ffi_const]` function must not diverge, neither via a side effect (e.g. a
+call to `abort`) nor by infinite loops.
+
+When translating C headers to Rust FFI, it is worth verifying for which targets
+the `const` attribute is enabled in those headers, and using the appropriate
+`cfg` macros in the Rust side to match those definitions. While the semantics of
+`const` are implemented identically by many C and C++ compilers, e.g., clang,
+[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily
+implemented in this way on all of them. It is therefore also worth verifying
+that the semantics of the C toolchain used to compile the binary being linked
+against are compatible with those of the `#[ffi_const]`.
+
+[#58328]: https://github.com/rust-lang/rust/issues/58328
+[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacgigch.html
+[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute
+[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_const.htm
diff --git a/src/doc/unstable-book/src/language-features/ffi-pure.md b/src/doc/unstable-book/src/language-features/ffi-pure.md
new file mode 100644
index 000000000..236ccb9f9
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/ffi-pure.md
@@ -0,0 +1,56 @@
+# `ffi_pure`
+
+The tracking issue for this feature is: [#58329]
+
+------
+
+The `#[ffi_pure]` attribute applies clang's `pure` attribute to foreign
+functions declarations.
+
+That is, `#[ffi_pure]` functions shall have no effects except for its return
+value, which shall not change across two consecutive function calls with
+the same parameters.
+
+Applying the `#[ffi_pure]` attribute to a function that violates these
+requirements is undefined behavior.
+
+This attribute enables Rust to perform common optimizations, like sub-expression
+elimination and loop optimizations. Some common examples of pure functions are
+`strlen` or `memcmp`.
+
+These optimizations are only applicable when the compiler can prove that no
+program state observable by the `#[ffi_pure]` function has changed between calls
+of the function, which could alter the result. See also the `#[ffi_const]`
+attribute, which provides stronger guarantees regarding the allowable behavior
+of a function, enabling further optimization.
+
+## Pitfalls
+
+A `#[ffi_pure]` function can read global memory through the function
+parameters (e.g. pointers), globals, etc. `#[ffi_pure]` functions are not
+referentially-transparent, and are therefore more relaxed than `#[ffi_const]`
+functions.
+
+However, accessing global memory through volatile or atomic reads can violate the
+requirement that two consecutive function calls shall return the same value.
+
+A `pure` function that returns unit has no effect on the abstract machine's
+state.
+
+A `#[ffi_pure]` function must not diverge, neither via a side effect (e.g. a
+call to `abort`) nor by infinite loops.
+
+When translating C headers to Rust FFI, it is worth verifying for which targets
+the `pure` attribute is enabled in those headers, and using the appropriate
+`cfg` macros in the Rust side to match those definitions. While the semantics of
+`pure` are implemented identically by many C and C++ compilers, e.g., clang,
+[GCC], [ARM C/C++ compiler], [IBM ILE C/C++], etc. they are not necessarily
+implemented in this way on all of them. It is therefore also worth verifying
+that the semantics of the C toolchain used to compile the binary being linked
+against are compatible with those of the `#[ffi_pure]`.
+
+
+[#58329]: https://github.com/rust-lang/rust/issues/58329
+[ARM C/C++ compiler]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/Cacigdac.html
+[GCC]: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute
+[IBM ILE C/C++]: https://www.ibm.com/support/knowledgecenter/fr/ssw_ibm_i_71/rzarg/fn_attrib_pure.htm
diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md
new file mode 100644
index 000000000..7b865c9c6
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/generators.md
@@ -0,0 +1,246 @@
+# `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/half-open-range-patterns.md b/src/doc/unstable-book/src/language-features/half-open-range-patterns.md
new file mode 100644
index 000000000..3b16dd049
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/half-open-range-patterns.md
@@ -0,0 +1,27 @@
+# `half_open_range_patterns`
+
+The tracking issue for this feature is: [#67264]
+It is part of the `#![exclusive_range_pattern]` feature,
+tracked at [#37854].
+
+[#67264]: https://github.com/rust-lang/rust/issues/67264
+[#37854]: https://github.com/rust-lang/rust/issues/37854
+-----
+
+The `half_open_range_patterns` feature allows RangeTo patterns
+(`..10`) to be used in appropriate pattern matching contexts.
+This requires also enabling the `exclusive_range_pattern` feature.
+
+It also enabled RangeFrom patterns but that has since been
+stabilized.
+
+```rust
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
+ let x = 5;
+ match x {
+ ..0 => println!("negative!"), // "RangeTo" pattern. Unstable.
+ 0 => println!("zero!"),
+ 1.. => println!("positive!"), // "RangeFrom" pattern. Stable.
+ }
+```
diff --git a/src/doc/unstable-book/src/language-features/inline-const-pat.md b/src/doc/unstable-book/src/language-features/inline-const-pat.md
new file mode 100644
index 000000000..5f0f7547a
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/inline-const-pat.md
@@ -0,0 +1,24 @@
+# `inline_const_pat`
+
+The tracking issue for this feature is: [#76001]
+
+See also [`inline_const`](inline-const.md)
+
+------
+
+This feature allows you to use inline constant expressions in pattern position:
+
+```rust
+#![feature(inline_const_pat)]
+
+const fn one() -> i32 { 1 }
+
+let some_int = 3;
+match some_int {
+ const { 1 + 2 } => println!("Matched 1 + 2"),
+ const { one() } => println!("Matched const fn returning 1"),
+ _ => println!("Didn't match anything :("),
+}
+```
+
+[#76001]: https://github.com/rust-lang/rust/issues/76001
diff --git a/src/doc/unstable-book/src/language-features/inline-const.md b/src/doc/unstable-book/src/language-features/inline-const.md
new file mode 100644
index 000000000..7be70eed6
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/inline-const.md
@@ -0,0 +1,32 @@
+# `inline_const`
+
+The tracking issue for this feature is: [#76001]
+
+See also [`inline_const_pat`](inline-const-pat.md)
+
+------
+
+This feature allows you to use inline constant expressions. For example, you can
+turn this code:
+
+```rust
+# fn add_one(x: i32) -> i32 { x + 1 }
+const MY_COMPUTATION: i32 = 1 + 2 * 3 / 4;
+
+fn main() {
+ let x = add_one(MY_COMPUTATION);
+}
+```
+
+into this code:
+
+```rust
+#![feature(inline_const)]
+
+# fn add_one(x: i32) -> i32 { x + 1 }
+fn main() {
+ let x = add_one(const { 1 + 2 * 3 / 4 });
+}
+```
+
+[#76001]: https://github.com/rust-lang/rust/issues/76001
diff --git a/src/doc/unstable-book/src/language-features/intra-doc-pointers.md b/src/doc/unstable-book/src/language-features/intra-doc-pointers.md
new file mode 100644
index 000000000..fbc83f4b4
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/intra-doc-pointers.md
@@ -0,0 +1,15 @@
+# `intra-doc-pointers`
+
+The tracking issue for this feature is: [#80896]
+
+[#80896]: https://github.com/rust-lang/rust/issues/80896
+
+------------------------
+
+Rustdoc does not currently allow disambiguating between `*const` and `*mut`, and
+raw pointers in intra-doc links are unstable until it does.
+
+```rust
+#![feature(intra_doc_pointers)]
+//! [pointer::add]
+```
diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md
new file mode 100644
index 000000000..a0fb4e743
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/intrinsics.md
@@ -0,0 +1,29 @@
+# `intrinsics`
+
+The tracking issue for this feature is: None.
+
+Intrinsics are never intended to be stable directly, but intrinsics are often
+exported in some sort of stable manner. Prefer using the stable interfaces to
+the intrinsic directly when you can.
+
+------------------------
+
+
+These are imported as if they were FFI functions, with the special
+`rust-intrinsic` ABI. For example, if one was in a freestanding
+context, but wished to be able to `transmute` between types, and
+perform efficient pointer arithmetic, one would import those functions
+via a declaration like
+
+```rust
+#![feature(intrinsics)]
+# fn main() {}
+
+extern "rust-intrinsic" {
+ fn transmute<T, U>(x: T) -> U;
+
+ fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+```
+
+As with any other FFI functions, these are always `unsafe` to call.
diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md
new file mode 100644
index 000000000..39238dffa
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/lang-items.md
@@ -0,0 +1,297 @@
+# `lang_items`
+
+The tracking issue for this feature is: None.
+
+------------------------
+
+The `rustc` compiler has certain pluggable operations, that is,
+functionality that isn't hard-coded into the language, but is
+implemented in libraries, with a special marker to tell the compiler
+it exists. The marker is the attribute `#[lang = "..."]` and there are
+various different values of `...`, i.e. various different 'lang
+items'.
+
+For example, `Box` pointers require two lang items, one for allocation
+and one for deallocation. A freestanding program that uses the `Box`
+sugar for dynamic allocations via `malloc` and `free`:
+
+```rust,ignore (libc-is-finicky)
+#![feature(lang_items, box_syntax, start, libc, core_intrinsics, rustc_private)]
+#![no_std]
+use core::intrinsics;
+use core::panic::PanicInfo;
+
+extern crate libc;
+
+struct Unique<T>(*mut T);
+
+#[lang = "owned_box"]
+pub struct Box<T>(Unique<T>);
+
+#[lang = "exchange_malloc"]
+unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
+ let p = libc::malloc(size as libc::size_t) as *mut u8;
+
+ // Check if `malloc` failed:
+ if p as usize == 0 {
+ intrinsics::abort();
+ }
+
+ p
+}
+
+#[lang = "box_free"]
+unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
+ libc::free(ptr as *mut libc::c_void)
+}
+
+#[start]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+ let _x = box 1;
+
+ 0
+}
+
+#[lang = "eh_personality"] extern fn rust_eh_personality() {}
+#[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } }
+#[no_mangle] pub extern fn rust_eh_register_frames () {}
+#[no_mangle] pub extern fn rust_eh_unregister_frames () {}
+```
+
+Note the use of `abort`: the `exchange_malloc` lang item is assumed to
+return a valid pointer, and so needs to do the check internally.
+
+Other features provided by lang items include:
+
+- overloadable operators via traits: the traits corresponding to the
+ `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
+ marked with lang items; those specific four are `eq`, `ord`,
+ `deref`, and `add` respectively.
+- stack unwinding and general failure; the `eh_personality`,
+ `panic` and `panic_bounds_check` lang items.
+- the traits in `std::marker` used to indicate types of
+ various kinds; lang items `send`, `sync` and `copy`.
+- the marker types and variance indicators found in
+ `std::marker`; lang items `covariant_type`,
+ `contravariant_lifetime`, etc.
+
+Lang items are loaded lazily by the compiler; e.g. if one never uses
+`Box` then there is no need to define functions for `exchange_malloc`
+and `box_free`. `rustc` will emit an error when an item is needed
+but not found in the current crate or any that it depends on.
+
+Most lang items are defined by `libcore`, but if you're trying to build
+an executable without the standard library, you'll run into the need
+for lang items. The rest of this page focuses on this use-case, even though
+lang items are a bit broader than that.
+
+### Using libc
+
+In order to build a `#[no_std]` executable we will need libc as a dependency.
+We can specify this using our `Cargo.toml` file:
+
+```toml
+[dependencies]
+libc = { version = "0.2.14", default-features = false }
+```
+
+Note that the default features have been disabled. This is a critical step -
+**the default features of libc include the standard library and so must be
+disabled.**
+
+### Writing an executable without stdlib
+
+Controlling the entry point is possible in two ways: the `#[start]` attribute,
+or overriding the default shim for the C `main` function with your own.
+
+The function marked `#[start]` is passed the command line parameters
+in the same format as C:
+
+```rust,ignore (libc-is-finicky)
+#![feature(lang_items, core_intrinsics, rustc_private)]
+#![feature(start)]
+#![no_std]
+use core::intrinsics;
+use core::panic::PanicInfo;
+
+// Pull in the system libc library for what crt0.o likely requires.
+extern crate libc;
+
+// Entry point for this program.
+#[start]
+fn start(_argc: isize, _argv: *const *const u8) -> isize {
+ 0
+}
+
+// These functions are used by the compiler, but not
+// for a bare-bones hello world. These are normally
+// provided by libstd.
+#[lang = "eh_personality"]
+#[no_mangle]
+pub extern fn rust_eh_personality() {
+}
+
+#[lang = "panic_impl"]
+#[no_mangle]
+pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
+ unsafe { intrinsics::abort() }
+}
+```
+
+To override the compiler-inserted `main` shim, one has to disable it
+with `#![no_main]` and then create the appropriate symbol with the
+correct ABI and the correct name, which requires overriding the
+compiler's name mangling too:
+
+```rust,ignore (libc-is-finicky)
+#![feature(lang_items, core_intrinsics, rustc_private)]
+#![feature(start)]
+#![no_std]
+#![no_main]
+use core::intrinsics;
+use core::panic::PanicInfo;
+
+// Pull in the system libc library for what crt0.o likely requires.
+extern crate libc;
+
+// Entry point for this program.
+#[no_mangle] // ensure that this symbol is called `main` in the output
+pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
+ 0
+}
+
+// These functions are used by the compiler, but not
+// for a bare-bones hello world. These are normally
+// provided by libstd.
+#[lang = "eh_personality"]
+#[no_mangle]
+pub extern fn rust_eh_personality() {
+}
+
+#[lang = "panic_impl"]
+#[no_mangle]
+pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
+ unsafe { intrinsics::abort() }
+}
+```
+
+In many cases, you may need to manually link to the `compiler_builtins` crate
+when building a `no_std` binary. You may observe this via linker error messages
+such as "```undefined reference to `__rust_probestack'```".
+
+## More about the language items
+
+The compiler currently makes a few assumptions about symbols which are
+available in the executable to call. Normally these functions are provided by
+the standard library, but without it you must define your own. These symbols
+are called "language items", and they each have an internal name, and then a
+signature that an implementation must conform to.
+
+The first of these functions, `rust_eh_personality`, is used by the failure
+mechanisms of the compiler. This is often mapped to GCC's personality function
+(see the [libstd implementation][unwind] for more information), but crates
+which do not trigger a panic can be assured that this function is never
+called. The language item's name is `eh_personality`.
+
+[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs
+
+The second function, `rust_begin_panic`, is also used by the failure mechanisms of the
+compiler. When a panic happens, this controls the message that's displayed on
+the screen. While the language item's name is `panic_impl`, the symbol name is
+`rust_begin_panic`.
+
+Finally, a `eh_catch_typeinfo` static is needed for certain targets which
+implement Rust panics on top of C++ exceptions.
+
+## List of all language items
+
+This is a list of all language items in Rust along with where they are located in
+the source code.
+
+- Primitives
+ - `i8`: `libcore/num/mod.rs`
+ - `i16`: `libcore/num/mod.rs`
+ - `i32`: `libcore/num/mod.rs`
+ - `i64`: `libcore/num/mod.rs`
+ - `i128`: `libcore/num/mod.rs`
+ - `isize`: `libcore/num/mod.rs`
+ - `u8`: `libcore/num/mod.rs`
+ - `u16`: `libcore/num/mod.rs`
+ - `u32`: `libcore/num/mod.rs`
+ - `u64`: `libcore/num/mod.rs`
+ - `u128`: `libcore/num/mod.rs`
+ - `usize`: `libcore/num/mod.rs`
+ - `f32`: `libstd/f32.rs`
+ - `f64`: `libstd/f64.rs`
+ - `char`: `libcore/char.rs`
+ - `slice`: `liballoc/slice.rs`
+ - `str`: `liballoc/str.rs`
+ - `const_ptr`: `libcore/ptr.rs`
+ - `mut_ptr`: `libcore/ptr.rs`
+ - `unsafe_cell`: `libcore/cell.rs`
+- Runtime
+ - `start`: `libstd/rt.rs`
+ - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC)
+ - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU)
+ - `eh_personality`: `libpanic_unwind/seh.rs` (SEH)
+ - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC)
+ - `panic`: `libcore/panicking.rs`
+ - `panic_bounds_check`: `libcore/panicking.rs`
+ - `panic_impl`: `libcore/panicking.rs`
+ - `panic_impl`: `libstd/panicking.rs`
+- Allocations
+ - `owned_box`: `liballoc/boxed.rs`
+ - `exchange_malloc`: `liballoc/heap.rs`
+ - `box_free`: `liballoc/heap.rs`
+- Operands
+ - `not`: `libcore/ops/bit.rs`
+ - `bitand`: `libcore/ops/bit.rs`
+ - `bitor`: `libcore/ops/bit.rs`
+ - `bitxor`: `libcore/ops/bit.rs`
+ - `shl`: `libcore/ops/bit.rs`
+ - `shr`: `libcore/ops/bit.rs`
+ - `bitand_assign`: `libcore/ops/bit.rs`
+ - `bitor_assign`: `libcore/ops/bit.rs`
+ - `bitxor_assign`: `libcore/ops/bit.rs`
+ - `shl_assign`: `libcore/ops/bit.rs`
+ - `shr_assign`: `libcore/ops/bit.rs`
+ - `deref`: `libcore/ops/deref.rs`
+ - `deref_mut`: `libcore/ops/deref.rs`
+ - `index`: `libcore/ops/index.rs`
+ - `index_mut`: `libcore/ops/index.rs`
+ - `add`: `libcore/ops/arith.rs`
+ - `sub`: `libcore/ops/arith.rs`
+ - `mul`: `libcore/ops/arith.rs`
+ - `div`: `libcore/ops/arith.rs`
+ - `rem`: `libcore/ops/arith.rs`
+ - `neg`: `libcore/ops/arith.rs`
+ - `add_assign`: `libcore/ops/arith.rs`
+ - `sub_assign`: `libcore/ops/arith.rs`
+ - `mul_assign`: `libcore/ops/arith.rs`
+ - `div_assign`: `libcore/ops/arith.rs`
+ - `rem_assign`: `libcore/ops/arith.rs`
+ - `eq`: `libcore/cmp.rs`
+ - `ord`: `libcore/cmp.rs`
+- Functions
+ - `fn`: `libcore/ops/function.rs`
+ - `fn_mut`: `libcore/ops/function.rs`
+ - `fn_once`: `libcore/ops/function.rs`
+ - `generator_state`: `libcore/ops/generator.rs`
+ - `generator`: `libcore/ops/generator.rs`
+- Other
+ - `coerce_unsized`: `libcore/ops/unsize.rs`
+ - `drop`: `libcore/ops/drop.rs`
+ - `drop_in_place`: `libcore/ptr.rs`
+ - `clone`: `libcore/clone.rs`
+ - `copy`: `libcore/marker.rs`
+ - `send`: `libcore/marker.rs`
+ - `sized`: `libcore/marker.rs`
+ - `unsize`: `libcore/marker.rs`
+ - `sync`: `libcore/marker.rs`
+ - `phantom_data`: `libcore/marker.rs`
+ - `discriminant_kind`: `libcore/marker.rs`
+ - `freeze`: `libcore/marker.rs`
+ - `debug_trait`: `libcore/fmt/mod.rs`
+ - `non_zero`: `libcore/nonzero.rs`
+ - `arc`: `liballoc/sync.rs`
+ - `rc`: `liballoc/rc.rs`
diff --git a/src/doc/unstable-book/src/language-features/link-cfg.md b/src/doc/unstable-book/src/language-features/link-cfg.md
new file mode 100644
index 000000000..ee0fd5bf8
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/link-cfg.md
@@ -0,0 +1,5 @@
+# `link_cfg`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/language-features/marker-trait-attr.md b/src/doc/unstable-book/src/language-features/marker-trait-attr.md
new file mode 100644
index 000000000..be350cd61
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/marker-trait-attr.md
@@ -0,0 +1,35 @@
+# `marker_trait_attr`
+
+The tracking issue for this feature is: [#29864]
+
+[#29864]: https://github.com/rust-lang/rust/issues/29864
+
+------------------------
+
+Normally, Rust keeps you from adding trait implementations that could
+overlap with each other, as it would be ambiguous which to use. This
+feature, however, carves out an exception to that rule: a trait can
+opt-in to having overlapping implementations, at the cost that those
+implementations are not allowed to override anything (and thus the
+trait itself cannot have any associated items, as they're pointless
+when they'd need to do the same thing for every type anyway).
+
+```rust
+#![feature(marker_trait_attr)]
+
+#[marker] trait CheapToClone: Clone {}
+
+impl<T: Copy> CheapToClone for T {}
+
+// These could potentially overlap with the blanket implementation above,
+// so are only allowed because CheapToClone is a marker trait.
+impl<T: CheapToClone, U: CheapToClone> CheapToClone for (T, U) {}
+impl<T: CheapToClone> CheapToClone for std::ops::Range<T> {}
+
+fn cheap_clone<T: CheapToClone>(t: T) -> T {
+ t.clone()
+}
+```
+
+This is expected to replace the unstable `overlapping_marker_traits`
+feature, which applied to all empty traits (without needing an opt-in).
diff --git a/src/doc/unstable-book/src/language-features/more-qualified-paths.md b/src/doc/unstable-book/src/language-features/more-qualified-paths.md
new file mode 100644
index 000000000..857af577a
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/more-qualified-paths.md
@@ -0,0 +1,29 @@
+# `more_qualified_paths`
+
+The `more_qualified_paths` feature can be used in order to enable the
+use of qualified paths in patterns.
+
+## Example
+
+```rust
+#![feature(more_qualified_paths)]
+
+fn main() {
+ // destructure through a qualified path
+ let <Foo as A>::Assoc { br } = StructStruct { br: 2 };
+}
+
+struct StructStruct {
+ br: i8,
+}
+
+struct Foo;
+
+trait A {
+ type Assoc;
+}
+
+impl A for Foo {
+ type Assoc = StructStruct;
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/native-link-modifiers-as-needed.md b/src/doc/unstable-book/src/language-features/native-link-modifiers-as-needed.md
new file mode 100644
index 000000000..175767361
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/native-link-modifiers-as-needed.md
@@ -0,0 +1,18 @@
+# `native_link_modifiers_as_needed`
+
+The tracking issue for this feature is: [#81490]
+
+[#81490]: https://github.com/rust-lang/rust/issues/81490
+
+------------------------
+
+The `native_link_modifiers_as_needed` feature allows you to use the `as-needed` modifier.
+
+`as-needed` is only compatible with the `dynamic` and `framework` linking kinds. Using any other kind will result in a compiler error.
+
+`+as-needed` means that the library will be actually linked only if it satisfies some undefined symbols at the point at which it is specified on the command line, making it similar to static libraries in this regard.
+
+This modifier translates to `--as-needed` for ld-like linkers, and to `-dead_strip_dylibs` / `-needed_library` / `-needed_framework` for ld64.
+The modifier does nothing for linkers that don't support it (e.g. `link.exe`).
+
+The default for this modifier is unclear, some targets currently specify it as `+as-needed`, some do not. We may want to try making `+as-needed` a default for all targets.
diff --git a/src/doc/unstable-book/src/language-features/native-link-modifiers-verbatim.md b/src/doc/unstable-book/src/language-features/native-link-modifiers-verbatim.md
new file mode 100644
index 000000000..02bd87e50
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/native-link-modifiers-verbatim.md
@@ -0,0 +1,20 @@
+# `native_link_modifiers_verbatim`
+
+The tracking issue for this feature is: [#81490]
+
+[#81490]: https://github.com/rust-lang/rust/issues/81490
+
+------------------------
+
+The `native_link_modifiers_verbatim` feature allows you to use the `verbatim` modifier.
+
+`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes (like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the linker.
+
+For `ld`-like linkers rustc will use the `-l:filename` syntax (note the colon) when passing the library, so the linker won't add any prefixes or suffixes as well.
+See [`-l namespec`](https://sourceware.org/binutils/docs/ld/Options.html) in ld documentation for more details.
+For linkers not supporting any verbatim modifiers (e.g. `link.exe` or `ld64`) the library name will be passed as is.
+
+The default for this modifier is `-verbatim`.
+
+This RFC changes the behavior of `raw-dylib` linking kind specified by [RFC 2627](https://github.com/rust-lang/rfcs/pull/2627). The `.dll` suffix (or other target-specified suffixes for other targets) is now added automatically.
+If your DLL doesn't have the `.dll` suffix, it can be specified with `+verbatim`.
diff --git a/src/doc/unstable-book/src/language-features/negative-impls.md b/src/doc/unstable-book/src/language-features/negative-impls.md
new file mode 100644
index 000000000..151520f0e
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/negative-impls.md
@@ -0,0 +1,57 @@
+# `negative_impls`
+
+The tracking issue for this feature is [#68318].
+
+[#68318]: https://github.com/rust-lang/rust/issues/68318
+
+----
+
+With the feature gate `negative_impls`, you can write negative impls as well as positive ones:
+
+```rust
+#![feature(negative_impls)]
+trait DerefMut { }
+impl<T: ?Sized> !DerefMut for &T { }
+```
+
+Negative impls indicate a semver guarantee that the given trait will not be implemented for the given types. Negative impls play an additional purpose for auto traits, described below.
+
+Negative impls have the following characteristics:
+
+* They do not have any items.
+* They must obey the orphan rules as if they were a positive impl.
+* They cannot "overlap" with any positive impls.
+
+## Semver interaction
+
+It is a breaking change to remove a negative impl. Negative impls are a commitment not to implement the given trait for the named types.
+
+## Orphan and overlap rules
+
+Negative impls must obey the same orphan rules as a positive impl. This implies you cannot add a negative impl for types defined in upstream crates and so forth.
+
+Similarly, negative impls cannot overlap with positive impls, again using the same "overlap" check that we ordinarily use to determine if two impls overlap. (Note that positive impls typically cannot overlap with one another either, except as permitted by specialization.)
+
+## Interaction with auto traits
+
+Declaring a negative impl `impl !SomeAutoTrait for SomeType` for an
+auto-trait serves two purposes:
+
+* as with any trait, it declares that `SomeType` will never implement `SomeAutoTrait`;
+* it disables the automatic `SomeType: SomeAutoTrait` impl that would otherwise have been generated.
+
+Note that, at present, there is no way to indicate that a given type
+does not implement an auto trait *but that it may do so in the
+future*. For ordinary types, this is done by simply not declaring any
+impl at all, but that is not an option for auto traits. A workaround
+is that one could embed a marker type as one of the fields, where the
+marker type is `!AutoTrait`.
+
+## Immediate uses
+
+Negative impls are used to declare that `&T: !DerefMut` and `&mut T: !Clone`, as required to fix the soundness of `Pin` described in [#66544](https://github.com/rust-lang/rust/issues/66544).
+
+This serves two purposes:
+
+* For proving the correctness of unsafe code, we can use that impl as evidence that no `DerefMut` or `Clone` impl exists.
+* It prevents downstream crates from creating such impls.
diff --git a/src/doc/unstable-book/src/language-features/no-coverage.md b/src/doc/unstable-book/src/language-features/no-coverage.md
new file mode 100644
index 000000000..327cdb397
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/no-coverage.md
@@ -0,0 +1,30 @@
+# `no_coverage`
+
+The tracking issue for this feature is: [#84605]
+
+[#84605]: https://github.com/rust-lang/rust/issues/84605
+
+---
+
+The `no_coverage` attribute can be used to selectively disable coverage
+instrumentation in an annotated function. This might be useful to:
+
+- Avoid instrumentation overhead in a performance critical function
+- Avoid generating coverage for a function that is not meant to be executed,
+ but still target 100% coverage for the rest of the program.
+
+## Example
+
+```rust
+#![feature(no_coverage)]
+
+// `foo()` will get coverage instrumentation (by default)
+fn foo() {
+ // ...
+}
+
+#[no_coverage]
+fn bar() {
+ // ...
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/no-sanitize.md b/src/doc/unstable-book/src/language-features/no-sanitize.md
new file mode 100644
index 000000000..28c683934
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/no-sanitize.md
@@ -0,0 +1,29 @@
+# `no_sanitize`
+
+The tracking issue for this feature is: [#39699]
+
+[#39699]: https://github.com/rust-lang/rust/issues/39699
+
+------------------------
+
+The `no_sanitize` attribute can be used to selectively disable sanitizer
+instrumentation in an annotated function. This might be useful to: avoid
+instrumentation overhead in a performance critical function, or avoid
+instrumenting code that contains constructs unsupported by given sanitizer.
+
+The precise effect of this annotation depends on particular sanitizer in use.
+For example, with `no_sanitize(thread)`, the thread sanitizer will no longer
+instrument non-atomic store / load operations, but it will instrument atomic
+operations to avoid reporting false positives and provide meaning full stack
+traces.
+
+## Examples
+
+``` rust
+#![feature(no_sanitize)]
+
+#[no_sanitize(address)]
+fn foo() {
+ // ...
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md
new file mode 100644
index 000000000..56fe9a31b
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/plugin.md
@@ -0,0 +1,116 @@
+# `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/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs)
+that warns about any item named `lintme`.
+
+```rust,ignore (requires-stage-2)
+#![feature(box_syntax, rustc_private)]
+
+extern crate rustc_ast;
+
+// Load rustc as a plugin to get macros
+extern crate rustc_driver;
+#[macro_use]
+extern crate rustc_lint;
+#[macro_use]
+extern crate rustc_session;
+
+use rustc_driver::plugin::Registry;
+use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
+use rustc_ast::ast;
+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, |lint| {
+ lint.build("item is named 'lintme'").set_span(it.span).emit()
+ });
+ }
+ }
+}
+
+#[no_mangle]
+fn __rustc_plugin_registrar(reg: &mut Registry) {
+ reg.lint_store.register_lints(&[&TEST_LINT]);
+ reg.lint_store.register_early_pass(|| box 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/profiler-runtime.md b/src/doc/unstable-book/src/language-features/profiler-runtime.md
new file mode 100644
index 000000000..aee86f639
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/profiler-runtime.md
@@ -0,0 +1,5 @@
+# `profiler_runtime`
+
+The tracking issue for this feature is: [#42524](https://github.com/rust-lang/rust/issues/42524).
+
+------------------------
diff --git a/src/doc/unstable-book/src/language-features/raw-dylib.md b/src/doc/unstable-book/src/language-features/raw-dylib.md
new file mode 100644
index 000000000..23fc5b305
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/raw-dylib.md
@@ -0,0 +1,34 @@
+# `raw_dylib`
+
+The tracking issue for this feature is: [#58713]
+
+[#58713]: https://github.com/rust-lang/rust/issues/58713
+
+------------------------
+
+The `raw_dylib` feature allows you to link against the implementations of functions in an `extern`
+block without, on Windows, linking against an import library.
+
+```rust,ignore (partial-example)
+#![feature(raw_dylib)]
+
+#[link(name="library", kind="raw-dylib")]
+extern {
+ fn extern_function(x: i32);
+}
+
+fn main() {
+ unsafe {
+ extern_function(14);
+ }
+}
+```
+
+## Limitations
+
+Currently, this feature is only supported on `-windows-msvc` targets. Non-Windows platforms don't have import
+libraries, and an incompatibility between LLVM and the BFD linker means that it is not currently supported on
+`-windows-gnu` targets.
+
+On the `i686-pc-windows-msvc` target, this feature supports only the `cdecl`, `stdcall`, `system`, and `fastcall`
+calling conventions.
diff --git a/src/doc/unstable-book/src/language-features/repr128.md b/src/doc/unstable-book/src/language-features/repr128.md
new file mode 100644
index 000000000..146f50ee6
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/repr128.md
@@ -0,0 +1,18 @@
+# `repr128`
+
+The tracking issue for this feature is: [#56071]
+
+[#56071]: https://github.com/rust-lang/rust/issues/56071
+
+------------------------
+
+The `repr128` feature adds support for `#[repr(u128)]` on `enum`s.
+
+```rust
+#![feature(repr128)]
+
+#[repr(u128)]
+enum Foo {
+ Bar(u64),
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/rustc-attrs.md b/src/doc/unstable-book/src/language-features/rustc-attrs.md
new file mode 100644
index 000000000..c67b806f0
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/rustc-attrs.md
@@ -0,0 +1,53 @@
+# `rustc_attrs`
+
+This feature has no tracking issue, and is therefore internal to
+the compiler, not being intended for general use.
+
+Note: `rustc_attrs` enables many rustc-internal attributes and this page
+only discuss a few of them.
+
+------------------------
+
+The `rustc_attrs` feature allows debugging rustc type layouts by using
+`#[rustc_layout(...)]` to debug layout at compile time (it even works
+with `cargo check`) as an alternative to `rustc -Z print-type-sizes`
+that is way more verbose.
+
+Options provided by `#[rustc_layout(...)]` are `debug`, `size`, `align`,
+`abi`. Note that it only works on sized types without generics.
+
+## Examples
+
+```rust,compile_fail
+#![feature(rustc_attrs)]
+
+#[rustc_layout(abi, size)]
+pub enum X {
+ Y(u8, u8, u8),
+ Z(isize),
+}
+```
+
+When that is compiled, the compiler will error with something like
+
+```text
+error: abi: Aggregate { sized: true }
+ --> src/lib.rs:4:1
+ |
+4 | / pub enum T {
+5 | | Y(u8, u8, u8),
+6 | | Z(isize),
+7 | | }
+ | |_^
+
+error: size: Size { raw: 16 }
+ --> src/lib.rs:4:1
+ |
+4 | / pub enum T {
+5 | | Y(u8, u8, u8),
+6 | | Z(isize),
+7 | | }
+ | |_^
+
+error: aborting due to 2 previous errors
+```
diff --git a/src/doc/unstable-book/src/language-features/strict-provenance.md b/src/doc/unstable-book/src/language-features/strict-provenance.md
new file mode 100644
index 000000000..dc60f3f37
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/strict-provenance.md
@@ -0,0 +1,22 @@
+# `strict_provenance`
+
+The tracking issue for this feature is: [#95228]
+
+[#95228]: https://github.com/rust-lang/rust/issues/95228
+-----
+
+The `strict_provenance` feature allows to enable the `fuzzy_provenance_casts` and `lossy_provenance_casts` lints.
+These lint on casts between integers and pointers, that are recommended against or invalid in the strict provenance model.
+The same feature gate is also used for the experimental strict provenance API in `std` (actually `core`).
+
+## Example
+
+```rust
+#![feature(strict_provenance)]
+#![warn(fuzzy_provenance_casts)]
+
+fn main() {
+ let _dangling = 16_usize as *const u8;
+ //~^ WARNING: strict provenance disallows casting integer `usize` to pointer `*const u8`
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/trait-alias.md b/src/doc/unstable-book/src/language-features/trait-alias.md
new file mode 100644
index 000000000..f1be053dd
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/trait-alias.md
@@ -0,0 +1,34 @@
+# `trait_alias`
+
+The tracking issue for this feature is: [#41517]
+
+[#41517]: https://github.com/rust-lang/rust/issues/41517
+
+------------------------
+
+The `trait_alias` feature adds support for trait aliases. These allow aliases
+to be created for one or more traits (currently just a single regular trait plus
+any number of auto-traits), and used wherever traits would normally be used as
+either bounds or trait objects.
+
+```rust
+#![feature(trait_alias)]
+
+trait Foo = std::fmt::Debug + Send;
+trait Bar = Foo + Sync;
+
+// Use trait alias as bound on type parameter.
+fn foo<T: Foo>(v: &T) {
+ println!("{:?}", v);
+}
+
+pub fn main() {
+ foo(&1);
+
+ // Use trait alias for trait objects.
+ let a: &Bar = &123;
+ println!("{:?}", a);
+ let b = Box::new(456) as Box<dyn Foo>;
+ println!("{:?}", b);
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/trait-upcasting.md b/src/doc/unstable-book/src/language-features/trait-upcasting.md
new file mode 100644
index 000000000..3697ae38f
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/trait-upcasting.md
@@ -0,0 +1,27 @@
+# `trait_upcasting`
+
+The tracking issue for this feature is: [#65991]
+
+[#65991]: https://github.com/rust-lang/rust/issues/65991
+
+------------------------
+
+The `trait_upcasting` feature adds support for trait upcasting coercion. This allows a
+trait object of type `dyn Bar` to be cast to a trait object of type `dyn Foo`
+so long as `Bar: Foo`.
+
+```rust,edition2018
+#![feature(trait_upcasting)]
+#![allow(incomplete_features)]
+
+trait Foo {}
+
+trait Bar: Foo {}
+
+impl Foo for i32 {}
+
+impl<T: Foo + ?Sized> Bar for T {}
+
+let bar: &dyn Bar = &123;
+let foo: &dyn Foo = bar;
+```
diff --git a/src/doc/unstable-book/src/language-features/transparent-unions.md b/src/doc/unstable-book/src/language-features/transparent-unions.md
new file mode 100644
index 000000000..9b39b8971
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/transparent-unions.md
@@ -0,0 +1,83 @@
+# `transparent_unions`
+
+The tracking issue for this feature is [#60405]
+
+[#60405]: https://github.com/rust-lang/rust/issues/60405
+
+----
+
+The `transparent_unions` feature allows you mark `union`s as
+`#[repr(transparent)]`. A `union` may be `#[repr(transparent)]` in exactly the
+same conditions in which a `struct` may be `#[repr(transparent)]` (generally,
+this means the `union` must have exactly one non-zero-sized field). Some
+concrete illustrations follow.
+
+```rust
+#![feature(transparent_unions)]
+
+// This union has the same representation as `f32`.
+#[repr(transparent)]
+union SingleFieldUnion {
+ field: f32,
+}
+
+// This union has the same representation as `usize`.
+#[repr(transparent)]
+union MultiFieldUnion {
+ field: usize,
+ nothing: (),
+}
+```
+
+For consistency with transparent `struct`s, `union`s must have exactly one
+non-zero-sized field. If all fields are zero-sized, the `union` must not be
+`#[repr(transparent)]`:
+
+```rust
+#![feature(transparent_unions)]
+
+// This (non-transparent) union is already valid in stable Rust:
+pub union GoodUnion {
+ pub nothing: (),
+}
+
+// Error: transparent union needs exactly one non-zero-sized field, but has 0
+// #[repr(transparent)]
+// pub union BadUnion {
+// pub nothing: (),
+// }
+```
+
+The one exception is if the `union` is generic over `T` and has a field of type
+`T`, it may be `#[repr(transparent)]` even if `T` is a zero-sized type:
+
+```rust
+#![feature(transparent_unions)]
+
+// This union has the same representation as `T`.
+#[repr(transparent)]
+pub union GenericUnion<T: Copy> { // Unions with non-`Copy` fields are unstable.
+ pub field: T,
+ pub nothing: (),
+}
+
+// This is okay even though `()` is a zero-sized type.
+pub const THIS_IS_OKAY: GenericUnion<()> = GenericUnion { field: () };
+```
+
+Like transarent `struct`s, a transparent `union` of type `U` has the same
+layout, size, and ABI as its single non-ZST field. If it is generic over a type
+`T`, and all its fields are ZSTs except for exactly one field of type `T`, then
+it has the same layout and ABI as `T` (even if `T` is a ZST when monomorphized).
+
+Like transparent `struct`s, transparent `union`s are FFI-safe if and only if
+their underlying representation type is also FFI-safe.
+
+A `union` may not be eligible for the same nonnull-style optimizations that a
+`struct` or `enum` (with the same fields) are eligible for. Adding
+`#[repr(transparent)]` to `union` does not change this. To give a more concrete
+example, it is unspecified whether `size_of::<T>()` is equal to
+`size_of::<Option<T>>()`, where `T` is a `union` (regardless of whether or not
+it is transparent). The Rust compiler is free to perform this optimization if
+possible, but is not required to, and different compiler versions may differ in
+their application of these optimizations.
diff --git a/src/doc/unstable-book/src/language-features/try-blocks.md b/src/doc/unstable-book/src/language-features/try-blocks.md
new file mode 100644
index 000000000..e342c260a
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/try-blocks.md
@@ -0,0 +1,30 @@
+# `try_blocks`
+
+The tracking issue for this feature is: [#31436]
+
+[#31436]: https://github.com/rust-lang/rust/issues/31436
+
+------------------------
+
+The `try_blocks` feature adds support for `try` blocks. A `try`
+block creates a new scope one can use the `?` operator in.
+
+```rust,edition2018
+#![feature(try_blocks)]
+
+use std::num::ParseIntError;
+
+let result: Result<i32, ParseIntError> = try {
+ "1".parse::<i32>()?
+ + "2".parse::<i32>()?
+ + "3".parse::<i32>()?
+};
+assert_eq!(result, Ok(6));
+
+let result: Result<i32, ParseIntError> = try {
+ "1".parse::<i32>()?
+ + "foo".parse::<i32>()?
+ + "3".parse::<i32>()?
+};
+assert!(result.is_err());
+```
diff --git a/src/doc/unstable-book/src/language-features/type-changing-struct-update.md b/src/doc/unstable-book/src/language-features/type-changing-struct-update.md
new file mode 100644
index 000000000..9909cf35b
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/type-changing-struct-update.md
@@ -0,0 +1,33 @@
+# `type_changing_struct_update`
+
+The tracking issue for this feature is: [#86555]
+
+[#86555]: https://github.com/rust-lang/rust/issues/86555
+
+------------------------
+
+This implements [RFC2528]. When turned on, you can create instances of the same struct
+that have different generic type or lifetime parameters.
+
+[RFC2528]: https://github.com/rust-lang/rfcs/blob/master/text/2528-type-changing-struct-update-syntax.md
+
+```rust
+#![allow(unused_variables, dead_code)]
+#![feature(type_changing_struct_update)]
+
+fn main () {
+ struct Foo<T, U> {
+ field1: T,
+ field2: U,
+ }
+
+ let base: Foo<String, i32> = Foo {
+ field1: String::from("hello"),
+ field2: 1234,
+ };
+ let updated: Foo<f64, i32> = Foo {
+ field1: 3.14,
+ ..base
+ };
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/unboxed-closures.md b/src/doc/unstable-book/src/language-features/unboxed-closures.md
new file mode 100644
index 000000000..e4113d72d
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/unboxed-closures.md
@@ -0,0 +1,25 @@
+# `unboxed_closures`
+
+The tracking issue for this feature is [#29625]
+
+See Also: [`fn_traits`](../library-features/fn-traits.md)
+
+[#29625]: https://github.com/rust-lang/rust/issues/29625
+
+----
+
+The `unboxed_closures` feature allows you to write functions using the `"rust-call"` ABI,
+required for implementing the [`Fn*`] family of traits. `"rust-call"` functions must have
+exactly one (non self) argument, a tuple representing the argument list.
+
+[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
+
+```rust
+#![feature(unboxed_closures)]
+
+extern "rust-call" fn add_args(args: (u32, u32)) -> u32 {
+ args.0 + args.1
+}
+
+fn main() {}
+```
diff --git a/src/doc/unstable-book/src/language-features/unsized-locals.md b/src/doc/unstable-book/src/language-features/unsized-locals.md
new file mode 100644
index 000000000..d5b01a3d6
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/unsized-locals.md
@@ -0,0 +1,175 @@
+# `unsized_locals`
+
+The tracking issue for this feature is: [#48055]
+
+[#48055]: https://github.com/rust-lang/rust/issues/48055
+
+------------------------
+
+This implements [RFC1909]. When turned on, you can have unsized arguments and locals:
+
+[RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-unsized-rvalues.md
+
+```rust
+#![allow(incomplete_features)]
+#![feature(unsized_locals, unsized_fn_params)]
+
+use std::any::Any;
+
+fn main() {
+ let x: Box<dyn Any> = Box::new(42);
+ let x: dyn Any = *x;
+ // ^ unsized local variable
+ // ^^ unsized temporary
+ foo(x);
+}
+
+fn foo(_: dyn Any) {}
+// ^^^^^^ unsized argument
+```
+
+The RFC still forbids the following unsized expressions:
+
+```rust,compile_fail
+#![feature(unsized_locals)]
+
+use std::any::Any;
+
+struct MyStruct<T: ?Sized> {
+ content: T,
+}
+
+struct MyTupleStruct<T: ?Sized>(T);
+
+fn answer() -> Box<dyn Any> {
+ Box::new(42)
+}
+
+fn main() {
+ // You CANNOT have unsized statics.
+ static X: dyn Any = *answer(); // ERROR
+ const Y: dyn Any = *answer(); // ERROR
+
+ // You CANNOT have struct initialized unsized.
+ MyStruct { content: *answer() }; // ERROR
+ MyTupleStruct(*answer()); // ERROR
+ (42, *answer()); // ERROR
+
+ // You CANNOT have unsized return types.
+ fn my_function() -> dyn Any { *answer() } // ERROR
+
+ // You CAN have unsized local variables...
+ let mut x: dyn Any = *answer(); // OK
+ // ...but you CANNOT reassign to them.
+ x = *answer(); // ERROR
+
+ // You CANNOT even initialize them separately.
+ let y: dyn Any; // OK
+ y = *answer(); // ERROR
+
+ // Not mentioned in the RFC, but by-move captured variables are also Sized.
+ let x: dyn Any = *answer();
+ (move || { // ERROR
+ let y = x;
+ })();
+
+ // You CAN create a closure with unsized arguments,
+ // but you CANNOT call it.
+ // This is an implementation detail and may be changed in the future.
+ let f = |x: dyn Any| {};
+ f(*answer()); // ERROR
+}
+```
+
+## By-value trait objects
+
+With this feature, you can have by-value `self` arguments without `Self: Sized` bounds.
+
+```rust
+#![feature(unsized_fn_params)]
+
+trait Foo {
+ fn foo(self) {}
+}
+
+impl<T: ?Sized> Foo for T {}
+
+fn main() {
+ let slice: Box<[i32]> = Box::new([1, 2, 3]);
+ <[i32] as Foo>::foo(*slice);
+}
+```
+
+And `Foo` will also be object-safe.
+
+```rust
+#![feature(unsized_fn_params)]
+
+trait Foo {
+ fn foo(self) {}
+}
+
+impl<T: ?Sized> Foo for T {}
+
+fn main () {
+ let slice: Box<dyn Foo> = Box::new([1, 2, 3]);
+ // doesn't compile yet
+ <dyn Foo as Foo>::foo(*slice);
+}
+```
+
+One of the objectives of this feature is to allow `Box<dyn FnOnce>`.
+
+## Variable length arrays
+
+The RFC also describes an extension to the array literal syntax: `[e; dyn n]`. In the syntax, `n` isn't necessarily a constant expression. The array is dynamically allocated on the stack and has the type of `[T]`, instead of `[T; n]`.
+
+```rust,ignore (not-yet-implemented)
+#![feature(unsized_locals)]
+
+fn mergesort<T: Ord>(a: &mut [T]) {
+ let mut tmp = [T; dyn a.len()];
+ // ...
+}
+
+fn main() {
+ let mut a = [3, 1, 5, 6];
+ mergesort(&mut a);
+ assert_eq!(a, [1, 3, 5, 6]);
+}
+```
+
+VLAs are not implemented yet. The syntax isn't final, either. We may need an alternative syntax for Rust 2015 because, in Rust 2015, expressions like `[e; dyn(1)]` would be ambiguous. One possible alternative proposed in the RFC is `[e; n]`: if `n` captures one or more local variables, then it is considered as `[e; dyn n]`.
+
+## Advisory on stack usage
+
+It's advised not to casually use the `#![feature(unsized_locals)]` feature. Typical use-cases are:
+
+- When you need a by-value trait objects.
+- When you really need a fast allocation of small temporary arrays.
+
+Another pitfall is repetitive allocation and temporaries. Currently the compiler simply extends the stack frame every time it encounters an unsized assignment. So for example, the code
+
+```rust
+#![feature(unsized_locals)]
+
+fn main() {
+ let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]);
+ let _x = {{{{{{{{{{*x}}}}}}}}}};
+}
+```
+
+and the code
+
+```rust
+#![feature(unsized_locals)]
+
+fn main() {
+ for _ in 0..10 {
+ let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]);
+ let _x = *x;
+ }
+}
+```
+
+will unnecessarily extend the stack frame.
diff --git a/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md
new file mode 100644
index 000000000..310c8d962
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md
@@ -0,0 +1,27 @@
+# `unsized_tuple_coercion`
+
+The tracking issue for this feature is: [#42877]
+
+[#42877]: https://github.com/rust-lang/rust/issues/42877
+
+------------------------
+
+This is a part of [RFC0401]. According to the RFC, there should be an implementation like this:
+
+```rust,ignore (partial-example)
+impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized<U> {}
+```
+
+This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this:
+
+```rust
+#![feature(unsized_tuple_coercion)]
+
+fn main() {
+ let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]);
+ let y : &([i32; 3], [i32]) = &x;
+ assert_eq!(y.1[0], 4);
+}
+```
+
+[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
diff --git a/src/doc/unstable-book/src/language-features/yeet-expr.md b/src/doc/unstable-book/src/language-features/yeet-expr.md
new file mode 100644
index 000000000..bc1ba4c91
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/yeet-expr.md
@@ -0,0 +1,26 @@
+# `yeet_expr`
+
+The tracking issue for this feature is: [#96373]
+
+[#96373]: https://github.com/rust-lang/rust/issues/96373
+
+------------------------
+
+The `yeet_expr` feature adds support for `do yeet` expressions,
+which can be used to early-exit from a function or `try` block.
+
+These are highly experimental, thus the placeholder syntax.
+
+```rust,edition2021
+#![feature(yeet_expr)]
+
+fn foo() -> Result<String, i32> {
+ do yeet 4;
+}
+assert_eq!(foo(), Err(4));
+
+fn bar() -> Option<String> {
+ do yeet;
+}
+assert_eq!(bar(), None);
+```
diff --git a/src/doc/unstable-book/src/library-features.md b/src/doc/unstable-book/src/library-features.md
new file mode 100644
index 000000000..9f537e261
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features.md
@@ -0,0 +1 @@
+# Library Features
diff --git a/src/doc/unstable-book/src/library-features/allocator-api.md b/src/doc/unstable-book/src/library-features/allocator-api.md
new file mode 100644
index 000000000..9f045ce08
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/allocator-api.md
@@ -0,0 +1,15 @@
+# `allocator_api`
+
+The tracking issue for this feature is [#32838]
+
+[#32838]: https://github.com/rust-lang/rust/issues/32838
+
+------------------------
+
+Sometimes you want the memory for one collection to use a different
+allocator than the memory for another collection. In this case,
+replacing the global allocator is not a workable option. Instead,
+you need to pass in an instance of an `AllocRef` to each collection
+for which you want a custom allocator.
+
+TBD
diff --git a/src/doc/unstable-book/src/library-features/c-variadic.md b/src/doc/unstable-book/src/library-features/c-variadic.md
new file mode 100644
index 000000000..77762116e
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/c-variadic.md
@@ -0,0 +1,26 @@
+# `c_variadic`
+
+The tracking issue for this feature is: [#44930]
+
+[#44930]: https://github.com/rust-lang/rust/issues/44930
+
+------------------------
+
+The `c_variadic` library feature exposes the `VaList` structure,
+Rust's analogue of C's `va_list` type.
+
+## Examples
+
+```rust
+#![feature(c_variadic)]
+
+use std::ffi::VaList;
+
+pub unsafe extern "C" fn vadd(n: usize, mut args: VaList) -> usize {
+ let mut sum = 0;
+ for _ in 0..n {
+ sum += args.arg::<usize>();
+ }
+ sum
+}
+```
diff --git a/src/doc/unstable-book/src/library-features/c-void-variant.md b/src/doc/unstable-book/src/library-features/c-void-variant.md
new file mode 100644
index 000000000..a2fdc9936
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/c-void-variant.md
@@ -0,0 +1,5 @@
+# `c_void_variant`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/char-error-internals.md b/src/doc/unstable-book/src/library-features/char-error-internals.md
new file mode 100644
index 000000000..8013b4988
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/char-error-internals.md
@@ -0,0 +1,5 @@
+# `char_error_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/concat-idents.md b/src/doc/unstable-book/src/library-features/concat-idents.md
new file mode 100644
index 000000000..73f6cfa21
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/concat-idents.md
@@ -0,0 +1,22 @@
+# `concat_idents`
+
+The tracking issue for this feature is: [#29599]
+
+[#29599]: https://github.com/rust-lang/rust/issues/29599
+
+------------------------
+
+The `concat_idents` feature adds a macro for concatenating multiple identifiers
+into one identifier.
+
+## Examples
+
+```rust
+#![feature(concat_idents)]
+
+fn main() {
+ fn foobar() -> u32 { 23 }
+ let f = concat_idents!(foo, bar);
+ assert_eq!(f(), 23);
+}
+```
diff --git a/src/doc/unstable-book/src/library-features/core-intrinsics.md b/src/doc/unstable-book/src/library-features/core-intrinsics.md
new file mode 100644
index 000000000..28ad3525e
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/core-intrinsics.md
@@ -0,0 +1,5 @@
+# `core_intrinsics`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/core-panic.md b/src/doc/unstable-book/src/library-features/core-panic.md
new file mode 100644
index 000000000..c19758840
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/core-panic.md
@@ -0,0 +1,5 @@
+# `core_panic`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/core-private-bignum.md b/src/doc/unstable-book/src/library-features/core-private-bignum.md
new file mode 100644
index 000000000..f85811c54
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/core-private-bignum.md
@@ -0,0 +1,5 @@
+# `core_private_bignum`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/core-private-diy-float.md b/src/doc/unstable-book/src/library-features/core-private-diy-float.md
new file mode 100644
index 000000000..8465921d6
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/core-private-diy-float.md
@@ -0,0 +1,5 @@
+# `core_private_diy_float`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/dec2flt.md b/src/doc/unstable-book/src/library-features/dec2flt.md
new file mode 100644
index 000000000..311ab4adc
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/dec2flt.md
@@ -0,0 +1,5 @@
+# `dec2flt`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/default-free-fn.md b/src/doc/unstable-book/src/library-features/default-free-fn.md
new file mode 100644
index 000000000..d40a27ddd
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/default-free-fn.md
@@ -0,0 +1,47 @@
+# `default_free_fn`
+
+The tracking issue for this feature is: [#73014]
+
+[#73014]: https://github.com/rust-lang/rust/issues/73014
+
+------------------------
+
+Adds a free `default()` function to the `std::default` module. This function
+just forwards to [`Default::default()`], but may remove repetition of the word
+"default" from the call site.
+
+[`Default::default()`]: https://doc.rust-lang.org/nightly/std/default/trait.Default.html#tymethod.default
+
+Here is an example:
+
+```rust
+#![feature(default_free_fn)]
+use std::default::default;
+
+#[derive(Default)]
+struct AppConfig {
+ foo: FooConfig,
+ bar: BarConfig,
+}
+
+#[derive(Default)]
+struct FooConfig {
+ foo: i32,
+}
+
+#[derive(Default)]
+struct BarConfig {
+ bar: f32,
+ baz: u8,
+}
+
+fn main() {
+ let options = AppConfig {
+ foo: default(),
+ bar: BarConfig {
+ bar: 10.1,
+ ..default()
+ },
+ };
+}
+```
diff --git a/src/doc/unstable-book/src/library-features/derive-clone-copy.md b/src/doc/unstable-book/src/library-features/derive-clone-copy.md
new file mode 100644
index 000000000..cc603911c
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/derive-clone-copy.md
@@ -0,0 +1,5 @@
+# `derive_clone_copy`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/derive-eq.md b/src/doc/unstable-book/src/library-features/derive-eq.md
new file mode 100644
index 000000000..68a275f54
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/derive-eq.md
@@ -0,0 +1,5 @@
+# `derive_eq`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/fd-read.md b/src/doc/unstable-book/src/library-features/fd-read.md
new file mode 100644
index 000000000..e78d4330a
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/fd-read.md
@@ -0,0 +1,5 @@
+# `fd_read`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/fd.md b/src/doc/unstable-book/src/library-features/fd.md
new file mode 100644
index 000000000..041424428
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/fd.md
@@ -0,0 +1,5 @@
+# `fd`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/flt2dec.md b/src/doc/unstable-book/src/library-features/flt2dec.md
new file mode 100644
index 000000000..15e62a3a7
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/flt2dec.md
@@ -0,0 +1,5 @@
+# `flt2dec`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/fmt-internals.md b/src/doc/unstable-book/src/library-features/fmt-internals.md
new file mode 100644
index 000000000..7cbe3c89a
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/fmt-internals.md
@@ -0,0 +1,5 @@
+# `fmt_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/fn-traits.md b/src/doc/unstable-book/src/library-features/fn-traits.md
new file mode 100644
index 000000000..29a8aecee
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/fn-traits.md
@@ -0,0 +1,35 @@
+# `fn_traits`
+
+The tracking issue for this feature is [#29625]
+
+See Also: [`unboxed_closures`](../language-features/unboxed-closures.md)
+
+[#29625]: https://github.com/rust-lang/rust/issues/29625
+
+----
+
+The `fn_traits` feature allows for implementation of the [`Fn*`] traits
+for creating custom closure-like types.
+
+[`Fn*`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
+
+```rust
+#![feature(unboxed_closures)]
+#![feature(fn_traits)]
+
+struct Adder {
+ a: u32
+}
+
+impl FnOnce<(u32, )> for Adder {
+ type Output = u32;
+ extern "rust-call" fn call_once(self, b: (u32, )) -> Self::Output {
+ self.a + b.0
+ }
+}
+
+fn main() {
+ let adder = Adder { a: 3 };
+ assert_eq!(adder(2), 5);
+}
+```
diff --git a/src/doc/unstable-book/src/library-features/int-error-internals.md b/src/doc/unstable-book/src/library-features/int-error-internals.md
new file mode 100644
index 000000000..402e4fa5e
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/int-error-internals.md
@@ -0,0 +1,5 @@
+# `int_error_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/internal-output-capture.md b/src/doc/unstable-book/src/library-features/internal-output-capture.md
new file mode 100644
index 000000000..7e1241fce
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/internal-output-capture.md
@@ -0,0 +1,5 @@
+# `internal_output_capture`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/is-sorted.md b/src/doc/unstable-book/src/library-features/is-sorted.md
new file mode 100644
index 000000000..e3b7dc3b2
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/is-sorted.md
@@ -0,0 +1,11 @@
+# `is_sorted`
+
+The tracking issue for this feature is: [#53485]
+
+[#53485]: https://github.com/rust-lang/rust/issues/53485
+
+------------------------
+
+Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`;
+add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to
+`Iterator`.
diff --git a/src/doc/unstable-book/src/library-features/libstd-sys-internals.md b/src/doc/unstable-book/src/library-features/libstd-sys-internals.md
new file mode 100644
index 000000000..1b53faa8a
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/libstd-sys-internals.md
@@ -0,0 +1,5 @@
+# `libstd_sys_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/libstd-thread-internals.md b/src/doc/unstable-book/src/library-features/libstd-thread-internals.md
new file mode 100644
index 000000000..b682d12e7
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/libstd-thread-internals.md
@@ -0,0 +1,5 @@
+# `libstd_thread_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/print-internals.md b/src/doc/unstable-book/src/library-features/print-internals.md
new file mode 100644
index 000000000..a68557872
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/print-internals.md
@@ -0,0 +1,5 @@
+# `print_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/profiler-runtime-lib.md b/src/doc/unstable-book/src/library-features/profiler-runtime-lib.md
new file mode 100644
index 000000000..a01f1e73a
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/profiler-runtime-lib.md
@@ -0,0 +1,5 @@
+# `profiler_runtime_lib`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/rt.md b/src/doc/unstable-book/src/library-features/rt.md
new file mode 100644
index 000000000..007acc207
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/rt.md
@@ -0,0 +1,5 @@
+# `rt`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/sort-internals.md b/src/doc/unstable-book/src/library-features/sort-internals.md
new file mode 100644
index 000000000..6f2385e53
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/sort-internals.md
@@ -0,0 +1,5 @@
+# `sort_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/str-internals.md b/src/doc/unstable-book/src/library-features/str-internals.md
new file mode 100644
index 000000000..af8ef056d
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/str-internals.md
@@ -0,0 +1,5 @@
+# `str_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/test.md b/src/doc/unstable-book/src/library-features/test.md
new file mode 100644
index 000000000..c99584e5f
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/test.md
@@ -0,0 +1,158 @@
+# `test`
+
+The tracking issue for this feature is: None.
+
+------------------------
+
+The internals of the `test` crate are unstable, behind the `test` flag. The
+most widely used part of the `test` crate are benchmark tests, which can test
+the performance of your code. Let's make our `src/lib.rs` look like this
+(comments elided):
+
+```rust,no_run
+#![feature(test)]
+
+extern crate test;
+
+pub fn add_two(a: i32) -> i32 {
+ a + 2
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use test::Bencher;
+
+ #[test]
+ fn it_works() {
+ assert_eq!(4, add_two(2));
+ }
+
+ #[bench]
+ fn bench_add_two(b: &mut Bencher) {
+ b.iter(|| add_two(2));
+ }
+}
+```
+
+Note the `test` feature gate, which enables this unstable feature.
+
+We've imported the `test` crate, which contains our benchmarking support.
+We have a new function as well, with the `bench` attribute. Unlike regular
+tests, which take no arguments, benchmark tests take a `&mut Bencher`. This
+`Bencher` provides an `iter` method, which takes a closure. This closure
+contains the code we'd like to benchmark.
+
+We can run benchmark tests with `cargo bench`:
+
+```bash
+$ cargo bench
+ Compiling adder v0.0.1 (file:///home/steve/tmp/adder)
+ Running target/release/adder-91b3e234d4ed382a
+
+running 2 tests
+test tests::it_works ... ignored
+test tests::bench_add_two ... bench: 1 ns/iter (+/- 0)
+
+test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured
+```
+
+Our non-benchmark test was ignored. You may have noticed that `cargo bench`
+takes a bit longer than `cargo test`. This is because Rust runs our benchmark
+a number of times, and then takes the average. Because we're doing so little
+work in this example, we have a `1 ns/iter (+/- 0)`, but this would show
+the variance if there was one.
+
+Advice on writing benchmarks:
+
+
+* Move setup code outside the `iter` loop; only put the part you want to measure inside
+* Make the code do "the same thing" on each iteration; do not accumulate or change state
+* Make the outer function idempotent too; the benchmark runner is likely to run
+ it many times
+* Make the inner `iter` loop short and fast so benchmark runs are fast and the
+ calibrator can adjust the run-length at fine resolution
+* Make the code in the `iter` loop do something simple, to assist in pinpointing
+ performance improvements (or regressions)
+
+## Gotcha: optimizations
+
+There's another tricky part to writing benchmarks: benchmarks compiled with
+optimizations activated can be dramatically changed by the optimizer so that
+the benchmark is no longer benchmarking what one expects. For example, the
+compiler might recognize that some calculation has no external effects and
+remove it entirely.
+
+```rust,no_run
+#![feature(test)]
+
+extern crate test;
+use test::Bencher;
+
+#[bench]
+fn bench_xor_1000_ints(b: &mut Bencher) {
+ b.iter(|| {
+ (0..1000).fold(0, |old, new| old ^ new);
+ });
+}
+```
+
+gives the following results
+
+```text
+running 1 test
+test bench_xor_1000_ints ... bench: 0 ns/iter (+/- 0)
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
+```
+
+The benchmarking runner offers two ways to avoid this. Either, the closure that
+the `iter` method receives can return an arbitrary value which forces the
+optimizer to consider the result used and ensures it cannot remove the
+computation entirely. This could be done for the example above by adjusting the
+`b.iter` call to
+
+```rust
+# struct X;
+# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
+b.iter(|| {
+ // Note lack of `;` (could also use an explicit `return`).
+ (0..1000).fold(0, |old, new| old ^ new)
+});
+```
+
+Or, the other option is to call the generic `test::black_box` function, which
+is an opaque "black box" to the optimizer and so forces it to consider any
+argument as used.
+
+```rust
+#![feature(test)]
+
+extern crate test;
+
+# fn main() {
+# struct X;
+# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
+b.iter(|| {
+ let n = test::black_box(1000);
+
+ (0..n).fold(0, |a, b| a ^ b)
+})
+# }
+```
+
+Neither of these read or modify the value, and are very cheap for small values.
+Larger values can be passed indirectly to reduce overhead (e.g.
+`black_box(&huge_struct)`).
+
+Performing either of the above changes gives the following benchmarking results
+
+```text
+running 1 test
+test bench_xor_1000_ints ... bench: 131 ns/iter (+/- 3)
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
+```
+
+However, the optimizer can still modify a testcase in an undesirable manner
+even when using either of the above.
diff --git a/src/doc/unstable-book/src/library-features/thread-local-internals.md b/src/doc/unstable-book/src/library-features/thread-local-internals.md
new file mode 100644
index 000000000..e1cdcc339
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/thread-local-internals.md
@@ -0,0 +1,5 @@
+# `thread_local_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/trace-macros.md b/src/doc/unstable-book/src/library-features/trace-macros.md
new file mode 100644
index 000000000..41aa286e6
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/trace-macros.md
@@ -0,0 +1,39 @@
+# `trace_macros`
+
+The tracking issue for this feature is [#29598].
+
+[#29598]: https://github.com/rust-lang/rust/issues/29598
+
+------------------------
+
+With `trace_macros` you can trace the expansion of macros in your code.
+
+## Examples
+
+```rust
+#![feature(trace_macros)]
+
+fn main() {
+ trace_macros!(true);
+ println!("Hello, Rust!");
+ trace_macros!(false);
+}
+```
+
+The `cargo build` output:
+
+```txt
+note: trace_macro
+ --> src/main.rs:5:5
+ |
+5 | println!("Hello, Rust!");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: expanding `println! { "Hello, Rust!" }`
+ = note: to `print ! ( concat ! ( "Hello, Rust!" , "\n" ) )`
+ = note: expanding `print! { concat ! ( "Hello, Rust!" , "\n" ) }`
+ = note: to `$crate :: io :: _print ( format_args ! ( concat ! ( "Hello, Rust!" , "\n" ) )
+ )`
+
+ Finished dev [unoptimized + debuginfo] target(s) in 0.60 secs
+```
diff --git a/src/doc/unstable-book/src/library-features/update-panic-count.md b/src/doc/unstable-book/src/library-features/update-panic-count.md
new file mode 100644
index 000000000..d315647ba
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/update-panic-count.md
@@ -0,0 +1,5 @@
+# `update_panic_count`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/windows-c.md b/src/doc/unstable-book/src/library-features/windows-c.md
new file mode 100644
index 000000000..3f833eb3d
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/windows-c.md
@@ -0,0 +1,5 @@
+# `windows_c`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/windows-handle.md b/src/doc/unstable-book/src/library-features/windows-handle.md
new file mode 100644
index 000000000..f47a84250
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/windows-handle.md
@@ -0,0 +1,5 @@
+# `windows_handle`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/windows-net.md b/src/doc/unstable-book/src/library-features/windows-net.md
new file mode 100644
index 000000000..174960d4f
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/windows-net.md
@@ -0,0 +1,5 @@
+# `windows_net`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/library-features/windows-stdio.md b/src/doc/unstable-book/src/library-features/windows-stdio.md
new file mode 100644
index 000000000..4d3614423
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/windows-stdio.md
@@ -0,0 +1,5 @@
+# `windows_stdio`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/the-unstable-book.md b/src/doc/unstable-book/src/the-unstable-book.md
new file mode 100644
index 000000000..554c52c3c
--- /dev/null
+++ b/src/doc/unstable-book/src/the-unstable-book.md
@@ -0,0 +1,22 @@
+# The Unstable Book
+
+Welcome to the Unstable Book! This book consists of a number of chapters,
+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(box_syntax)]
+
+fn main() {
+ let five = box 5;
+}
+```
+
+The `box_syntax` feature [has a chapter][box] describing how to use it.
+
+[box]: language-features/box-syntax.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
+best-effort basis. Each page will have a link to its tracking issue with the
+latest developments; you might want to check those as well.