From 7575dc3755dc1c36cbb4ed5ec0c7ca04c5b06594 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 5 Jan 2025 18:34:43 +0100 Subject: [PATCH 01/10] move r[rules] to the left of the main body, using a grid --- theme/reference.css | 51 +++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/theme/reference.css b/theme/reference.css index 58be91816..6d0551b56 100644 --- a/theme/reference.css +++ b/theme/reference.css @@ -156,31 +156,46 @@ dfn { /* Rules are generated via r[foo.bar] syntax, processed by mdbook-spec. */ .rule { - /* Allows the rule to be positioned. */ - position: relative; - /* Position slightly to the left. */ - left: -4em; - color: #999; font-size: 0.8em; } -/* mdbook will wrap the rule content in a

tag, with a margin. However, we - don't need the extra space -*/ -.rule ~ p { - margin-top: 0px; + +main { + /* To nicely display rules (`[a.b.c]`) on a side of the main text body we + use grid layout. */ + display: grid; + grid-template-columns: + /* Left margin / place for rules */ + [rules] minmax(20px, 1fr) + /* The main text body */ + [text] auto + /* Right margin */ + [margin] minmax(20px, 1fr); + max-width: none !important; } -/* When the sidebar is visible, reduce the spacing of rules so that the - content doesn't get shifted too far, and make the text too narrow. -*/ -.sidebar-visible .rule { - left: -1em; +main > * { + /* By default grid items can't be smaller than their content. + That is, by default `min-width: auto`. + We want to be able to force code blocks to be scrollable, + so we need to overwrite `min-width`. */ + min-width: 0; + max-width: var(--content-max-width); + + /* All elements should be in the main text body... */ + grid-column: text; +} + +main > .rule { + /* ... except the rules, which must be in the left margin */ + grid-column: rules; } -.sidebar-visible .content main { - padding-left: 1em; + +main > .rule { + max-width: unset; + justify-self: right; + width: 100%; } -/* Remove the blue coloring of links on rules that mdbook normally sets. */ .rule-link { color: #999 !important; } From 5a14e3e6d201b91a4ff831f1f40d89048ac14965 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Wed, 8 Jan 2025 12:02:06 +0100 Subject: [PATCH 02/10] Move heading-related rules before headings i.e. this replaces ```markdown # UwU r[uwu] ``` with ```markdown r[uwu] # UwU ``` This is required because the new grid system assumes that a rule is related to the *following* element. But also, it makes it clear in the source which element the rule is related to, as it's curently ambiguous. Also (2), existing annotations are not 100% consistent. I've done this using the following two irregular "regex" replacements: 1. `([^\]]\n|^(?> `$1$3\n$2\n\n$4` (~255 cases) 2. `([^\]]\n|^(?> `$1$3\n$2\n\n` (~99 cases) With the latter one being reviewed manually, since it can produce bad replacements in cases like this, where the rule relates to the following paragraph/element, rather than the preceding heading: ```markdown # OwO r[meow] >////< mEeoowW prRRrr purrrrrrRr :3 mrrrrrreww meEooww purrrrrr~ Mrrrew ``` --- src/attributes.md | 12 ++---- src/attributes/codegen.md | 41 ++++++++---------- src/attributes/debugger.md | 14 +++---- src/attributes/derive.md | 5 +-- src/attributes/diagnostics.md | 28 +++++-------- src/attributes/limits.md | 7 ++-- src/attributes/testing.md | 11 ++--- src/attributes/type_system.md | 6 +-- src/behavior-considered-undefined.md | 5 +-- src/comments.md | 7 ++-- src/conditional-compilation.md | 54 +++++++++--------------- src/const_eval.md | 8 ++-- src/crates-and-source-files.md | 11 ++--- src/destructors.md | 24 +++++------ src/identifiers.md | 8 ++-- src/inline-assembly.md | 50 +++++++++------------- src/input-format.md | 15 +++---- src/interior-mutability.md | 3 +- src/items.md | 3 +- src/items/associated-items.md | 21 ++++------ src/items/constant-items.md | 12 ++---- src/items/enumerations.md | 24 ++++------- src/items/extern-crates.md | 9 ++-- src/items/external-blocks.md | 45 +++++++------------- src/items/functions.md | 30 +++++--------- src/items/generics.md | 12 ++---- src/items/implementations.md | 21 ++++------ src/items/modules.md | 12 ++---- src/items/static-items.md | 12 ++---- src/items/structs.md | 3 +- src/items/traits.md | 24 ++++------- src/items/type-aliases.md | 3 +- src/items/unions.md | 15 +++---- src/items/use-declarations.md | 30 +++++--------- src/linkage.md | 5 +-- src/macro-ambiguity.md | 23 ++++------- src/macros-by-example.md | 32 +++++--------- src/procedural-macros.md | 23 ++++------- src/statements-and-expressions.md | 2 +- src/statements.md | 16 +++---- src/subtyping.md | 6 +-- src/tokens.md | 62 ++++++++++------------------ src/trait-bounds.md | 16 +++---- src/type-coercions.md | 15 +++---- src/type-layout.md | 59 +++++++++++--------------- src/types.md | 12 ++---- src/types/array.md | 3 +- src/types/boolean.md | 24 ++++------- src/types/closure.md | 49 ++++++++++------------ src/types/enum.md | 3 +- src/types/function-item.md | 3 +- src/types/function-pointer.md | 6 +-- src/types/impl-trait.md | 24 ++++------- src/types/inferred.md | 3 +- src/types/never.md | 3 +- src/types/numeric.md | 15 +++---- src/types/parameters.md | 3 +- src/types/pointer.md | 21 ++++------ src/types/slice.md | 3 +- src/types/struct.md | 3 +- src/types/textual.md | 6 +-- src/types/trait-object.md | 6 +-- src/types/tuple.md | 3 +- src/types/union.md | 3 +- src/unsafe-keyword.md | 18 ++++---- src/unsafety.md | 3 +- src/variables.md | 3 +- src/visibility-and-privacy.md | 9 ++-- src/whitespace.md | 3 +- 69 files changed, 387 insertions(+), 686 deletions(-) diff --git a/src/attributes.md b/src/attributes.md index f537e4cd2..0b72c018b 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -105,9 +105,8 @@ fn some_unused_variables() { } ``` -## Meta Item Attribute Syntax - r[attributes.meta] +## Meta Item Attribute Syntax r[attributes.meta.intro] A "meta item" is the syntax used for the _Attr_ rule by most [built-in @@ -188,9 +187,8 @@ _MetaListPaths_ | `allow(unused, clippy::inline_always)` _MetaListIdents_ | `macro_use(foo, bar)` _MetaListNameValueStr_ | `link(name = "CoreFoundation", kind = "framework")` -## Active and inert attributes - r[attributes.activity] +## Active and inert attributes r[attributes.activity.intro] An attribute is either active or inert. During attribute processing, *active @@ -201,9 +199,8 @@ The [`cfg`] and [`cfg_attr`] attributes are active. The [`test`] attribute is inert when compiling for tests and active otherwise. [Attribute macros] are active. All other attributes are inert. -## Tool attributes - r[attributes.tool] +## Tool attributes r[attributes.tool.intro] The compiler may allow attributes for external tools where each tool resides @@ -234,9 +231,8 @@ pub fn f() {} > Note: `rustc` currently recognizes the tools "clippy", "rustfmt", "diagnostic", > "miri" and "rust_analyzer". -## Built-in attributes index - r[attributes.builtin] +## Built-in attributes index The following is an index of all built-in attributes. diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 297d6436f..ab9295c3b 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -1,12 +1,11 @@ +r[attributes.codegen] # Code generation attributes -r[attributes.codegen] The following [attributes] are used for controlling code generation. -## Optimization hints - r[attributes.codegen.hint] +## Optimization hints r[attributes.codegen.hint.cold-inline] The `cold` and `inline` [attributes] give suggestions to generate code in a @@ -19,9 +18,8 @@ Both attributes can be used on [functions]. When applied to a function in a a trait implementation and not to all trait implementations. The attributes have no effect on a trait function without a body. -### The `inline` attribute - r[attributes.codegen.inline] +### The `inline` attribute r[attributes.codegen.inline.intro] The *`inline` [attribute]* suggests that a copy of the attributed function @@ -44,24 +42,23 @@ There are three ways to use the inline attribute: > ***Note***: `#[inline]` in every form is a hint, with no *requirements* > on the language to place a copy of the attributed function in the caller. +r[attributes.codegen.cold] ### The `cold` attribute -r[attributes.codegen.cold] The *`cold` [attribute]* suggests that the attributed function is unlikely to be called. +r[attributes.codegen.no_builtins] ## The `no_builtins` attribute -r[attributes.codegen.no_builtins] The *`no_builtins` [attribute]* may be applied at the crate level to disable optimizing certain code patterns to invocations of library functions that are assumed to exist. -## The `target_feature` attribute - r[attributes.codegen.target_feature] +## The `target_feature` attribute r[attributes.codegen.target_feature.intro] The *`target_feature` [attribute]* may be applied to a function to @@ -90,15 +87,15 @@ Functions marked with `target_feature` are not inlined into a context that does not support the given features. The `#[inline(always)]` attribute may not be used with a `target_feature` attribute. +r[attributes.codegen.target_feature.availability] ### Available features -r[attributes.codegen.target_feature.availability] The following is a list of the available feature names. +r[attributes.codegen.target_feature.x86] #### `x86` or `x86_64` -r[attributes.codegen.target_feature.x86] Executing code with unsupported features is undefined behavior on this platform. Hence this platform requires that `#[target_feature]` is only applied to [`unsafe` @@ -165,9 +162,9 @@ Feature | Implicitly Enables | Description [`xsaveopt`]: https://www.felixcloutier.com/x86/xsaveopt [`xsaves`]: https://www.felixcloutier.com/x86/xsaves +r[attributes.codegen.target_feature.aarch64] #### `aarch64` -r[attributes.codegen.target_feature.aarch64] This platform requires that `#[target_feature]` is only applied to [`unsafe` functions][unsafe function]. @@ -230,9 +227,9 @@ Feature | Implicitly Enables | Feature Name `tme` | | FEAT_TME --- Transactional Memory Extension `vh` | | FEAT_VHE --- Virtualization Host Extensions +r[attributes.codegen.target_feature.riscv] #### `riscv32` or `riscv64` -r[attributes.codegen.target_feature.riscv] This platform requires that `#[target_feature]` is only applied to [`unsafe` functions][unsafe function]. @@ -292,9 +289,9 @@ Feature | Implicitly Enables | Description [rv-zksh]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zksh.adoc [rv-zkt]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zkt.adoc +r[attributes.codegen.target_feature.wasm] #### `wasm32` or `wasm64` -r[attributes.codegen.target_feature.wasm] `#[target_feature]` may be used with both safe and [`unsafe` functions][unsafe function] on Wasm platforms. It is impossible to @@ -327,9 +324,8 @@ Feature | Implicitly Enables | Description [tail-call]: https://github.com/webassembly/tail-call [multivalue]: https://github.com/webassembly/multi-value -### Additional information - r[attributes.codegen.target_feature.info] +### Additional information r[attributes.codegen.target_feature.remark-cfg] See the [`target_feature` conditional compilation option] for selectively @@ -346,9 +342,8 @@ in the standard library for runtime feature detection on these platforms. > may be enabled or disabled for an entire crate with the > [`-C target-feature`] flag. -## The `track_caller` attribute - r[attributes.codegen.track_caller] +## The `track_caller` attribute r[attributes.codegen.track_caller.allowed-positions] The `track_caller` attribute may be applied to any function with [`"Rust"` ABI][rust-abi] @@ -364,9 +359,9 @@ implementations, otherwise undefined behavior results. When applied to a functio available to an `extern` block, the declaration in the `extern` block must also have the attribute, otherwise undefined behavior results. +r[attributes.codegen.track_caller.behavior] ### Behavior -r[attributes.codegen.track_caller.behavior] Applying the attribute to a function `f` allows code within `f` to get a hint of the [`Location`] of the "topmost" tracked call that led to `f`'s invocation. At the point of observation, an implementation behaves as if it walks up the stack from `f`'s frame to find the nearest frame of an @@ -444,9 +439,8 @@ fn calls_h() { And so on. -### Limitations - r[attributes.codegen.track_caller.limits] +### Limitations r[attributes.codegen.track_caller.hint] This information is a hint and implementations are not required to preserve it. @@ -480,9 +474,8 @@ trait object whose methods are attributed. [rust-abi]: ../items/external-blocks.md#abi [`Location`]: core::panic::Location -## The `instruction_set` attribute - r[attributes.codegen.instruction_set] +## The `instruction_set` attribute r[attributes.codegen.instruction_set.allowed-positions] The *`instruction_set` [attribute]* may be applied to a function to control which instruction set the function will be generated for. @@ -498,9 +491,9 @@ It uses the [_MetaListPath_] syntax, and a path comprised of the architecture fa r[attributes.codegen.instruction_set.target-limits] It is a compilation error to use the `instruction_set` attribute on a target that does not support it. +r[attributes.codegen.instruction_set.arm] ### On ARM -r[attributes.codegen.instruction_set.arm] For the `ARMv4T` and `ARMv5te` architectures, the following are supported: * `arm::a32` --- Generate the function as A32 "ARM" code. diff --git a/src/attributes/debugger.md b/src/attributes/debugger.md index 2521c4e83..1dfce1ce7 100644 --- a/src/attributes/debugger.md +++ b/src/attributes/debugger.md @@ -1,12 +1,11 @@ +r[attributes.debugger] # Debugger attributes -r[attributes.debugger] The following [attributes] are used for enhancing the debugging experience when using third-party debuggers like GDB or WinDbg. -## The `debugger_visualizer` attribute - r[attributes.debugger.debugger_visualizer] +## The `debugger_visualizer` attribute r[attributes.debugger.debugger_visualizer.intro] The *`debugger_visualizer` attribute* can be used to embed a debugger visualizer file into the debug information. @@ -15,9 +14,8 @@ This enables an improved debugger experience for displaying values in the debugg r[attributes.debugger.debugger_visualizer.syntax] It uses the [_MetaListNameValueStr_] syntax to specify its inputs, and must be specified as a crate attribute. -### Using `debugger_visualizer` with Natvis - r[attributes.debugger.debugger_visualizer.natvis] +### Using `debugger_visualizer` with Natvis r[attributes.debugger.debugger_visualizer.natvis.intro] Natvis is an XML-based framework for Microsoft debuggers (such as Visual Studio and WinDbg) that uses declarative rules to customize the display of types. @@ -82,9 +80,8 @@ When viewed under WinDbg, the `fancy_rect` variable would be shown as follows: > LowerRight: (15.0, 10.0) ``` -### Using `debugger_visualizer` with GDB - r[attributes.debugger.debugger_visualizer.gdb] +### Using `debugger_visualizer` with GDB r[attributes.debugger.debugger_visualizer.gdb.pretty] GDB supports the use of a structured Python script, called a *pretty printer*, that describes how a type should be visualized in the debugger view. @@ -156,9 +153,8 @@ When the crate's debug executable is passed into GDB[^rust-gdb], `print bob` wil [pretty printing documentation]: https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html [_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax -## The `collapse_debuginfo` attribute - r[attributes.debugger.collapse_debuginfo] +## The `collapse_debuginfo` attribute r[attributes.debugger.collapse_debuginfo.intro] The *`collapse_debuginfo` [attribute]* controls whether code locations from a macro definition are collapsed into a single location associated with the macro's call site, diff --git a/src/attributes/derive.md b/src/attributes/derive.md index 6a61dbf78..a89b5380d 100644 --- a/src/attributes/derive.md +++ b/src/attributes/derive.md @@ -1,6 +1,5 @@ -# Derive - r[attributes.derive] +# Derive r[attributes.derive.intro] The *`derive` attribute* allows new [items] to be automatically generated for @@ -36,9 +35,9 @@ impl PartialEq for Foo { r[attributes.derive.proc-macro] You can implement `derive` for your own traits through [procedural macros]. +r[attributes.derive.automatically_derived] ## The `automatically_derived` attribute -r[attributes.derive.automatically_derived] The *`automatically_derived` attribute* is automatically added to [implementations] created by the `derive` attribute for built-in traits. It has no direct effect, but it may be used by tools and diagnostic lints to diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index c75915d51..f46e58f9d 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -1,13 +1,11 @@ -# Diagnostic attributes - r[attributes.diagnostics] +# Diagnostic attributes The following [attributes] are used for controlling or generating diagnostic messages during compilation. -## Lint check attributes - r[attributes.diagnostics.lint] +## Lint check attributes A lint check names a potentially undesirable coding pattern, such as unreachable code or omitted documentation. @@ -104,9 +102,9 @@ pub mod m3 { > [command-line][rustc-lint-cli], and also supports [setting > caps][rustc-lint-caps] on the lints that are reported. +r[attributes.diagnostics.lint.reason] ### Lint Reasons -r[attributes.diagnostics.lint.reason] All lint attributes support an additional `reason` parameter, to give context why a certain attribute was added. This reason will be displayed as part of the lint message if the lint is emitted at the defined level. @@ -141,9 +139,8 @@ pub fn get_path() -> PathBuf { } ``` -### The `#[expect]` attribute - r[attributes.diagnostics.expect] +### The `#[expect]` attribute r[attributes.diagnostics.expect.intro] The `#[expect(C)]` attribute creates a lint expectation for lint `C`. The @@ -228,9 +225,9 @@ pub fn another_example() { > Note: The behavior of `#[expect(unfulfilled_lint_expectations)]` is currently > defined to always generate the `unfulfilled_lint_expectations` lint. +r[attributes.diagnostics.lint.group] ### Lint groups -r[attributes.diagnostics.lint.group] Lints may be organized into named groups so that the level of related lints can be adjusted together. Using a named group is equivalent to listing out the lints within that group. @@ -269,9 +266,8 @@ fn example_err() { } ``` -### Tool lint attributes - r[attributes.diagnostics.lint.tool] +### Tool lint attributes r[attributes.diagnostics.lint.tool.intro] Tool lints allows using scoped lints, to `allow`, `warn`, `deny` or `forbid` @@ -303,9 +299,8 @@ fn foo() { > Note: `rustc` currently recognizes the tool lints for "[clippy]" and "[rustdoc]". -## The `deprecated` attribute - r[attributes.diagnostics.deprecated] +## The `deprecated` attribute r[attributes.diagnostics.deprecated.intro] The *`deprecated` attribute* marks an item as deprecated. `rustc` will issue @@ -350,9 +345,8 @@ The [RFC][1270-deprecation.md] contains motivations and more details. [1270-deprecation.md]: https://github.com/rust-lang/rfcs/blob/master/text/1270-deprecation.md -## The `must_use` attribute - r[attributes.diagnostics.must_use] +## The `must_use` attribute r[attributes.diagnostics.must_use.intro] The *`must_use` attribute* is used to issue a diagnostic warning when a value @@ -469,9 +463,8 @@ When used on a function in a trait implementation, the attribute does nothing. > let _ = five(); > ``` -## The `diagnostic` tool attribute namespace - r[attributes.diagnostic.namespace] +## The `diagnostic` tool attribute namespace r[attributes.diagnostic.namespace.intro] The `#[diagnostic]` attribute namespace is a home for attributes to influence compile-time error messages. @@ -482,9 +475,8 @@ Unknown attributes in this namespace are accepted, though they may emit warnings Additionally, invalid inputs to known attributes will typically be a warning (see the attribute definitions for details). This is meant to allow adding or discarding attributes and changing inputs in the future to allow changes without the need to keep the non-meaningful attributes or options working. -### The `diagnostic::on_unimplemented` attribute - r[attributes.diagnostic.on_unimplemented] +### The `diagnostic::on_unimplemented` attribute r[attributes.diagnostic.on_unimplemented.intro] The `#[diagnostic::on_unimplemented]` attribute is a hint to the compiler to supplement the error message that would normally be generated in scenarios where a trait is required but not implemented on a type. diff --git a/src/attributes/limits.md b/src/attributes/limits.md index 1c8c46bb5..37000c44b 100644 --- a/src/attributes/limits.md +++ b/src/attributes/limits.md @@ -1,12 +1,11 @@ +r[attributes.limits] # Limits -r[attributes.limits] The following [attributes] affect compile-time limits. -## The `recursion_limit` attribute - r[attributes.limits.recursion_limit] +## The `recursion_limit` attribute r[attributes.limits.recursion_limit.intro] The *`recursion_limit` attribute* may be applied at the [crate] level to set the @@ -41,9 +40,9 @@ a!{} (|_: &u8| {})(&&&1); ``` +r[attributes.limits.type_length_limit] ## The `type_length_limit` attribute -r[attributes.limits.type_length_limit] > **Note**: This limit is only enforced when the nightly `-Zenforce-type-length-limit` flag is active. > diff --git a/src/attributes/testing.md b/src/attributes/testing.md index d245da66b..1c37c6d2f 100644 --- a/src/attributes/testing.md +++ b/src/attributes/testing.md @@ -1,15 +1,14 @@ +r[attributes.testing] # Testing attributes -r[attributes.testing] The following [attributes] are used for specifying functions for performing tests. Compiling a crate in "test" mode enables building the test functions along with a test harness for executing the tests. Enabling the test mode also enables the [`test` conditional compilation option]. -## The `test` attribute - r[attributes.testing.test] +## The `test` attribute r[attributes.testing.test.intro] The *`test` attribute* marks a function to be executed as a test. @@ -50,9 +49,8 @@ fn test_the_thing() -> io::Result<()> { } ``` -## The `ignore` attribute - r[attributes.testing.ignore] +## The `ignore` attribute r[attributes.testing.ignore.intro] A function annotated with the `test` attribute can also be annotated with the @@ -74,9 +72,8 @@ fn mytest() { > **Note**: The `rustc` test harness supports the `--include-ignored` flag to > force ignored tests to be run. -## The `should_panic` attribute - r[attributes.testing.should_panic] +## The `should_panic` attribute r[attributes.testing.should_panic.intro] A function annotated with the `test` attribute that returns `()` can also be diff --git a/src/attributes/type_system.md b/src/attributes/type_system.md index e26de1210..88044a717 100644 --- a/src/attributes/type_system.md +++ b/src/attributes/type_system.md @@ -1,12 +1,10 @@ -# Type system attributes - r[attributes.type-system] +# Type system attributes The following [attributes] are used for changing how a type can be used. -## The `non_exhaustive` attribute - r[attributes.type-system.non_exhaustive] +## The `non_exhaustive` attribute r[attributes.type-system.non_exhaustive.intro] The *`non_exhaustive` attribute* indicates that a type or variant may have diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index 424ef228f..92c1942db 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -1,6 +1,5 @@ -## Behavior considered undefined - r[undefined] +## Behavior considered undefined r[undefined.general] Rust code is incorrect if it exhibits any of the behaviors in the following @@ -103,9 +102,9 @@ r[undefined.const-transmute-ptr2int] > vice versa, undefined behavior in Rust can cause adverse affects on code > executed by any FFI calls to other languages. +r[undefined.pointed-to] ### Pointed-to bytes -r[undefined.pointed-to] The span of bytes a pointer or reference "points to" is determined by the pointer value and the size of the pointee type (using `size_of_val`). ### Places based on misaligned pointers diff --git a/src/comments.md b/src/comments.md index 502bf89a8..6b4a954e4 100644 --- a/src/comments.md +++ b/src/comments.md @@ -1,6 +1,6 @@ +r[comments.syntax] # Comments -r[comments.syntax] > **Lexer**\ > LINE_COMMENT :\ @@ -34,9 +34,9 @@ r[comments.syntax] > _IsolatedCR_ :\ >    \\r +r[comments.normal] ## Non-doc comments -r[comments.normal] Comments follow the general C++ style of line (`//`) and block (`/* ... */`) comment forms. Nested block comments are supported. @@ -44,9 +44,8 @@ block (`/* ... */`) comment forms. Nested block comments are supported. r[comments.normal.tokenization] Non-doc comments are interpreted as a form of whitespace. -## Doc comments - r[comments.doc] +## Doc comments r[comments.doc.syntax] Line doc comments beginning with exactly _three_ slashes (`///`), and block diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 5255bb8d8..6c2a505a4 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -1,6 +1,5 @@ -# Conditional compilation - r[cfg] +# Conditional compilation r[cfg.syntax] > **Syntax**\ @@ -64,9 +63,8 @@ Key-value pairs are written as an identifier, `=`, and then a string, such as `t r[cfg.option-key-uniqueness] Keys do not need to be unique. For example, both `feature = "std"` and `feature = "serde"` can be set at the same time. -## Set Configuration Options - r[cfg.options.set] +## Set Configuration Options r[cfg.options.general] Which configuration options are set is determined statically during the @@ -92,9 +90,8 @@ configuration option from within the source code of the crate being compiled. > [!WARNING] > Arbitrarily-set configuration options can clash with compiler-set configuration options. For example, it is possible to do `rustc --cfg "unix" program.rs` while compiling to a Windows target, and have both `unix` and `windows` configuration options set at the same time. Doing this would be unwise. -### `target_arch` - r[cfg.target_arch] +### `target_arch` r[cfg.target_arch.gen] Key-value option set once with the target's CPU architecture. The value is @@ -112,9 +109,8 @@ Example values: * `"arm"` * `"aarch64"` -### `target_feature` - r[cfg.target_feature] +### `target_feature` r[cfg.target_feature.general] Key-value option set for each platform feature available for the current @@ -138,9 +134,8 @@ r[cfg.target_feature.crt_static] An additional feature of `crt-static` is available to the `target_feature` option to indicate that a [static C runtime] is available. -### `target_os` - r[cfg.target_os] +### `target_os` r[cfg.target_os.general] Key-value option set once with the target's operating system. This value is @@ -160,9 +155,8 @@ Example values: * `"netbsd"` * `"none"` (typical for embedded targets) -### `target_family` - r[cfg.target_family] +### `target_family` r[cfg.target_family.general] Key-value option providing a more generic description of a target, such as the family of the @@ -177,17 +171,16 @@ Example values: * `"wasm"` * Both `"unix"` and `"wasm"` +r[cfg.target_family.unix] ### `unix` and `windows` -r[cfg.target_family.unix] `unix` is set if `target_family = "unix"` is set. r[cfg.target_family.windows] `windows` is set if `target_family = "windows"` is set. -### `target_env` - r[cfg.target_env] +### `target_env` r[cfg.target_env.general] Key-value option set with further disambiguating information about the target @@ -207,9 +200,8 @@ Example values: * `"musl"` * `"sgx"` -### `target_abi` - r[cfg.target_abi] +### `target_abi` r[cfg.target_abi.general] Key-value option set to further disambiguate the `target_env` with information @@ -230,15 +222,14 @@ Example values: * `"sim"` * `"macabi"` +r[cfg.target_endian] ### `target_endian` -r[cfg.target_endian] Key-value option set once with either a value of "little" or "big" depending on the endianness of the target's CPU. -### `target_pointer_width` - r[cfg.target_pointer_width] +### `target_pointer_width` r[cfg.target_pointer_width.general] Key-value option set once with the target's pointer width in bits. @@ -250,9 +241,8 @@ Example values: * `"32"` * `"64"` -### `target_vendor` - r[cfg.target_vendor] +### `target_vendor` r[cfg.target_vendor.general] Key-value option set once with the vendor of the target. @@ -265,9 +255,8 @@ Example values: * `"pc"` * `"unknown"` -### `target_has_atomic` - r[cfg.target_has_atomic] +### `target_has_atomic` r[cfg.target_has_atomic.general] Key-value option set for each bit width that the target supports @@ -288,32 +277,31 @@ Possible values: * `"128"` * `"ptr"` +r[cfg.test] ### `test` -r[cfg.test] Enabled when compiling the test harness. Done with `rustc` by using the [`--test`] flag. See [Testing] for more on testing support. +r[cfg.debug_assertions] ### `debug_assertions` -r[cfg.debug_assertions] Enabled by default when compiling without optimizations. This can be used to enable extra debugging code in development but not in production. For example, it controls the behavior of the standard library's [`debug_assert!`] macro. +r[cfg.proc_macro] ### `proc_macro` -r[cfg.proc_macro] Set when the crate being compiled is being compiled with the `proc_macro` [crate type]. -### `panic` - r[cfg.panic] +### `panic` r[cfg.panic.general] Key-value option set depending on the panic strategy. Note that more values may be added in the future. @@ -326,9 +314,8 @@ Example values: ## Forms of conditional compilation -### The `cfg` attribute - r[cfg.attr] +### The `cfg` attribute r[cfg.attr.syntax] > **Syntax**\ @@ -394,9 +381,8 @@ fn when_unwinding() { r[cfg.attr.restriction] The `cfg` attribute is allowed anywhere attributes are allowed. -### The `cfg_attr` attribute - r[cfg.cfg_attr] +### The `cfg_attr` attribute r[cfg.cfg_attr.syntax] > **Syntax**\ @@ -447,9 +433,9 @@ The `cfg_attr` attribute is allowed anywhere attributes are allowed. The [`crate_type`] and [`crate_name`] attributes cannot be used with `cfg_attr`. +r[cfg.macro] ### The `cfg` macro -r[cfg.macro] The built-in `cfg` macro takes in a single configuration predicate and evaluates to the `true` literal when the predicate is true and the `false` literal when it is false. diff --git a/src/const_eval.md b/src/const_eval.md index 66efed2a8..61e0f62f8 100644 --- a/src/const_eval.md +++ b/src/const_eval.md @@ -1,14 +1,13 @@ -# Constant evaluation r[const-eval] +# Constant evaluation r[const-eval.general] Constant evaluation is the process of computing the result of [expressions] during compilation. Only a subset of all expressions can be evaluated at compile-time. -## Constant expressions - r[const-eval.const-expr] +## Constant expressions r[const-eval.const-expr.general] Certain forms of expressions, called constant expressions, can be evaluated at @@ -140,9 +139,8 @@ surrounding generic parameters: such an expression must either be a single bare const generic parameter, or an arbitrary expression not making use of any generics. -## Const Functions - r[const-eval.const-fn] +## Const Functions r[const-eval.const-fn.general] A _const fn_ is a function that one is permitted to call from a const context. diff --git a/src/crates-and-source-files.md b/src/crates-and-source-files.md index 734ee3e98..e91eadb87 100644 --- a/src/crates-and-source-files.md +++ b/src/crates-and-source-files.md @@ -1,6 +1,5 @@ -# Crates and source files - r[crate] +# Crates and source files r[crate.syntax] > **Syntax**\ @@ -75,9 +74,8 @@ apply to the crate as a whole. #![warn(non_camel_case_types)] ``` -## Main Functions - r[crate.main] +## Main Functions r[crate.main.general] A crate that contains a `main` [function] can be compiled to an executable. @@ -124,17 +122,16 @@ use foo::bar as main; +r[crate.no_main] ### The `no_main` attribute -r[crate.no_main] The *`no_main` [attribute]* may be applied at the crate level to disable emitting the `main` symbol for an executable binary. This is useful when some other object being linked to defines `main`. -## The `crate_name` attribute - r[crate.crate_name] +## The `crate_name` attribute r[crate.crate_name.general] The *`crate_name` [attribute]* may be applied at the crate level to specify the diff --git a/src/destructors.md b/src/destructors.md index 247f44f71..7ec6d6fe1 100644 --- a/src/destructors.md +++ b/src/destructors.md @@ -58,9 +58,8 @@ core::mem::forget(partial_move.1); // When partial_move's scope ends, only the first field is dropped. ``` -## Drop scopes - r[destructors.scope] +## Drop scopes r[destructors.scope.intro] Each variable or temporary is associated to a *drop scope*. When control flow @@ -134,9 +133,9 @@ r[destructors.scope.nesting.other] * The parent of all other scopes is the scope of the immediately enclosing expression. +r[destructors.scope.params] ### Scopes of function parameters -r[destructors.scope.params] All function parameters are in the scope of the entire function body, so are dropped last when evaluating the function. Each actual function parameter is @@ -162,9 +161,8 @@ patterns_in_parameters( ); ``` -### Scopes of local variables - r[destructors.scope.bindings] +### Scopes of local variables r[destructors.scope.bindings.intro] Local variables declared in a `let` statement are associated to the scope of @@ -190,9 +188,8 @@ r[destructors.scope.bindings.match-pattern-order] If multiple patterns are used in the same arm for a `match` expression, then an unspecified pattern will be used to determine the drop order. -### Temporary scopes - r[destructors.scope.temporary] +### Temporary scopes r[destructors.scope.temporary.intro] The *temporary scope* of an expression is the scope that is used for the @@ -269,9 +266,9 @@ match PrintOnDrop("Matched value in final expression") { } ``` +r[destructors.scope.operands] ### Operands -r[destructors.scope.operands] Temporaries are also created to hold the result of operands to an expression while the other operands are evaluated. The temporaries are associated to the @@ -301,9 +298,9 @@ loop { } ``` +r[destructors.scope.const-promotion] ### Constant promotion -r[destructors.scope.const-promotion] Promotion of a value expression to a `'static` slot occurs when the expression could be written in a constant and borrowed, and that borrow could be dereferenced @@ -314,9 +311,9 @@ resulting value does not contain [interior mutability] or [destructors] (these properties are determined based on the value where possible, e.g. `&None` always has the type `&'static Option<_>`, as it contains nothing disallowed). +r[destructors.scope.lifetime-extension] ### Temporary lifetime extension -r[destructors.scope.lifetime-extension] > **Note**: The exact rules for temporary lifetime extension are subject to > change. This is describing the current behavior only. @@ -353,9 +350,8 @@ temporary scope then so does its operand. If an [indexing expression] has an extended temporary scope then the indexed expression also has an extended temporary scope. -#### Extending based on patterns - r[destructors.scope.lifetime-extension.patterns] +#### Extending based on patterns r[destructors.scope.lifetime-extension.patterns.extending] An *extending pattern* is either @@ -372,9 +368,9 @@ r[destructors.scope.lifetime-extension.patterns.let] If the pattern in a `let` statement is an extending pattern then the temporary scope of the initializer expression is extended. +r[destructors.scope.lifetime-extension.exprs] #### Extending based on expressions -r[destructors.scope.lifetime-extension.exprs] For a let statement with an initializer, an *extending expression* is an expression which is one of the following: @@ -426,9 +422,9 @@ let x = (&temp()).use_temp(); // ERROR # x; ``` +r[destructors.forget] ## Not running destructors -r[destructors.forget] [`std::mem::forget`] can be used to prevent the destructor of a variable from being run, and [`std::mem::ManuallyDrop`] provides a wrapper to prevent a diff --git a/src/identifiers.md b/src/identifiers.md index c510321bb..1fbc3cc2c 100644 --- a/src/identifiers.md +++ b/src/identifiers.md @@ -1,6 +1,5 @@ -# Identifiers - r[ident] +# Identifiers r[ident.syntax] > **Lexer:**\ @@ -53,17 +52,16 @@ Identifiers are restricted to the ASCII subset of [`XID_Start`] and [`XID_Contin * [`no_mangle`] attributed items * Item names in [external blocks] +r[ident.normalization] ## Normalization -r[ident.normalization] Identifiers are normalized using Normalization Form C (NFC) as defined in [Unicode Standard Annex #15][UAX15]. Two identifiers are equal if their NFC forms are equal. [Procedural][proc-macro] and [declarative][mbe] macros receive normalized identifiers in their input. -## Raw identifiers - r[ident.raw] +## Raw identifiers r[ident.raw.intro] A raw identifier is like a normal identifier, but prefixed by `r#`. (Note that diff --git a/src/inline-assembly.md b/src/inline-assembly.md index a6cdb1ed8..eaa604d48 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -1,6 +1,5 @@ -# Inline assembly - r[asm] +# Inline assembly r[asm.intro] Support for inline assembly is provided via the [`asm!`] and [`global_asm!`] macros. @@ -20,9 +19,9 @@ Support for inline assembly is stable on the following architectures: The compiler will emit an error if `asm!` is used on an unsupported target. +r[asm.example] ## Example -r[asm.example] ```rust # #[cfg(target_arch = "x86_64")] { @@ -44,9 +43,9 @@ assert_eq!(x, 4 * 6); # } ``` +r[asm.syntax] ## Syntax -r[asm.syntax] The following ABNF specifies the general syntax: @@ -64,9 +63,8 @@ asm := "asm!(" format_string *("," format_string) *("," operand) [","] ")" global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [","] ")" ``` -## Scope - r[asm.scope] +## Scope r[asm.scope.intro] Inline assembly can be used in one of two ways. @@ -80,9 +78,8 @@ r[asm.scope.global_asm] With the `global_asm!` macro, the assembly code is emitted in a global scope, outside a function. This can be used to hand-write entire functions using assembly code, and generally provides much more freedom to use arbitrary registers and assembler directives. -## Template string arguments - r[asm.ts-args] +## Template string arguments r[asm.ts-args.syntax] The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). @@ -123,9 +120,8 @@ Further constraints on the directives used by inline assembly are indicated by [ [format-syntax]: std::fmt#syntax [rfc-2795]: https://github.com/rust-lang/rfcs/pull/2795 -## Operand type - r[asm.operand-type] +## Operand type r[asm.operand-type.supported-operands] Several types of operands are supported: @@ -188,9 +184,8 @@ This is significant if two outputs point to the same place: that place will cont r[asm.operand-type.global_asm-restriction] Since `global_asm!` exists outside a function, it can only use `sym` and `const` operands. -## Register operands - r[asm.register-operands] +## Register operands r[asm.register-operands.register-or-class] Input and output operands can be specified either as an explicit register or as a register class from which the register allocator can select a register. @@ -315,9 +310,8 @@ When separate input and output expressions are specified for an `inout` operand, The only exception is if both operands are pointers or integers, in which case they are only required to have the same size. This restriction exists because the register allocators in LLVM and GCC sometimes cannot handle tied operands with different types. -## Register names - r[asm.register-names] +## Register names r[asm.register-names.supported-register-aliases] Some registers have multiple names. @@ -416,9 +410,8 @@ Some registers cannot be used for input or output operands: r[asm.register-names.fp-bp-reserved] The frame pointer and base pointer registers are reserved for internal use by LLVM. While `asm!` statements cannot explicitly specify the use of reserved registers, in some cases LLVM will allocate one of these reserved registers for `reg` operands. Assembly code making use of reserved registers should be careful since `reg` operands may use the same registers. -## Template modifiers - r[asm.template-modifiers] +## Template modifiers r[asm.template-modifiers.intro] The placeholders can be augmented by modifiers which are specified after the `:` in the curly braces. @@ -485,9 +478,8 @@ If all references to an operand already have modifiers then the warning is suppr [llvm-argmod]: http://llvm.org/docs/LangRef.html#asm-template-argument-modifiers -## ABI clobbers - r[asm.abi-clobbers] +## ABI clobbers r[asm.abi-clobbers.intro] The `clobber_abi` keyword can be used to apply a default set of clobbers to an `asm!` block. @@ -522,9 +514,8 @@ The following ABIs can be used with `clobber_abi`: The list of clobbered registers for each ABI is updated in rustc as architectures gain new registers: this ensures that `asm!` clobbers will continue to be correct when LLVM starts using these new registers in its generated code. -## Options - r[asm.options] +## Options r[asm.options.supported-options] Flags are used to further influence the behavior of the inline assembly block. @@ -582,9 +573,8 @@ r[asm.options.global_asm-restriction] `global_asm!` only supports the `att_syntax` and `raw` options. The remaining options are not meaningful for global-scope inline assembly -## Rules for inline assembly - r[asm.rules] +## Rules for inline assembly r[asm.rules.intro] To avoid undefined behavior, these rules must be followed when using function-scope inline assembly (`asm!`): @@ -693,9 +683,8 @@ r[asm.rules.x86-prefix-restriction] r[asm.rules.preserves_flags] > **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call. -### Correctness and Validity - r[asm.validity] +### Correctness and Validity r[asm.validity.necessary-but-not-sufficient] In addition to all of the previous rules, the string argument to `asm!` must ultimately become--- @@ -720,9 +709,8 @@ and the rules for assembly may include thousands of pages of architectural refer Programmers should exercise appropriate care, as invoking this `unsafe` capability comes with assuming the responsibility of not violating rules of both the compiler or the architecture. -### Directives Support - r[asm.directives] +### Directives Support r[asm.directives.subset-supported] Inline assembly supports a subset of the directives supported by both GNU AS and LLVM's internal assembler, given as follows. @@ -785,13 +773,13 @@ The following directives are guaranteed to be supported by the assembler: +r[asm.target-specific-directives] #### Target Specific Directive Support -r[asm.target-specific-directives] +r[asm.target-specific-directives.dwarf-unwinding] ##### Dwarf Unwinding -r[asm.target-specific-directives.dwarf-unwinding] The following directives are supported on ELF targets that support DWARF unwind info: @@ -818,9 +806,9 @@ The following directives are supported on ELF targets that support DWARF unwind - `.cfi_window_save` +r[asm.target-specific-directives.structured-exception-handling] ##### Structured Exception Handling -r[asm.target-specific-directives.structured-exception-handling] On targets with structured exception Handling, the following additional directives are guaranteed to be supported: - `.seh_endproc` @@ -832,9 +820,9 @@ On targets with structured exception Handling, the following additional directiv - `.seh_stackalloc` +r[asm.target-specific-directives.x86] ##### x86 (32-bit and 64-bit) -r[asm.target-specific-directives.x86] On x86 targets, both 32-bit and 64-bit, the following additional directives are guaranteed to be supported: - `.nops` - `.code16` @@ -847,9 +835,9 @@ Use of `.code16`, `.code32`, and `.code64` directives are only supported if the +r[asm.target-specific-directives.arm-32-bit] ##### ARM (32-bit) -r[asm.target-specific-directives.arm-32-bit] On ARM, the following additional directives are guaranteed to be supported: - `.even` diff --git a/src/input-format.md b/src/input-format.md index 517fb75f5..dee13465e 100644 --- a/src/input-format.md +++ b/src/input-format.md @@ -1,15 +1,13 @@ -# Input format - r[input] +# Input format r[input.intro] This chapter describes how a source file is interpreted as a sequence of tokens. See [Crates and source files] for a description of how programs are organised into files. -## Source encoding - r[input.encoding] +## Source encoding r[input.encoding.utf8] Each source file is interpreted as a sequence of Unicode characters encoded in UTF-8. @@ -17,23 +15,22 @@ Each source file is interpreted as a sequence of Unicode characters encoded in U r[input.encoding.invalid] It is an error if the file is not valid UTF-8. +r[input.byte-order-mark] ## Byte order mark removal -r[input.byte-order-mark] If the first character in the sequence is `U+FEFF` ([BYTE ORDER MARK]), it is removed. +r[input.crlf] ## CRLF normalization -r[input.crlf] Each pair of characters `U+000D` (CR) immediately followed by `U+000A` (LF) is replaced by a single `U+000A` (LF). Other occurrences of the character `U+000D` (CR) are left in place (they are treated as [whitespace]). -## Shebang removal - r[input.shebang] +## Shebang removal r[input.shebang.intro] If the remaining sequence begins with the characters `#!`, the characters up to and including the first `U+000A` (LF) are removed from the sequence. @@ -55,9 +52,9 @@ This prevents an [inner attribute] at the start of a source file being removed. > **Note**: The standard library [`include!`] macro applies byte order mark removal, CRLF normalization, and shebang removal to the file it reads. The [`include_str!`] and [`include_bytes!`] macros do not. +r[input.tokenization] ## Tokenization -r[input.tokenization] The resulting sequence of characters is then converted into tokens as described in the remainder of this chapter. diff --git a/src/interior-mutability.md b/src/interior-mutability.md index 7f7178473..f3e04150e 100644 --- a/src/interior-mutability.md +++ b/src/interior-mutability.md @@ -1,6 +1,5 @@ -# Interior Mutability - r[interior-mut] +# Interior Mutability r[interior-mut.intro] Sometimes a type needs to be mutated while having multiple aliases. In Rust this diff --git a/src/items.md b/src/items.md index d5733491c..1d9e25710 100644 --- a/src/items.md +++ b/src/items.md @@ -1,6 +1,5 @@ -# Items - r[items] +# Items r[items.syntax] > **Syntax:**\ diff --git a/src/items/associated-items.md b/src/items/associated-items.md index 3df2e0eee..ea95c1890 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -1,6 +1,5 @@ -# Associated Items - r[items.associated] +# Associated Items r[items.associated.syntax] > **Syntax**\ @@ -37,9 +36,8 @@ r[items.associated.trait-items] It is the declarations that make up the contract of traits and what is available on generic types. -## Associated functions and methods - r[items.associated.fn] +## Associated functions and methods r[items.associated.fn.intro] *Associated functions* are [functions] associated with a type. @@ -102,9 +100,8 @@ let _: f64 = ::from_i32(42); let _: f64 = f64::from_i32(42); ``` -### Methods - r[items.associated.fn.method] +### Methods r[items.associated.fn.method.intro] Associated functions whose first parameter is named `self` are called *methods* @@ -218,16 +215,14 @@ r[items.associated.fn.params.edition2015] > methods with anonymous parameters (e.g. `fn foo(u8)`). This is deprecated and > an error as of the 2018 edition. All parameters must have an argument name. -#### Attributes on method parameters - r[items.associated.fn.param-attributes] +#### Attributes on method parameters Attributes on method parameters follow the same rules and restrictions as [regular function parameters]. -## Associated Types - r[items.associated.type] +## Associated Types r[items.associated.type.intro] *Associated types* are [type aliases] associated with another type. @@ -394,9 +389,8 @@ trait Example { Given a reference to the associated type like `::Output`, the associated type itself must be `Ord`, and the type `Y` must be `Debug`. -### Required where clauses on generic associated types - r[items.associated.type.generic-where-clause] +### Required where clauses on generic associated types r[items.associated.type.generic-where-clause.intro] Generic associated type declarations on traits currently may require a list of @@ -465,9 +459,8 @@ trait StaticReturn { } ``` -## Associated Constants - r[items.associated.const] +## Associated Constants r[items.associated.const.intro] *Associated constants* are [constants] associated with a type. diff --git a/src/items/constant-items.md b/src/items/constant-items.md index bb8a43827..c5558e09f 100644 --- a/src/items/constant-items.md +++ b/src/items/constant-items.md @@ -1,6 +1,5 @@ -# Constant items - r[items.const] +# Constant items r[items.const.syntax] > **Syntax**\ @@ -54,9 +53,8 @@ The final value of a `const` item cannot contain references to anything mutable. r[items.const.expr-omission] The constant expression may only be omitted in a [trait definition]. -## Constants with Destructors - r[items.const.destructor] +## Constants with Destructors Constants can contain destructors. Destructors are run when the value goes out of scope. @@ -79,9 +77,8 @@ fn create_and_drop_zero_with_destructor() { } ``` -## Unnamed constant - r[items.const.unnamed] +## Unnamed constant r[items.const.unnamed.intro] Unlike an [associated constant], a [free] constant may be unnamed by using @@ -109,9 +106,8 @@ m!(const _: () = ();); // const _: () = (); ``` -## Evaluation - r[items.const.eval] +## Evaluation [Free][free] constants are always [evaluated][const_eval] at compile-time to surface panics. This happens even within an unused function: diff --git a/src/items/enumerations.md b/src/items/enumerations.md index 02b2b8373..d9d16bf0a 100644 --- a/src/items/enumerations.md +++ b/src/items/enumerations.md @@ -1,6 +1,5 @@ -# Enumerations - r[items.enum] +# Enumerations r[items.enum.syntax] > **Syntax**\ @@ -124,9 +123,8 @@ let z = StructLike { value: 123 }; // Struct expression. ``` -## Discriminants - r[items.enum.discriminant] +## Discriminants r[items.enum.discriminant.intro] Each enum instance has a _discriminant_: an integer logically associated to it @@ -139,9 +137,8 @@ another means of distinguishing variants) in its actual memory layout. ### Assigning discriminant values -#### Explicit discriminants - r[items.enum.discriminant.explicit] +#### Explicit discriminants r[items.enum.discriminant.explicit.intro] In two circumstances, the discriminant of a variant may be explicitly set by @@ -165,9 +162,8 @@ r[items.enum.discriminant.explicit.primitive-repr] } ``` -#### Implicit discriminants - r[items.enum.discriminant.implicit] +#### Implicit discriminants If a discriminant for a variant is not specified, then it is set to one higher than the discriminant of the previous variant in the declaration. If the @@ -185,9 +181,8 @@ let baz_discriminant = Foo::Baz as u32; assert_eq!(baz_discriminant, 123); ``` -#### Restrictions - r[items.enum.discriminant.restrictions] +#### Restrictions r[items.enum.discriminant.restrictions.same-discriminant] It is an error when two variants share the same discriminant. @@ -234,9 +229,8 @@ r[items.enum.discriminant.access-opaque] an enum value which can be compared. This cannot be used to get the value of the discriminant. -#### Casting - r[items.enum.discriminant.coercion] +#### Casting r[items.enum.discriminant.coercion.intro] If an enumeration is [unit-only] (with no tuple and struct variants), then its @@ -314,9 +308,8 @@ assert_eq!(1, tuple_like.discriminant()); assert_eq!(2, struct_like.discriminant()); ``` -## Zero-variant enums - r[items.enum.empty] +## Zero-variant enums r[items.enum.empty.intro] Enums with zero variants are known as *zero-variant enums*. As they have @@ -336,9 +329,8 @@ let x: ZeroVariants = panic!(); let y: u32 = x; // mismatched type error ``` -## Variant visibility - r[items.enum.variant-visibility] +## Variant visibility Enum variants syntactically allow a [_Visibility_] annotation, but this is rejected when the enum is validated. This allows items to be parsed with a diff --git a/src/items/extern-crates.md b/src/items/extern-crates.md index 85f10630e..8746dda0b 100644 --- a/src/items/extern-crates.md +++ b/src/items/extern-crates.md @@ -1,6 +1,5 @@ -# Extern crate declarations - r[items.extern-crate] +# Extern crate declarations r[items.extern-crate.syntax] > **Syntax:**\ @@ -63,9 +62,8 @@ Here is an example: extern crate hello_world; // hyphen replaced with an underscore ``` -## Underscore Imports - r[items.extern-crate.underscore] +## Underscore Imports r[items.extern-crate.underscore.intro] An external crate dependency can be declared without binding its name in scope @@ -77,9 +75,8 @@ r[items.extern-crate.underscore.macro_use] The [`macro_use` attribute] works as usual and imports the macro names into the [`macro_use` prelude]. -## The `no_link` attribute - r[items.extern-crate.no_link] +## The `no_link` attribute The *`no_link` attribute* may be specified on an `extern crate` item to prevent linking the crate into the output. This is commonly used to load a diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 74aa5cedb..1f224b14d 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -1,6 +1,5 @@ -# External blocks - r[items.extern] +# External blocks r[items.extern.syntax] > **Syntax**\ @@ -39,9 +38,8 @@ The `unsafe` keyword is semantically required to appear before the `extern` keyw r[items.extern.edition2024] > **Edition differences**: Prior to the 2024 edition, the `unsafe` keyword is optional. The `safe` and `unsafe` item qualifiers are only allowed if the external block itself is marked as `unsafe`. -## Functions - r[items.extern.fn] +## Functions r[items.extern.fn.body] Functions within external blocks are declared in the same way as other Rust @@ -71,9 +69,8 @@ type `extern "abi" for<'l1, ..., 'lm> fn(A1, ..., An) -> R`, where `'l1`, ... `'lm` are its lifetime parameters, `A1`, ..., `An` are the declared types of its parameters, `R` is the declared return type. -## Statics - r[items.extern.static] +## Statics r[items.extern.static.intro] Statics within external blocks are declared in the same way as [statics] outside of external blocks, @@ -94,9 +91,8 @@ the static to be initialized before Rust code reads from it. Once Rust code runs, mutating an immutable static (from inside or outside Rust) is UB, except if the mutation happens to bytes inside of an `UnsafeCell`. -## ABI - r[items.extern.abi] +## ABI r[items.extern.abi.intro] By default external blocks assume that the library they are calling uses the @@ -159,9 +155,8 @@ r[items.extern.abi.thiscall] r[items.extern.abi.efiapi] * `unsafe extern "efiapi"` -- The ABI used for [UEFI] functions. -## Variadic functions - r[items.extern.variadic] +## Variadic functions Functions within external blocks may be variadic by specifying `...` as the last argument. The variadic parameter may optionally be specified with an @@ -175,16 +170,14 @@ unsafe extern "C" { } ``` -## Attributes on extern blocks - r[items.extern.attributes] +## Attributes on extern blocks r[items.extern.attributes.intro] The following [attributes] control the behavior of external blocks. -### The `link` attribute - r[items.extern.attributes.link] +### The `link` attribute r[items.extern.attributes.link.intro] The *`link` attribute* specifies the name of a native library that the @@ -258,9 +251,8 @@ this to satisfy the linking requirements of extern blocks elsewhere in your code (including upstream crates) instead of adding the attribute to each extern block. -#### Linking modifiers: `bundle` - r[items.extern.attributes.link.modifiers.bundle] +#### Linking modifiers: `bundle` r[items.extern.attributes.link.modifiers.bundle.allowed-kinds] This modifier is only compatible with the `static` linking kind. @@ -288,9 +280,8 @@ The default for this modifier is `+bundle`. More implementation details about this modifier can be found in [`bundle` documentation for rustc]. -#### Linking modifiers: `whole-archive` - r[items.extern.attributes.link.modifiers.whole-archive] +#### Linking modifiers: `whole-archive` r[items.extern.attributes.link.modifiers.whole-archive.allowed-kinds] This modifier is only compatible with the `static` linking kind. @@ -306,9 +297,8 @@ The default for this modifier is `-whole-archive`. More implementation details about this modifier can be found in [`whole-archive` documentation for rustc]. -### Linking modifiers: `verbatim` - r[items.extern.attributes.link.modifiers.verbatim] +### Linking modifiers: `verbatim` r[items.extern.attributes.link.modifiers.verbatim.allowed-kinds] This modifier is compatible with all linking kinds. @@ -328,9 +318,8 @@ The default for this modifier is `-verbatim`. More implementation details about this modifier can be found in [`verbatim` documentation for rustc]. -#### `dylib` versus `raw-dylib` - r[items.extern.attributes.link.kind-raw-dylib] +#### `dylib` versus `raw-dylib` r[items.extern.attributes.link.kind-raw-dylib.intro] On Windows, linking against a dynamic library requires that an import library @@ -349,9 +338,8 @@ r[items.extern.attributes.link.kind-raw-dylib.platform-specific] `raw-dylib` is only supported on Windows. Using it when targeting other platforms will result in a compiler error. -#### The `import_name_type` key - r[items.extern.attributes.link.import_name_type] +#### The `import_name_type` key r[items.extern.attributes.link.import_name_type.intro] On x86 Windows, names of functions are "decorated" (i.e., have a specific prefix @@ -386,9 +374,8 @@ r[items.extern.attributes.link.import_name_type.platform-specific] The `import_name_type` key is only supported on x86 Windows. Using it when targeting other platforms will result in a compiler error. -### The `link_name` attribute - r[items.extern.attributes.link_name] +### The `link_name` attribute r[items.extern.attributes.link_name.intro] The *`link_name` attribute* may be specified on declarations inside an `extern` @@ -408,9 +395,8 @@ r[items.extern.attributes.link_name.exclusive] Using this attribute with the `link_ordinal` attribute will result in a compiler error. -### The `link_ordinal` attribute - r[items.extern.attributes.link_ordinal] +### The `link_ordinal` attribute r[items.extern.attributes.link_ordinal.intro] The *`link_ordinal` attribute* can be applied on declarations inside an `extern` @@ -439,9 +425,8 @@ r[items.extern.attributes.link_ordinal.exclusive] Using this attribute with the `link_name` attribute will result in a compiler error. -### Attributes on function parameters - r[items.extern.attributes.fn-parameters] +### Attributes on function parameters Attributes on extern function parameters follow the same rules and restrictions as [regular function parameters]. diff --git a/src/items/functions.md b/src/items/functions.md index 1fe173e70..a4d0ee6d0 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -1,6 +1,5 @@ -# Functions - r[items.fn] +# Functions r[items.fn.syntax] > **Syntax**\ @@ -82,9 +81,8 @@ fn answer_to_life_the_universe_and_everything() -> i32 { r[items.fn.safety-qualifiers] The `safe` function is semantically only allowed when used in an [`extern` block]. -## Function parameters - r[items.fn.params] +## Function parameters r[items.fn.params.intro] Function parameters are irrefutable [patterns], so any pattern that is valid in @@ -107,9 +105,8 @@ A parameter with the `...` token indicates a [variadic function], and may only be used as the last parameter of an [external block] function. The variadic parameter may have an optional identifier, such as `args: ...`. -## Function body - r[items.fn.body] +## Function body r[items.fn.body.intro] The body block of a function is conceptually wrapped in another block that first binds the @@ -133,9 +130,8 @@ r[items.fn.body.bodyless] Functions without a body block are terminated with a semicolon. This form may only appear in a [trait] or [external block]. -## Generic functions - r[items.fn.generics] +## Generic functions r[items.fn.generics.intro] A _generic function_ allows one or more _parameterized types_ to appear in its @@ -186,9 +182,8 @@ component after the function name. This might be necessary if there is not sufficient context to determine the type parameters. For example, `mem::size_of::() == 4`. -## Extern function qualifier - r[items.fn.extern] +## Extern function qualifier r[items.fn.extern.intro] The `extern` function qualifier allows providing function _definitions_ that can @@ -266,9 +261,8 @@ with such ABIs causes the process to abort. > **Note**: The LLVM backend of the `rustc` implementation aborts the process by executing an illegal instruction. -## Const functions - r[items.fn.const] +## Const functions r[items.fn.const.intro] Functions qualified with the `const` keyword are [const functions], as are @@ -281,9 +275,8 @@ Const functions may use the [`extern`] function qualifier. r[items.fn.const.exclusivity] Const functions are not allowed to be [async](#async-functions). -## Async functions - r[items.fn.async] +## Async functions r[items.fn.async.intro] Functions may be qualified as async, and this can also be combined with the @@ -347,9 +340,8 @@ r[items.fn.async.edition2018] > **Edition differences**: Async functions are only available beginning with > Rust 2018. -### Combining `async` and `unsafe` - r[items.fn.async.safety] +### Combining `async` and `unsafe` r[items.fn.async.safety.intro] It is legal to declare a function that is both async and unsafe. The @@ -392,9 +384,8 @@ dereferenced that pointer. This implies that `x` would have to be valid until the future is finished executing, and it is the caller's responsibility to ensure that. -## Attributes on functions - r[items.fn.attributes] +## Attributes on functions r[items.fn.attributes.intro] [Outer attributes][attributes] are allowed on functions. [Inner @@ -419,9 +410,8 @@ attributes], [`must_use`], [the procedural macro attributes], [the testing attributes], and [the optimization hint attributes]. Functions also accept attributes macros. -## Attributes on function parameters - r[items.fn.param-attributes] +## Attributes on function parameters r[items.fn.param-attributes.intro] [Outer attributes][attributes] are allowed on function parameters and the diff --git a/src/items/generics.md b/src/items/generics.md index 5fab8de8e..798413aab 100644 --- a/src/items/generics.md +++ b/src/items/generics.md @@ -1,6 +1,5 @@ -# Generic parameters - r[items.generics] +# Generic parameters r[items.generics.syntax] > **Syntax**\ @@ -57,9 +56,8 @@ referred to with path syntax. r[items.generics.invalid-lifetimes] `'_` and `'_static` are not valid lifetime parameters. -### Const generics - r[items.generics.const] +### Const generics r[items.generics.const.intro] *Const generic parameters* allow items to be generic over constant values. @@ -232,9 +230,8 @@ fn generic() { } ``` -## Where clauses - r[items.generics.where] +## Where clauses r[items.generics.where.syntax] > **Syntax**\ @@ -272,9 +269,8 @@ where } ``` -## Attributes - r[items.generics.attributes] +## Attributes Generic lifetime and type parameters allow [attributes] on them. There are no built-in attributes that do anything in this position, although custom derive diff --git a/src/items/implementations.md b/src/items/implementations.md index 5bde1ec21..dff5c03eb 100644 --- a/src/items/implementations.md +++ b/src/items/implementations.md @@ -1,6 +1,5 @@ -# Implementations - r[items.impl] +# Implementations r[items.impl.syntax] > **Syntax**\ @@ -34,9 +33,8 @@ There are two types of implementations: - inherent implementations - [trait] implementations -## Inherent Implementations - r[items.impl.inherent] +## Inherent Implementations r[items.impl.inherent.intro] An inherent implementation is defined as the sequence of the `impl` keyword, @@ -100,9 +98,8 @@ fn main() { } ``` -## Trait Implementations - r[items.impl.trait] +## Trait Implementations r[items.impl.trait.intro] A _trait implementation_ is defined like an inherent implementation except that @@ -161,9 +158,8 @@ impl Shape for Circle { } ``` -### Trait Implementation Coherence - r[items.impl.trait.coherence] +### Trait Implementation Coherence r[items.impl.trait.coherence.intro] A trait implementation is considered incoherent if either the orphan rules check fails @@ -175,9 +171,8 @@ traits the implementation is for, the implementations can be instantiated with the same type. -#### Orphan rules - r[items.impl.trait.orphan-rule] +#### Orphan rules r[items.impl.trait.orphan-rule.general] Given `impl Trait for T0`, an `impl` is valid only if at @@ -198,9 +193,8 @@ Note that for the purposes of coherence, [fundamental types] are special. The `T` in `Box` is not considered covered, and `Box` is considered local. -## Generic Implementations - r[items.impl.generics] +## Generic Implementations r[items.impl.generics.intro] An implementation can take [generic parameters], which can be used in the rest @@ -298,9 +292,8 @@ impl<'a> HasAssocType for Struct { } ``` -## Attributes on Implementations - r[items.impl.attributes] +## Attributes on Implementations Implementations may contain outer [attributes] before the `impl` keyword and inner [attributes] inside the brackets that contain the associated items. Inner diff --git a/src/items/modules.md b/src/items/modules.md index 67322f845..6ffc56d09 100644 --- a/src/items/modules.md +++ b/src/items/modules.md @@ -1,6 +1,5 @@ -# Modules - r[items.mod] +# Modules r[items.mod.syntax] > **Syntax:**\ @@ -55,9 +54,8 @@ keyword, but it is rejected at a semantic level. This allows macros to consume the syntax and make use of the `unsafe` keyword, before removing it from the token stream. -## Module Source Filenames - r[items.mod.outlined] +## Module Source Filenames r[items.mod.outlined.intro] A module without a body is loaded from an external file. When the module does @@ -87,9 +85,8 @@ alternately be expressed with `crate::util`'s contents in a file named > convention as it is more consistent, and avoids having many files named > `mod.rs` within a project. -### The `path` attribute - r[items.mod.outlined.path] +### The `path` attribute r[items.mod.outlined.path.intro] The directories and files used for loading external file modules can be @@ -150,9 +147,8 @@ mod thread { } ``` -## Attributes on Modules - r[items.mod.attributes] +## Attributes on Modules r[items.mod.attributes.intro] Modules, like all items, accept outer attributes. They also accept inner diff --git a/src/items/static-items.md b/src/items/static-items.md index d9e61e648..7877b987f 100644 --- a/src/items/static-items.md +++ b/src/items/static-items.md @@ -1,6 +1,5 @@ -# Static items - r[items.static] +# Static items r[items.static.syntax] > **Syntax**\ @@ -46,9 +45,8 @@ provided for free static items. r[items.static.safety-qualifiers] The `safe` and `unsafe` qualifiers are semantically only allowed when used in an [external block]. -## Statics & generics - r[items.static.generics] +## Statics & generics A static item defined in a generic scope (for example in a blanket or default implementation) will result in exactly one static item being defined, as if @@ -96,9 +94,8 @@ blanket_impl: counter was 0 blanket_impl: counter was 1 ``` -## Mutable statics - r[items.static.mut] +## Mutable statics r[items.static.mut.intro] If a static item is declared with the `mut` keyword, then it is allowed to be @@ -148,9 +145,8 @@ r[items.static.mut.sync] Mutable statics have the same restrictions as normal statics, except that the type does not have to implement the `Sync` trait. -## Using Statics or Consts - r[items.static.alternate] +## Using Statics or Consts It can be confusing whether or not you should use a constant item or a static item. Constants should, in general, be preferred over statics unless one of the diff --git a/src/items/structs.md b/src/items/structs.md index 8a6c9eb22..d9dab7273 100644 --- a/src/items/structs.md +++ b/src/items/structs.md @@ -1,6 +1,5 @@ -# Structs - r[items.struct] +# Structs r[items.struct.syntax] > **Syntax**\ diff --git a/src/items/traits.md b/src/items/traits.md index 0d0a9ecbd..00cdd885f 100644 --- a/src/items/traits.md +++ b/src/items/traits.md @@ -1,6 +1,5 @@ -# Traits - r[items.traits] +# Traits r[items.traits.syntax] > **Syntax**\ @@ -59,15 +58,13 @@ trait Example { r[items.traits.const-fn] Trait functions are not allowed to be [`const`]. -## Trait bounds - r[items.traits.bounds] +## Trait bounds Generic items may use traits as [bounds] on their type parameters. -## Generic traits - r[items.traits.generic] +## Generic traits Type parameters can be specified for a trait to make it generic. These appear after the trait name, using the same syntax used in [generic functions]. @@ -81,9 +78,8 @@ trait Seq { ``` -## Dyn compatibility - r[items.traits.dyn-compatible] +## Dyn compatibility r[items.traits.dyn-compatible.intro] A dyn-compatible trait can be the base trait of a [trait object]. A trait is @@ -207,9 +203,8 @@ impl WithSelf for S {} let obj: Box = Box::new(S); // ERROR: cannot use `Self` type parameter ``` -## Supertraits - r[items.traits.supertraits] +## Supertraits r[items.traits.supertraits.intro] **Supertraits** are traits that are required to be implemented for a type to @@ -278,9 +273,8 @@ let circle = Box::new(circle) as Box; let nonsense = circle.radius() * circle.area(); ``` -## Unsafe traits - r[items.traits.safety] +## Unsafe traits r[items.traits.safety.intro] Traits items that begin with the `unsafe` keyword indicate that *implementing* the @@ -289,9 +283,8 @@ The [trait implementation] must also begin with the `unsafe` keyword. [`Sync`] and [`Send`] are examples of unsafe traits. -## Parameter patterns - r[items.traits.params] +## Parameter patterns r[items.traits.params.allowed-patterns] Function or method declarations without a body only allow [IDENTIFIER] or @@ -331,9 +324,8 @@ trait T { } ``` -## Item visibility - r[items.traits.associated-visibility] +## Item visibility r[items.traits.associated-visibility.intro] Trait items syntactically allow a [_Visibility_] annotation, but this is diff --git a/src/items/type-aliases.md b/src/items/type-aliases.md index d496b8c60..488a31f8c 100644 --- a/src/items/type-aliases.md +++ b/src/items/type-aliases.md @@ -1,6 +1,5 @@ -# Type aliases - r[items.type] +# Type aliases r[items.type.syntax] > **Syntax**\ diff --git a/src/items/unions.md b/src/items/unions.md index 835f924ea..00c1f2741 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -1,6 +1,5 @@ -# Unions - r[items.union] +# Unions r[items.union.syntax] > **Syntax**\ @@ -51,9 +50,8 @@ to manually define what happens when it gets dropped. r[items.union.fieldless] Unions without any fields are not accepted by the compiler, but can be accepted by macros. -## Initialization of a union - r[items.union.init] +## Initialization of a union r[items.union.init.intro] A value of a union type can be created using the same syntax that is used for @@ -77,9 +75,8 @@ struct fields: let f = unsafe { u.f1 }; ``` -## Reading and writing union fields - r[items.union.fields] +## Reading and writing union fields r[items.union.fields.intro] Unions have no notion of an "active field". Instead, every union access just @@ -121,9 +118,8 @@ arbitrary data, but cannot cause undefined behavior. (Note that union field types can never have drop glue, so a union field write will never implicitly drop anything.) -## Pattern matching on unions - r[items.union.pattern] +## Pattern matching on unions r[items.union.pattern.intro] Another way to access union fields is to use pattern matching. @@ -180,9 +176,8 @@ fn is_zero(v: Value) -> bool { } ``` -## References to union fields - r[items.union.ref] +## References to union fields r[items.union.ref.intro] Since union fields share common storage, gaining write access to one field of a diff --git a/src/items/use-declarations.md b/src/items/use-declarations.md index ca70b8a8b..60ccf2272 100644 --- a/src/items/use-declarations.md +++ b/src/items/use-declarations.md @@ -1,6 +1,5 @@ -# Use declarations - r[items.use] +# Use declarations r[items.use.syntax] > **Syntax:**\ @@ -70,9 +69,8 @@ fn main() { } ``` -## `use` Visibility - r[items.use.visibility] +## `use` Visibility r[items.use.visibility.intro] Like items, `use` declarations are private to the containing module, by @@ -106,9 +104,8 @@ fn main() { In this example, the module `quux` re-exports two public names defined in `foo`. -## `use` Paths - r[items.use.path] +## `use` Paths r[items.use.path.intro] The [paths] that are allowed in a `use` item follow the [_SimplePath_] grammar and are similar to the paths that may be used in an expression. @@ -165,9 +162,8 @@ r[items.use.path.edition2015] > Thus, [`extern crate`] declarations are still required in 2015 to reference an external crate in a `use` declaration. > Beginning with the 2018 edition, `use` declarations can specify an external crate dependency the same way `extern crate` can. -## `as` renames - r[items.use.as] +## `as` renames The `as` keyword can be used to change the name of an imported entity. For example: @@ -181,9 +177,8 @@ mod inner { } ``` -## Brace syntax - r[items.use.multiple-syntax] +## Brace syntax r[items.use.multiple-syntax.intro] Braces can be used in the last segment of the path to import multiple entities from the previous segment, or, if there are no previous segments, from the current scope. @@ -204,9 +199,8 @@ An empty brace does not import anything, though the leading path is validated th r[items.use.multiple-syntax.edition2015] > **Edition differences**: In the 2015 edition, paths are relative to the crate root, so an import such as `use {foo, bar};` will import the names `foo` and `bar` from the crate root, whereas starting in 2018, those names are relative to the current scope. -## `self` imports - r[items.use.self] +## `self` imports r[items.use.self.intro] The keyword `self` may be used within [brace syntax](#brace-syntax) to create a binding of the parent entity under its own name. @@ -250,9 +244,8 @@ fn main() { > The usage of `self` as the first segment and inside a `use` brace is logically the same; it means the current module of the parent segment, or the current module if there is no parent segment. > See [`self`] in the paths chapter for more information on the meaning of a leading `self`. -## Glob imports - r[items.use.glob] +## Glob imports r[items.use.glob.intro] The `*` character may be used as the last segment of a `use` path to import all importable entities from the entity of the preceding segment. @@ -319,9 +312,8 @@ r[items.use.glob.edition2015] > **Edition differences**: In the 2015 edition, paths are relative to the crate root, so an import such as `use *;` is valid, and it means to import everything from the crate root. > This cannot be used in the crate root itself. -## Underscore Imports - r[items.use.as-underscore] +## Underscore Imports r[items.use.as-underscore.intro] Items can be imported without binding to a name by using an underscore with @@ -368,9 +360,8 @@ m!(use std as _;); // use std as _; ``` -## Restrictions - r[items.use.restrictions] +## Restrictions The following are restrictions for valid `use` declarations: @@ -398,9 +389,8 @@ r[items.use.restrictions.variant] use TypeAlias::MyVariant; //~ ERROR ``` -## Ambiguities - r[items.use.ambiguities] +## Ambiguities > **Note**: This section is incomplete. diff --git a/src/linkage.md b/src/linkage.md index ff41a140f..23bd44c2c 100644 --- a/src/linkage.md +++ b/src/linkage.md @@ -1,6 +1,6 @@ +r[link] # Linkage -r[link] > Note: This section is described more in terms of the compiler than of > the language. @@ -166,9 +166,8 @@ In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for all compilation needs, and the other options are just available if more fine-grained control is desired over the output format of a crate. -## Static and dynamic C runtimes - r[link.crt] +## Static and dynamic C runtimes r[link.crt.intro] The standard library in general strives to support both statically linked and diff --git a/src/macro-ambiguity.md b/src/macro-ambiguity.md index 159b86799..36049fcba 100644 --- a/src/macro-ambiguity.md +++ b/src/macro-ambiguity.md @@ -1,14 +1,13 @@ +r[macro.ambiguity] # Appendix: Macro Follow-Set Ambiguity Formal Specification -r[macro.ambiguity] This page documents the formal specification of the follow rules for [Macros By Example]. They were originally specified in [RFC 550], from which the bulk of this text is copied, and expanded upon in subsequent RFCs. -## Definitions & Conventions - r[macro.ambiguity.convention] +## Definitions & Conventions r[macro.ambiguity.convention.defs] - `macro`: anything invocable as `foo!(...)` in source code. @@ -109,9 +108,8 @@ true, because the `vis` matcher can match an empty fragment. Thus, for the purposes of the formalism, we will treat `$v:vis` as actually being `$($v:vis)?`, with a requirement that the matcher match an empty fragment. -### The Matcher Invariants - r[macro.ambiguity.invariant] +### The Matcher Invariants r[macro.ambiguity.invariant.list] To be valid, a matcher must meet the following three invariants. The definitions @@ -151,9 +149,8 @@ and significant reliance on the behaviour. It is currently undecided what to do about this going forward. Macros that do not respect the behaviour may become invalid in a future edition of Rust. See the [tracking issue].** -### FIRST and FOLLOW, informally - r[macro.ambiguity.sets] +### FIRST and FOLLOW, informally r[macro.ambiguity.sets.intro] A given matcher M maps to three sets: FIRST(M), LAST(M) and FOLLOW(M). @@ -195,9 +192,8 @@ at this point may want to jump ahead to the [examples of FIRST/LAST](#examples-of-first-and-last) before reading their formal definitions.) -### FIRST, LAST - r[macro.ambiguity.sets.def] +### FIRST, LAST r[macro.ambiguity.sets.def.intro] Below are formal inductive definitions for FIRST and LAST. @@ -206,9 +202,8 @@ r[macro.ambiguity.sets.def.notation] "A ∪ B" denotes set union, "A ∩ B" denotes set intersection, and "A \ B" denotes set difference (i.e. all elements of A that are not present in B). -#### FIRST - r[macro.ambiguity.sets.def.first] +#### FIRST r[macro.ambiguity.sets.def.first.intro] FIRST(M) is defined by case analysis on the sequence M and the structure of its @@ -260,9 +255,8 @@ then by definition ε ∉ ALPHA\_SET(M). Otherwise, the complex NT can accept ze repetitions, and then ALPHA\_SET(M) = FOLLOW(`α`). So this definition is correct with respect to \varepsilon as well. -#### LAST - r[macro.ambiguity.sets.def.last] +#### LAST r[macro.ambiguity.sets.def.last.intro] LAST(M), defined by case analysis on M itself (a sequence of token-trees): @@ -361,9 +355,8 @@ Here are similar examples but now for LAST. * LAST(`$( $d:ident $e:expr );* $(h)* $( f ;)+`) = { `;` } * LAST(`$( $d:ident $e:expr );* $(h)* $( f ;)+ g`) = { `g` } -### FOLLOW(M) - r[macro.ambiguity.sets.def.follow] +### FOLLOW(M) r[macro.ambiguity.sets.def.follow.intro] Finally, the definition for FOLLOW(M) is built up as follows. pat, expr, etc. diff --git a/src/macros-by-example.md b/src/macros-by-example.md index 90c21baab..19c069b6e 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -1,6 +1,5 @@ -# Macros By Example - r[macro.decl] +# Macros By Example r[macro.decl.syntax] > **Syntax**\ @@ -53,9 +52,8 @@ the matcher and the transcriber must be surrounded by delimiters. Macros can expand to expressions, statements, items (including traits, impls, and foreign items), types, or patterns. -## Transcribing - r[macro.decl.transcription] +## Transcribing r[macro.decl.transcription.intro] When a macro is invoked, the macro expander looks up macro invocations by name, @@ -86,9 +84,9 @@ delimiters for the matcher will match any pair of delimiters. Thus, for instance, the matcher `(())` will match `{()}` but not `{{}}`. The character `$` cannot be matched or transcribed literally. +r[macro.decl.transcription.fragment] ### Forwarding a matched fragment -r[macro.decl.transcription.fragment] When forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type. The second macro @@ -126,9 +124,8 @@ macro_rules! bar { foo!(3); ``` -## Metavariables - r[macro.decl.meta] +## Metavariables r[macro.decl.meta.intro] In the matcher, `$` _name_ `:` _fragment-specifier_ matches a Rust syntax @@ -174,9 +171,8 @@ r[macro.decl.meta.edition2024] > > The `expr_2021` fragment specifier exists to maintain backwards compatibility with editions before 2024. -## Repetitions - r[macro.decl.repetition] +## Repetitions r[macro.decl.repetition.intro] In both the matcher and transcriber, repetitions are indicated by placing the @@ -225,9 +221,8 @@ compiler knows how to expand them properly: not have the same number. This requirement applies to every layer of nested repetitions. -## Scoping, Exporting, and Importing - r[macro.decl.scope] +## Scoping, Exporting, and Importing r[macro.decl.scope.intro] For historical reasons, the scoping of macros by example does not work entirely @@ -255,9 +250,8 @@ lazy_static!{lazy} // Textual lookup finds our macro first. self::lazy_static!{} // Path-based lookup ignores our macro, finds imported one. ``` -### Textual Scope - r[macro.decl.scope.textual] +### Textual Scope r[macro.decl.scope.textual.intro] Textual scope is based largely on the order that things appear in source files, @@ -333,9 +327,8 @@ fn foo() { // m!(); // Error: m is not in scope. ``` -### The `macro_use` attribute - r[macro.decl.scope.macro_use] +### The `macro_use` attribute r[macro.decl.scope.macro_use.mod-decl] The *`macro_use` attribute* has two purposes. First, it can be used to make a @@ -376,9 +369,8 @@ r[macro.decl.scope.macro_use.export] Macros to be imported with `#[macro_use]` must be exported with `#[macro_export]`, which is described below. -### Path-Based Scope - r[macro.decl.scope.path] +### Path-Based Scope r[macro.decl.scope.path.intro] By default, a macro has no path-based scope. However, if it has the @@ -406,9 +398,8 @@ r[macro.decl.scope.path.export] Macros labeled with `#[macro_export]` are always `pub` and can be referred to by other crates, either by path or by `#[macro_use]` as described above. -## Hygiene - r[macro.decl.hygiene] +## Hygiene r[macro.decl.hygiene.intro] Macros by example have _mixed-site hygiene_. This means that [loop labels], [block labels], and local variables are looked up at the macro definition site while other symbols are looked up at the macro invocation site. For example: @@ -532,9 +523,8 @@ macro_rules! helper { } ``` -## Follow-set Ambiguity Restrictions - r[macro.decl.follow-set] +## Follow-set Ambiguity Restrictions r[macro.decl.follow-set.intro] The parser used by the macro system is reasonably powerful, but it is limited in diff --git a/src/procedural-macros.md b/src/procedural-macros.md index 0ae6e26d5..d717d9a50 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -1,6 +1,5 @@ -## Procedural Macros - r[macro.proc] +## Procedural Macros r[macro.proc.intro] *Procedural macros* allow creating syntax extensions as execution of a function. @@ -43,9 +42,8 @@ r[macro.proc.error] Procedural macros have two ways of reporting errors. The first is to panic. The second is to emit a [`compile_error`] macro invocation. -### The `proc_macro` crate - r[macro.proc.proc_macro] +### The `proc_macro` crate r[macro.proc.proc_macro.intro] Procedural macro crates almost always will link to the compiler-provided @@ -68,9 +66,9 @@ code within a program and are primarily used for error reporting. While you cannot modify a `Span` itself, you can always change the `Span` *associated* with any token, such as through getting a `Span` from another token. +r[macro.proc.hygiene] ### Procedural macro hygiene -r[macro.proc.hygiene] Procedural macros are *unhygienic*. This means they behave as if the output token stream was simply written inline to the code it's next to. This means that @@ -82,9 +80,8 @@ items in libraries (for example, `::std::option::Option` instead of `Option`) or by ensuring that generated functions have names that are unlikely to clash with other functions (like `__internal_foo` instead of `foo`). -### Function-like procedural macros - r[macro.proc.function] +### Function-like procedural macros r[macro.proc.function.intro] *Function-like procedural macros* are procedural macros that are invoked using @@ -134,9 +131,8 @@ position, which includes [statements], [expressions], [patterns], [type expressions], [item] positions, including items in [`extern` blocks], inherent and trait [implementations], and [trait definitions]. -### Derive macros - r[macro.proc.derive] +### Derive macros r[macro.proc.derive.intro] *Derive macros* define new inputs for the [`derive` attribute]. These macros @@ -186,9 +182,8 @@ fn main() { } ``` -#### Derive macro helper attributes - r[macro.proc.derive.attributes] +#### Derive macro helper attributes r[macro.proc.derive.attributes.intro] Derive macros can add additional [attributes] into the scope of the [item] @@ -226,9 +221,8 @@ struct Struct { } ``` -### Attribute macros - r[macro.proc.attribute] +### Attribute macros r[macro.proc.attribute.intro] *Attribute macros* define new [outer attributes][attributes] which can be @@ -313,9 +307,8 @@ fn invoke4() {} // out: item: "fn invoke4() {}" ``` -### Declarative macro tokens and procedural macro tokens - r[macro.proc.token] +### Declarative macro tokens and procedural macro tokens r[macro.proc.token.intro] Declarative `macro_rules` macros and procedural macros use similar, but diff --git a/src/statements-and-expressions.md b/src/statements-and-expressions.md index b7496964c..f6688c64b 100644 --- a/src/statements-and-expressions.md +++ b/src/statements-and-expressions.md @@ -1,6 +1,6 @@ +r[stmt-expr] # Statements and expressions -r[stmt-expr] Rust is _primarily_ an expression language. This means that most forms of value-producing or effect-causing evaluation are directed by the uniform syntax category of _expressions_. diff --git a/src/statements.md b/src/statements.md index 5ee35d9ab..713d9247e 100644 --- a/src/statements.md +++ b/src/statements.md @@ -1,6 +1,5 @@ -# Statements - r[statement] +# Statements r[statement.syntax] > **Syntax**\ @@ -17,18 +16,17 @@ A *statement* is a component of a [block], which is in turn a component of an ou r[statement.kind] Rust has two kinds of statement: [declaration statements](#declaration-statements) and [expression statements](#expression-statements). +r[statement.decl] ## Declaration statements -r[statement.decl] A *declaration statement* is one that introduces one or more *names* into the enclosing statement block. The declared names may denote new variables or new [items][item]. The two kinds of declaration statements are item declarations and `let` statements. -### Item declarations - r[statement.item] +### Item declarations r[statement.item.intro] An *item declaration statement* has a syntactic form identical to an [item declaration][item] within a [module]. @@ -55,9 +53,8 @@ fn outer() { } ``` -### `let` statements - r[statement.let] +### `let` statements r[statement.let.syntax] > **Syntax**\ @@ -98,9 +95,8 @@ let [u, v] = [v[0], v[1]] else { // This pattern is irrefutable, so the compiler }; ``` -## Expression statements - r[statement.expr] +## Expression statements r[statement.expr.syntax] > **Syntax**\ @@ -148,9 +144,9 @@ if true { }; ``` +r[statement.attribute] ## Attributes on Statements -r[statement.attribute] Statements accept [outer attributes]. The attributes that have meaning on a statement are [`cfg`], and [the lint check attributes]. diff --git a/src/subtyping.md b/src/subtyping.md index 38fb1270a..c88e0ba86 100644 --- a/src/subtyping.md +++ b/src/subtyping.md @@ -1,6 +1,5 @@ -# Subtyping and Variance - r[subtype] +# Subtyping and Variance r[subtype.intro] Subtyping is implicit and can occur at any stage in type checking or @@ -44,9 +43,8 @@ let subtype: &(for<'a, 'b> fn(&'a i32, &'b i32))= &((|x, y| {}) as fn(&_, &_)); let supertype: &for<'c> fn(&'c i32, &'c i32) = subtype; ``` -## Variance - r[subtyping.variance] +## Variance r[subtyping.variance.intro] Variance is a property that generic types have with respect to their arguments. diff --git a/src/tokens.md b/src/tokens.md index d3278f681..317a437ce 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -1,6 +1,5 @@ -# Tokens - r[lex.token] +# Tokens r[lex.token.intro] Tokens are primitive productions in the grammar defined by regular @@ -19,9 +18,9 @@ table production] form, and appear in `monospace` font. [string table production]: notation.md#string-table-productions +r[lex.token.literal] ## Literals -r[lex.token.literal] Literals are tokens used in [literal expressions]. ### Examples @@ -90,9 +89,8 @@ Literals are tokens used in [literal expressions]. [^nl]: All number literals allow `_` as a visual separator: `1_234.0E+18f64` -#### Suffixes - r[lex.token.literal.suffix] +#### Suffixes r[lex.token.literal.literal.suffix.intro] A suffix is a sequence of characters following the primary part of a literal (without intervening whitespace), of the same form as a non-raw identifier or keyword. @@ -128,9 +126,8 @@ and numeric literal tokens are accepted only with suffixes from the list below. ### Character and string literals -#### Character literals - r[lex.token.literal.char] +#### Character literals r[lex.token.literal.char.syntax] > **Lexer**\ @@ -152,9 +149,8 @@ A _character literal_ is a single Unicode character enclosed within two `U+0027` (single-quote) characters, with the exception of `U+0027` itself, which must be _escaped_ by a preceding `U+005C` character (`\`). -#### String literals - r[lex.token.literal.str] +#### String literals r[lex.token.literal.str.syntax] > **Lexer**\ @@ -181,9 +177,8 @@ When an unescaped `U+005C` character (`\`) occurs immediately before a line brea See [String continuation escapes] for details. The character `U+000D` (CR) may not appear in a string literal other than as part of such a string continuation escape. -#### Character escapes - r[lex.token.literal.char-escape] +#### Character escapes r[lex.token.literal.char-escape.intro] Some additional _escapes_ are available in either character or non-raw string @@ -215,9 +210,8 @@ r[lex.token.literal.char-escape.slash] * The _backslash escape_ is the character `U+005C` (`\`) which must be escaped in order to denote itself. -#### Raw string literals - r[lex.token.literal.str-raw] +#### Raw string literals r[lex.token.literal.str-raw.syntax] > **Lexer**\ @@ -258,9 +252,8 @@ r##"foo #"# bar"##; // foo #"# bar ### Byte and byte string literals -#### Byte literals - r[lex.token.byte] +#### Byte literals r[lex.token.byte.syntax] > **Lexer**\ @@ -282,9 +275,8 @@ range) or a single _escape_ preceded by the characters `U+0062` (`b`) and `U+005C` (`\`) character. It is equivalent to a `u8` unsigned 8-bit integer _number literal_. -#### Byte string literals - r[lex.token.str-byte] +#### Byte string literals r[lex.token.str-byte.syntax] > **Lexer**\ @@ -331,9 +323,8 @@ r[lex.token.str-byte.escape-slash] * The _backslash escape_ is the character `U+005C` (`\`) which must be escaped in order to denote its ASCII encoding `0x5C`. -#### Raw byte string literals - r[lex.token.str-byte-raw] +#### Raw byte string literals r[lex.token.str-byte-raw.syntax] > **Lexer**\ @@ -378,9 +369,8 @@ b"\\x52"; br"\x52"; // \x52 ### C string and raw C string literals -#### C string literals - r[lex.token.str-c] +#### C string literals r[lex.token.str-c.syntax] > **Lexer**\ @@ -453,9 +443,8 @@ r[lex.token.str-c.edition2021] > **Edition differences**: C string literals are accepted in the 2021 edition or > later. In earlier additions the token `c""` is lexed as `c ""`. -#### Raw C string literals - r[lex.token.str-c-raw] +#### Raw C string literals r[lex.token.str-c-raw.syntax] > **Lexer**\ @@ -499,16 +488,15 @@ c"\x52"; c"R"; cr"R"; // R c"\\x52"; cr"\x52"; // \x52 ``` +r[lex.token.literal.num] ### Number literals -r[lex.token.literal.num] A _number literal_ is either an _integer literal_ or a _floating-point literal_. The grammar for recognizing the two kinds of literals is mixed. -#### Integer literals - r[lex.token.literal.int] +#### Integer literals r[lex.token.literal.int.syntax] > **Lexer**\ @@ -609,9 +597,8 @@ Examples of integer literals which are not accepted as literal expressions: # } ``` -#### Tuple index - r[lex.token.literal.int.tuple-field] +#### Tuple index r[lex.token.literal.int.tuple-field.syntax] > **Lexer**\ @@ -640,9 +627,8 @@ let horse = example.0b10; // ERROR no field named `0b10` > **Note**: Tuple indices may include certain suffixes, but this is not intended to be valid, and may be removed in a future version. > See for more information. -#### Floating-point literals - r[lex.token.literal.float] +#### Floating-point literals r[lex.token.literal.float.syntax] > **Lexer**\ @@ -698,9 +684,9 @@ Examples of floating-point literals which are not accepted as literal expression # } ``` +r[lex.token.literal.reserved] #### Reserved forms similar to number literals -r[lex.token.literal.reserved] > **Lexer**\ > RESERVED_NUMBER :\ @@ -748,9 +734,8 @@ Examples of reserved forms: 2.0em; // this is not a suffixed literal, or `2.0` followed by `em` ``` -## Lifetimes and loop labels - r[lex.token.life] +## Lifetimes and loop labels r[lex.token.life.syntax] > **Lexer**\ @@ -791,9 +776,8 @@ r[lex.token.life.raw.edition2021] > **Edition differences**: Raw lifetimes are accepted in the 2021 > edition or later. In earlier additions the token `'r#lt` is lexed as `'r # lt`. -## Punctuation - r[lex.token.punct] +## Punctuation r[lex.token.punct.intro] Punctuation symbol tokens are listed here for completeness. Their individual @@ -849,9 +833,9 @@ usages and meanings are defined in the linked pages. | `?` | Question | [Question mark operator][question], [Questionably sized][sized], [Macro Kleene Matcher][macros] | `~` | Tilde | The tilde operator has been unused since before Rust 1.0, but its token may still be used +r[lex.token.delim] ## Delimiters -r[lex.token.delim] Bracket punctuation is used in various parts of the grammar. An open bracket must always be paired with a close bracket. Brackets and the tokens within @@ -863,9 +847,8 @@ them are referred to as "token trees" in [macros]. The three types of brackets | `[` `]` | Square brackets | | `(` `)` | Parentheses | -## Reserved prefixes - r[lex.token.reserved-prefix] +## Reserved prefixes r[lex.token.reserved-prefix.syntax] > **Lexer 2021+**\ @@ -913,9 +896,8 @@ r[lex.token.reserved-prefix.edition2021] > lexes!{'prefix#lt} > ``` -## Reserved guards - r[lex.token.reserved-guards] +## Reserved guards r[lex.token.reserved-guards.syntax] > **Lexer 2024+**\ diff --git a/src/trait-bounds.md b/src/trait-bounds.md index 2ff83412c..5d8806d04 100644 --- a/src/trait-bounds.md +++ b/src/trait-bounds.md @@ -1,6 +1,5 @@ -# Trait and lifetime bounds - r[bound] +# Trait and lifetime bounds r[bound.syntax] > **Syntax**\ @@ -118,16 +117,15 @@ struct UsesA<'a, T>(A<'a, T>); r[bound.trait-object] Trait and lifetime bounds are also used to name [trait objects]. +r[bound.sized] ## `?Sized` -r[bound.sized] `?` is only used to relax the implicit [`Sized`] trait bound for [type parameters] or [associated types]. `?Sized` may not be used as a bound for other types. -## Lifetime bounds - r[bound.lifetime] +## Lifetime bounds r[bound.lifetime.intro] Lifetime bounds can be applied to types or to other lifetimes. @@ -147,9 +145,8 @@ r[bound.lifetime.outlive-type] `T: 'a` means that all lifetime parameters of `T` outlive `'a`. For example, if `'a` is an unconstrained lifetime parameter, then `i32: 'static` and `&'static str: 'a` are satisfied, but `Vec<&'a ()>: 'static` is not. -## Higher-ranked trait bounds - r[bound.higher-ranked] +## Higher-ranked trait bounds r[bound.higher-ranked.syntax] > _ForLifetimes_ :\ @@ -192,9 +189,8 @@ fn call_on_ref_zero(f: F) where F: for<'a> Fn(&'a i32) { } ``` -## Implied bounds - r[bound.implied] +## Implied bounds r[bound.implied.intro] Lifetime bounds required for types to be well-formed are sometimes inferred. @@ -271,9 +267,9 @@ trait Trait<'a, T: 'a> {} impl<'a, T> Trait<'a, T> for &'a T {} ``` +r[bound.use] ## Use bounds -r[bound.use] Certain bounds lists may include a `use<..>` bound to control which generic parameters are captured by the `impl Trait` [abstract return type]. See [precise capturing] for more details. diff --git a/src/type-coercions.md b/src/type-coercions.md index 26e27eb1d..d88e7b0d7 100644 --- a/src/type-coercions.md +++ b/src/type-coercions.md @@ -1,6 +1,5 @@ -# Type coercions - r[coerce] +# Type coercions r[coerce.intro] **Type coercions** are implicit operations that change the type of a value. @@ -13,9 +12,8 @@ Any conversions allowed by coercion can also be explicitly performed by the Coercions are originally defined in [RFC 401] and expanded upon in [RFC 1558]. -## Coercion sites - r[coerce.site] +## Coercion sites r[coerce.site.intro] A coercion can only occur at certain coercion sites in a program; these are @@ -109,9 +107,8 @@ it is not semicolon-terminated) is a coercion site to `U`. This includes blocks which are part of control flow statements, such as `if`/`else`, if the block has a known type. -## Coercion types - r[coerce.types] +## Coercion types r[coerce.types.intro] Coercion is allowed between the following types: @@ -189,9 +186,8 @@ r[coerce.types.closure] r[coerce.types.never] * `!` to any `T` -### Unsized Coercions - r[coerce.unsize] +### Unsized Coercions r[coerce.unsize.intro] The following coercions are called `unsized coercions`, since they @@ -228,9 +224,8 @@ unsized coercion to `Foo`. > has been stabilized, the traits themselves are not yet stable and therefore > can't be used directly in stable Rust. -## Least upper bound coercions - r[coerce.least-upper-bound] +## Least upper bound coercions r[coerce.least-upper-bound.intro] In some contexts, the compiler must coerce together multiple types to try and diff --git a/src/type-layout.md b/src/type-layout.md index 5d04d2a80..316075ac0 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -1,6 +1,5 @@ -# Type Layout - r[layout] +# Type Layout r[layout.intro] The layout of a type is its size, alignment, and the relative offsets of its @@ -15,9 +14,9 @@ Note that even types with the same layout can still differ in how they are passe across function boundaries. For function call ABI compatibility of types, see [here][fn-abi-compatibility]. +r[layout.properties] ## Size and Alignment -r[layout.properties] All values have an alignment and size. r[layout.properties.align] @@ -44,9 +43,8 @@ as [dynamically sized types]. Since all values of a `Sized` type share the same size and alignment, we refer to those shared values as the size of the type and the alignment of the type respectively. -## Primitive Data Layout - r[layout.primitive] +## Primitive Data Layout r[layout.primitive.size] The size of most primitives is given in this table. @@ -76,9 +74,8 @@ In particular, `i128` and `u128` are often aligned to 4 or 8 bytes even though their size is 16, and on many 32-bit platforms, `i64`, `u64`, and `f64` are only aligned to 4 bytes, not 8. -## Pointers and References Layout - r[layout.pointer] +## Pointers and References Layout r[layout.pointer.intro] Pointers and references have the same layout. Mutability of the pointer or @@ -95,32 +92,31 @@ at least equal to the size and alignment of a pointer. > DSTs are currently twice the > size of the size of `usize` and have the same alignment. +r[layout.array] ## Array Layout -r[layout.array] An array of `[T; N]` has a size of `size_of::() * N` and the same alignment of `T`. Arrays are laid out so that the zero-based `nth` element of the array is offset from the start of the array by `n * size_of::()` bytes. +r[layout.slice] ## Slice Layout -r[layout.slice] Slices have the same layout as the section of the array they slice. > Note: This is about the raw `[T]` type, not pointers (`&[T]`, `Box<[T]>`, > etc.) to slices. +r[layout.str] ## `str` Layout -r[layout.str] String slices are a UTF-8 representation of characters that have the same layout as slices of type `[u8]`. -## Tuple Layout - r[layout.tuple] +## Tuple Layout r[layout.tuple.general] Tuples are laid out according to the [`Rust` representation][`Rust`]. @@ -129,24 +125,23 @@ r[layout.tuple.unit] The exception to this is the unit tuple (`()`), which is guaranteed as a zero-sized type to have a size of 0 and an alignment of 1. +r[layout.trait-object] ## Trait Object Layout -r[layout.trait-object] Trait objects have the same layout as the value the trait object is of. > Note: This is about the raw trait object types, not pointers (`&dyn Trait`, > `Box`, etc.) to trait objects. +r[layout.closure] ## Closure Layout -r[layout.closure] Closures have no layout guarantees. -## Representations - r[layout.repr] +## Representations r[layout.repr.intro] All user-defined composite types (`struct`s, `enum`s, and `union`s) have a @@ -208,9 +203,8 @@ not change the layout of the fields themselves. For example, a struct with a representation will not change the layout of `Inner`. -### The `Rust` Representation - r[layout.repr.rust] +### The `Rust` Representation r[layout.repr.rust.intro] The `Rust` representation is the default representation for nominal types @@ -244,9 +238,8 @@ same struct. r[layout.repr.rust.unspecified] There are no other guarantees of data layout made by this representation. -### The `C` Representation - r[layout.repr.c] +### The `C` Representation r[layout.repr.c.intro] The `C` representation is designed for dual purposes. One purpose is for @@ -261,9 +254,8 @@ r[layout.repr.c.constraint] This representation can be applied to structs, unions, and enums. The exception is [zero-variant enums] for which the `C` representation is an error. -#### `#[repr(C)]` Structs - r[layout.repr.c.struct] +#### `#[repr(C)]` Structs r[layout.repr.c.struct.align] The alignment of the struct is the alignment of the most-aligned field in it. @@ -327,9 +319,8 @@ struct.size = current_offset + padding_needed_for(current_offset, struct.alignme > they are fields that have the `[[no_unique_address]]` attribute, in which > case they do not increase the overall size of the struct. -#### `#[repr(C)]` Unions - r[layout.repr.c.union] +#### `#[repr(C)]` Unions r[layout.repr.c.union.intro] A union declared with `#[repr(C)]` will have the same size and alignment as an @@ -362,9 +353,9 @@ assert_eq!(std::mem::size_of::(), 8); // Size of 6 from b, assert_eq!(std::mem::align_of::(), 4); // From a ``` +r[layout.repr.c.enum] #### `#[repr(C)]` Field-less Enums -r[layout.repr.c.enum] For [field-less enums], the `C` representation has the size and alignment of the default `enum` size and alignment for the target platform's C ABI. @@ -376,9 +367,8 @@ the default `enum` size and alignment for the target platform's C ABI. > [!WARNING] > There are crucial differences between an `enum` in the C language and Rust's [field-less enums] with this representation. An `enum` in C is mostly a `typedef` plus some named constants; in other words, an object of an `enum` type can hold any integer value. For example, this is often used for bitflags in `C`. In contrast, Rust’s [field-less enums] can only legally hold the discriminant values, everything else is [undefined behavior]. Therefore, using a field-less enum in FFI to model a C `enum` is often wrong. -#### `#[repr(C)]` Enums With Fields - r[layout.repr.c.adt] +#### `#[repr(C)]` Enums With Fields r[layout.repr.c.adt.intro] The representation of a `repr(C)` enum with fields is a `repr(C)` struct with @@ -448,9 +438,8 @@ struct MyDFields; > Note: `union`s with non-`Copy` fields are unstable, see [55149]. -### Primitive representations - r[layout.repr.primitive] +### Primitive representations r[layout.repr.primitive.intro] The *primitive representations* are the representations with the same names as @@ -463,18 +452,18 @@ different behavior whether the enum has fields or no fields. It is an error for [zero-variant enums] to have a primitive representation. Combining two primitive representations together is an error. +r[layout.repr.primitive.enum] #### Primitive Representation of Field-less Enums -r[layout.repr.primitive.enum] For [field-less enums], primitive representations set the size and alignment to be the same as the primitive type of the same name. For example, a field-less enum with a `u8` representation can only have discriminants between 0 and 255 inclusive. +r[layout.repr.primitive.adt] #### Primitive Representation of Enums With Fields -r[layout.repr.primitive.adt] The representation of a primitive representation enum is a `repr(C)` union of `repr(C)` structs for each variant with a field. The first field of each struct @@ -528,9 +517,9 @@ struct MyVariantD(MyEnumDiscriminant); > Note: `union`s with non-`Copy` fields are unstable, see [55149]. +r[layout.repr.primitive-c] #### Combining primitive representations of enums with fields and `#[repr(C)]` -r[layout.repr.primitive-c] For enums with fields, it is also possible to combine `repr(C)` and a primitive representation (e.g., `repr(C, u8)`). This modifies the [`repr(C)`] by @@ -594,9 +583,8 @@ assert_eq!(std::mem::size_of::(), 4); [`repr(C)`]: #reprc-enums-with-fields -### The alignment modifiers - r[layout.repr.alignment] +### The alignment modifiers r[layout.repr.alignment.intro] The `align` and `packed` modifiers can be used to respectively raise or lower @@ -665,9 +653,8 @@ was wrapped in a newtype `struct` with the same `align` modifier. > unsafe { mut_ptr.write_unaligned(3) } > ``` -### The `transparent` Representation - r[layout.repr.transparent] +### The `transparent` Representation r[layout.repr.transparent.constraint-field] The `transparent` representation can only be used on a [`struct`][structs] diff --git a/src/types.md b/src/types.md index a93f93d1f..3b6ea8cfd 100644 --- a/src/types.md +++ b/src/types.md @@ -1,7 +1,6 @@ {{#include types-redirect.html}} -# Types - r[type] +# Types r[type.intro] Every variable, item, and value in a Rust program has a type. The _type_ of a @@ -42,9 +41,8 @@ The list of types is: * [Trait objects] * [Impl trait] -## Type expressions - r[type.name] +## Type expressions r[type.name.syntax] > **Syntax**\ @@ -101,9 +99,8 @@ r[type.name.never] r[type.name.macro-expansion] * [Macros] which expand to a type expression. -### Parenthesized types - r[type.name.parenthesized] +### Parenthesized types r[type.name.parenthesized.syntax] > _ParenthesizedType_ :\ @@ -122,9 +119,8 @@ require this disambiguation use the [_TypeNoBounds_] rule instead of type T<'a> = &'a (dyn Any + Send); ``` -## Recursive types - r[type.recursive] +## Recursive types r[type.recursive.intro] Nominal types — [structs], [enumerations], and [unions] — may be diff --git a/src/types/array.md b/src/types/array.md index ef54af1f3..d18ffa212 100644 --- a/src/types/array.md +++ b/src/types/array.md @@ -1,6 +1,5 @@ -# Array types - r[type.array] +# Array types r[type.array.syntax] > **Syntax**\ diff --git a/src/types/boolean.md b/src/types/boolean.md index 10c6e5de1..f1aa6977f 100644 --- a/src/types/boolean.md +++ b/src/types/boolean.md @@ -1,6 +1,5 @@ -# Boolean type - r[type.bool] +# Boolean type ```rust let b: bool = true; @@ -45,25 +44,22 @@ Like all primitives, the boolean type [implements][p-impl] the > **Note**: See the [standard library docs](bool) for library operations. -## Operations on boolean values - r[type.bool.expr] +## Operations on boolean values When using certain operator expressions with a boolean type for its operands, they evaluate using the rules of [boolean logic]. -### Logical not - r[type.bool.expr.not] +### Logical not | `b` | [`!b`][op-not] | |- | - | | `true` | `false` | | `false` | `true` | -### Logical or - r[type.bool.expr.or] +### Logical or | `a` | `b` | [a | b][op-or] | |- | - | - | @@ -72,9 +68,8 @@ r[type.bool.expr.or] | `false` | `true` | `true` | | `false` | `false` | `false` | -### Logical and - r[type.bool.expr.and] +### Logical and | `a` | `b` | [`a & b`][op-and] | |- | - | - | @@ -83,9 +78,8 @@ r[type.bool.expr.and] | `false` | `true` | `false` | | `false` | `false` | `false` | -### Logical xor - r[type.bool.expr.xor] +### Logical xor | `a` | `b` | [`a ^ b`][op-xor] | |- | - | - | @@ -94,9 +88,8 @@ r[type.bool.expr.xor] | `false` | `true` | `true` | | `false` | `false` | `false` | -### Comparisons - r[type.bool.expr.cmp] +### Comparisons r[type.bool.expr.cmp.eq] | `a` | `b` | [`a == b`][op-compare] | @@ -126,9 +119,8 @@ r[type.bool.expr.cmp.less] r[type.bool.expr.cmp.less-eq] * `a <= b` is the same as `a == b | a < b` -## Bit validity - r[type.bool.validity] +## Bit validity The single byte of a `bool` is guaranteed to be initialized (in other words, `transmute::(...)` is always sound -- but since some bit patterns diff --git a/src/types/closure.md b/src/types/closure.md index 2fc59276d..92da4f885 100644 --- a/src/types/closure.md +++ b/src/types/closure.md @@ -1,6 +1,5 @@ -# Closure types - r[type.closure] +# Closure types r[type.closure.intro] A [closure expression] produces a closure value with a unique, anonymous type that cannot be written out. @@ -60,9 +59,8 @@ so that the call to `f` works as if it were: f(Closure{ left_top: &mut rect.left_top, right_bottom_x: &mut rect.left_top.x }); ``` -## Capture modes - r[type.closure.capture] +## Capture modes r[type.closure.capture.intro] A *capture mode* determines how a [place expression] from the environment is borrowed or moved into the closure. @@ -82,9 +80,9 @@ The mode is not affected by the code surrounding the closure, such as the lifeti [place expression]: ../expressions.md#place-expressions-and-value-expressions [shared reference]: pointer.md#references--and-mut +r[type.closure.capture.copy] ### `Copy` values -r[type.closure.capture.copy] Values that implement [`Copy`] that are moved into the closure are captured with the `ImmBorrow` mode. ```rust @@ -94,9 +92,9 @@ let c = || { }; ``` +r[type.closure.async.input] ### Async input capture -r[type.closure.async.input] Async closures always capture all input arguments, regardless of whether or not they are used within the body. ## Capture Precision @@ -132,9 +130,9 @@ This closure captures an immutable borrow of `s.f1.1`. [dereference]: ../expressions/operator-expr.md#the-dereference-operator [array or slice index]: ../expressions/array-expr.md#array-and-slice-indexing-expressions +r[type.closure.capture.precision.shared-prefix] ### Shared prefix -r[type.closure.capture.precision.shared-prefix] In the case where a capture path and one of the ancestor’s of that path are both captured by a closure, the ancestor path is captured with the highest capture mode among the two captures, `CaptureMode = max(AncestorCaptureMode, DescendantCaptureMode)`, using the strict weak ordering: `ImmBorrow < UniqueImmBorrow < MutBorrow < ByValue` @@ -158,9 +156,9 @@ c(); Overall this closure will capture `u` by `ByValue`. +r[type.closure.capture.precision.dereference-shared] ### Rightmost shared reference truncation -r[type.closure.capture.precision.dereference-shared] The capture path is truncated at the rightmost dereference in the capture path if the dereference is applied to a shared reference. This truncation is allowed because fields that are read through a shared reference will always be read via a shared reference or a copy. @@ -186,9 +184,9 @@ fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static { If this were to capture `m`, then the closure would no longer outlive `'static`, since `m` is constrained to `'a`. Instead, it captures `(*(*m).a)` by `ImmBorrow`. +r[type.closure.capture.precision.wildcard] ### Wildcard pattern bindings -r[type.closure.capture.precision.wildcard] Closures only capture data that needs to be read. Binding a value with a [wildcard pattern] does not count as a read, and thus won't be captured. For example, the following closures will not capture `x`: @@ -270,9 +268,9 @@ let c = || { [_StructPatternEtCetera_]: ../patterns.md#struct-patterns [wildcard pattern]: ../patterns.md#wildcard-pattern +r[type.closure.capture.precision.move-dereference] ### Capturing references in move contexts -r[type.closure.capture.precision.move-dereference] Because it is not allowed to move fields out of a reference, `move` closures will only capture the prefix of a capture path that runs up to, but not including, the first dereference of a reference. The reference itself will be moved into the closure. @@ -287,9 +285,9 @@ let mut c = move || { c(); ``` +r[type.closure.capture.precision.raw-pointer-dereference] ### Raw pointer dereference -r[type.closure.capture.precision.raw-pointer-dereference] Because it is `unsafe` to dereference a raw pointer, closures will only capture the prefix of a capture path that runs up to, but not including, the first dereference of a raw pointer. ```rust @@ -304,9 +302,9 @@ let c = || unsafe { c(); ``` +r[type.closure.capture.precision.union] ### Union fields -r[type.closure.capture.precision.union] Because it is `unsafe` to access a union field, closures will only capture the prefix of a capture path that runs up to the union itself. ```rust @@ -330,9 +328,9 @@ let mut c = || { c(); ``` +r[type.closure.capture.precision.unaligned] ### Reference into unaligned `struct`s -r[type.closure.capture.precision.unaligned] Because it is [undefined behavior] to create references to unaligned fields in a structure, closures will only capture the prefix of the capture path that runs up to, but not including, the first field access into a structure that uses [the `packed` representation]. This includes all fields, even those that are aligned, to protect against compatibility concerns should any of the fields in the structure change in the future. @@ -381,9 +379,9 @@ c(); [undefined behavior]: ../behavior-considered-undefined.md [the `packed` representation]: ../type-layout.md#the-alignment-modifiers +r[type.closure.capture.precision.box-deref] ### `Box` vs other `Deref` implementations -r[type.closure.capture.precision.box-deref] The implementation of the [`Deref`] trait for [`Box`] is treated differently from other `Deref` implementations, as it is considered a special entity. For example, let us look at examples involving `Rc` and `Box`. The `*rc` is desugared to a call to the trait method `deref` defined on `Rc`, but since `*box` is treated differently, it is possible to do a precise capture of the contents of the `Box`. @@ -391,9 +389,9 @@ For example, let us look at examples involving `Rc` and `Box`. The `*rc` is desu [`Box`]: ../special-types-and-traits.md#boxt [`Deref`]: ../special-types-and-traits.md#deref-and-derefmut +r[type.closure.capture.precision.box-non-move.not-moved] #### `Box` with non-`move` closure -r[type.closure.capture.precision.box-non-move.not-moved] In a non-`move` closure, if the contents of the `Box` are not moved into the closure body, the contents of the `Box` are precisely captured. ```rust @@ -429,9 +427,9 @@ let c_box = || { c_box(); ``` +r[type.closure.capture.precision.box-move.read] #### `Box` with move closure -r[type.closure.capture.precision.box-move.read] Similarly to moving contents of a `Box` in a non-`move` closure, reading the contents of a `Box` in a `move` closure will capture the `Box` entirely. ```rust @@ -443,9 +441,9 @@ let c_box = move || { }; ``` +r[type.closure.unique-immutable] ## Unique immutable borrows in captures -r[type.closure.unique-immutable] Captures can occur by a special kind of borrow called a _unique immutable borrow_, which cannot be used anywhere else in the language and cannot be written out explicitly. It occurs when modifying the referent of a mutable reference, as in the following example: @@ -472,9 +470,8 @@ So a unique immutable borrow is used: it borrows `x` immutably, but like a mutab In the above example, uncommenting the declaration of `y` will produce an error because it would violate the uniqueness of the closure's borrow of `x`; the declaration of z is valid because the closure's lifetime has expired at the end of the block, releasing the borrow. -## Call traits and coercions - r[type.closure.call] +## Call traits and coercions r[type.closure.call.intro] Closure types all implement [`FnOnce`], indicating that they can be called once @@ -509,9 +506,8 @@ let bo: Binop = add; x = bo(5,7); ``` -### Async closure traits - r[type.closure.async.traits] +### Async closure traits r[type.closure.async.traits.fn-family] Async closures have a further restriction of whether or not they implement [`FnMut`] or [`Fn`]. @@ -568,9 +564,8 @@ If the async closure is lending to its `Future`, then [`FnMut`] and [`Fn`] are * r[type.closure.async.traits.async-family] Async closures implement [`AsyncFn`], [`AsyncFnMut`], and [`AsyncFnOnce`] in an analogous way as regular closures implement [`Fn`], [`FnMut`], and [`FnOnce`]; that is, depending on the use of the captured variables in its body. -### Other traits - r[type.closure.traits] +### Other traits r[type.closure.traits.intro] All closure types implement [`Sized`]. Additionally, closure types implement the @@ -605,9 +600,9 @@ Because captures are often by reference, the following general rules arise: [closure expression]: ../expressions/closure-expr.md [derived]: ../attributes/derive.md +r[type.closure.drop-order] ## Drop Order -r[type.closure.drop-order] If a closure captures a field of a composite types such as structs, tuples, and enums by value, the field's lifetime would now be tied to the closure. As a result, it is possible for disjoint fields of a composite types to be dropped at different times. ```rust @@ -623,11 +618,11 @@ If a closure captures a field of a composite types such as structs, tuples, and } // tuple.1 dropped here -----------------------------+ ``` +r[type.closure.capture.precision.edition2018.entirety] ## Edition 2018 and before ### Closure types difference -r[type.closure.capture.precision.edition2018.entirety] In Edition 2018 and before, closures always capture a variable in its entirety, without its precise capture path. This means that for the example used in the [Closure types](#closure-types) section, the generated closure type would instead look something like this: @@ -653,9 +648,9 @@ and the call to `f` would work as follows: f(Closure { rect: rect }); ``` +r[type.closure.capture.precision.edition2018.composite] ### Capture precision difference -r[type.closure.capture.precision.edition2018.composite] Composite types such as structs, tuples, and enums are always captured in its entirety, not by individual fields. As a result, it may be necessary to borrow into a local variable in order to capture a single field: @@ -685,9 +680,9 @@ If the `move` keyword is used, then all captures are by move or, for `Copy` type r[type.closure.capture.precision.edition2018.wildcard] Regardless of if the data will be read by the closure, i.e. in case of wild card patterns, if a variable defined outside the closure is mentioned within the closure the variable will be captured in its entirety. +r[type.closure.capture.precision.edition2018.drop-order] ### Drop order difference -r[type.closure.capture.precision.edition2018.drop-order] As composite types are captured in their entirety, a closure which captures one of those composite types by value would drop the entire captured variable at the same time as the closure gets dropped. ```rust diff --git a/src/types/enum.md b/src/types/enum.md index a3ae2878f..f434cfaeb 100644 --- a/src/types/enum.md +++ b/src/types/enum.md @@ -1,6 +1,5 @@ -# Enumerated types - r[type.enum] +# Enumerated types r[type.enum.intro] An *enumerated type* is a nominal, heterogeneous disjoint union type, denoted diff --git a/src/types/function-item.md b/src/types/function-item.md index 81a867e3c..f5e7f491e 100644 --- a/src/types/function-item.md +++ b/src/types/function-item.md @@ -1,6 +1,5 @@ -# Function item types - r[type.fn-item] +# Function item types r[type.fn-item.intro] When referred to, a function item, or the constructor of a tuple-like struct or diff --git a/src/types/function-pointer.md b/src/types/function-pointer.md index 21a398265..88ca5a31a 100644 --- a/src/types/function-pointer.md +++ b/src/types/function-pointer.md @@ -1,6 +1,5 @@ -# Function pointer types - r[type.fn-pointer] +# Function pointer types r[type.fn-pointer.syntax] > **Syntax**\ @@ -62,9 +61,8 @@ let bo: Binop = add; x = bo(5,7); ``` -## Attributes on function pointer parameters - r[type.fn-pointer.attributes] +## Attributes on function pointer parameters Attributes on function pointer parameters follow the same rules and restrictions as [regular function parameters]. diff --git a/src/types/impl-trait.md b/src/types/impl-trait.md index bf5f8622f..bc873eb5d 100644 --- a/src/types/impl-trait.md +++ b/src/types/impl-trait.md @@ -1,6 +1,5 @@ -# Impl trait - r[type.impl-trait] +# Impl trait r[type.impl-trait.syntax] > **Syntax**\ @@ -25,9 +24,8 @@ fn foo(arg: impl Trait) { fn bar() -> impl Trait { } ``` -## Anonymous type parameters - r[type.impl-trait.param] +## Anonymous type parameters > Note: This is often called "impl Trait in argument position". (The term "parameter" is more correct here, but "impl Trait in argument position" is the phrasing used during the development of this feature, and it remains in parts of the implementation.) @@ -58,9 +56,8 @@ That is, `impl Trait` in argument position is syntactic sugar for a generic type > With a generic parameter such as ``, the caller has the option to explicitly specify the generic argument for `T` at the call site using [_GenericArgs_], for example, `foo::(1)`. > Changing a parameter from either one to the other can constitute a breaking change for the callers of a function, since this changes the number of generic arguments. -## Abstract return types - r[type.impl-trait.return] +## Abstract return types > Note: This is often called "impl Trait in return position". @@ -98,9 +95,8 @@ which also avoids the drawbacks of using a boxed trait object. Similarly, the concrete types of iterators could become very complex, incorporating the types of all previous iterators in a chain. Returning `impl Iterator` means that a function only exposes the `Iterator` trait as a bound on its return type, instead of explicitly specifying all of the other iterator types involved. -## Return-position `impl Trait` in traits and trait implementations - r[type.impl-trait.return-in-trait] +## Return-position `impl Trait` in traits and trait implementations r[type.impl-trait.return-in-trait.intro] Functions in traits may also use `impl Trait` as a syntax for an anonymous associated type. @@ -108,15 +104,13 @@ Functions in traits may also use `impl Trait` as a syntax for an anonymous assoc r[type.impl-trait.return-in-trait.desugaring] Every `impl Trait` in the return type of an associated function in a trait is desugared to an anonymous associated type. The return type that appears in the implementation's function signature is used to determine the value of the associated type. -## Capturing - r[type.impl-trait.generic-captures] +## Capturing Behind each return-position `impl Trait` abstract type is some hidden concrete type. For this concrete type to use a generic parameter, that generic parameter must be *captured* by the abstract type. -## Automatic capturing - r[type.impl-trait.generic-capture.auto] +## Automatic capturing r[type.impl-trait.generic-capture.auto.intro] Return-position `impl Trait` abstract types automatically capture all in-scope generic parameters, including generic type, const, and lifetime parameters (including higher-ranked ones). @@ -124,9 +118,8 @@ Return-position `impl Trait` abstract types automatically capture all in-scope g r[type.impl-trait.generic-capture.edition2024] > **Edition differences**: Before the 2024 edition, on free functions and on associated functions and methods of inherent impls, generic lifetime parameters that do not appear in the bounds of the abstract return type are not automatically captured. -## Precise capturing - r[type.impl-trait.generic-capture.precise] +## Precise capturing r[type.impl-trait.generic-capture.precise.use] The set of generic parameters captured by a return-position `impl Trait` abstract type may be explicitly controlled with a [`use<..>` bound]. If present, only the generic parameters listed in the `use<..>` bound will be captured. E.g.: @@ -179,9 +172,8 @@ fn foo() -> impl Trait { doesn't allow the caller to determine the return type. Instead, the function chooses the return type, but only promises that it will implement `Trait`. -## Limitations - r[type.impl-trait.constraint] +## Limitations `impl Trait` can only appear as a parameter or return type of a non-`extern` function. It cannot be the type of a `let` binding, field type, or appear inside a type alias. diff --git a/src/types/inferred.md b/src/types/inferred.md index 7179826c4..668f75b48 100644 --- a/src/types/inferred.md +++ b/src/types/inferred.md @@ -1,6 +1,5 @@ -# Inferred type - r[type.inferred] +# Inferred type r[type.inferred.syntax] > **Syntax**\ diff --git a/src/types/never.md b/src/types/never.md index 702281db2..d4a4d3366 100644 --- a/src/types/never.md +++ b/src/types/never.md @@ -1,6 +1,5 @@ -# Never type - r[type.never] +# Never type r[type.never.syntax] > **Syntax**\ diff --git a/src/types/numeric.md b/src/types/numeric.md index 88178d123..b4db2121f 100644 --- a/src/types/numeric.md +++ b/src/types/numeric.md @@ -1,10 +1,8 @@ -# Numeric types - r[type.numeric] - -## Integer types +# Numeric types r[type.numeric.int] +## Integer types r[type.numeric.int.unsigned] The unsigned integer types consist of: @@ -29,16 +27,14 @@ Type | Minimum | Maximum `i128` | -(2127) | 2127-1 -## Floating-point types - r[type.numeric.float] +## Floating-point types The IEEE 754-2008 "binary32" and "binary64" floating-point types are `f32` and `f64`, respectively. -## Machine-dependent integer types - r[type.numeric.int.size] +## Machine-dependent integer types r[type.numeric.int.size.usize] The `usize` type is an unsigned integer type with the same number of bits as the @@ -59,9 +55,8 @@ r[type.numeric.int.size.minimum] > pointer support is limited and may require explicit care and acknowledgment > from a library to support. -## Bit validity - r[type.numeric.validity] +## Bit validity For every numeric type, `T`, the bit validity of `T` is equivalent to the bit validity of `[u8; size_of::()]`. An uninitialized byte is not a valid `u8`. diff --git a/src/types/parameters.md b/src/types/parameters.md index 89b7df9ec..143478915 100644 --- a/src/types/parameters.md +++ b/src/types/parameters.md @@ -1,6 +1,5 @@ -# Type parameters - r[type.generic] +# Type parameters Within the body of an item that has type parameter declarations, the names of its type parameters are types: diff --git a/src/types/pointer.md b/src/types/pointer.md index 0f24d6bce..238786522 100644 --- a/src/types/pointer.md +++ b/src/types/pointer.md @@ -1,23 +1,20 @@ -# Pointer types - r[type.pointer] +# Pointer types r[type.pointer.intro] All pointers are explicit first-class values. They can be moved or copied, stored into data structs, and returned from functions. -## References (`&` and `&mut`) - r[type.pointer.reference] +## References (`&` and `&mut`) r[type.pointer.reference.syntax] > **Syntax**\ > _ReferenceType_ :\ >    `&` [_Lifetime_]? `mut`? [_TypeNoBounds_] -### Shared references (`&`) - r[type.pointer.reference.shared] +### Shared references (`&`) r[type.pointer.reference.shared.intro] Shared references point to memory which is owned by some other value. @@ -33,9 +30,8 @@ Copying a reference is a "shallow" operation: it involves only copying the pointer itself, that is, pointers are `Copy`. Releasing a reference has no effect on the value it points to, but referencing of a [temporary value] will keep it alive during the scope of the reference itself. -### Mutable references (`&mut`) - r[type.pointer.reference.mut] +### Mutable references (`&mut`) r[type.pointer.reference.mut.intro] Mutable references point to memory which is owned by some other value. @@ -44,9 +40,8 @@ A mutable reference type is written `&mut type` or `&'a mut type`. r[type.pointer.reference.mut.copy] A mutable reference (that hasn't been borrowed) is the only way to access the value it points to, so is not `Copy`. -## Raw pointers (`*const` and `*mut`) - r[type.pointer.raw] +## Raw pointers (`*const` and `*mut`) r[type.pointer.raw.syntax] > **Syntax**\ @@ -75,15 +70,13 @@ When comparing raw pointers to [dynamically sized types] they also have their ad r[type.pointer.raw.constructor] Raw pointers can be created directly using `&raw const` for `*const` pointers and `&raw mut` for `*mut` pointers. -## Smart Pointers - r[type.pointer.smart] +## Smart Pointers The standard library contains additional 'smart pointer' types beyond references and raw pointers. -## Bit validity - r[type.pointer.validity] +## Bit validity r[type.pointer.validity.pointer-fragment] Despite pointers and references being similar to `usize`s in the machine code emitted on most platforms, diff --git a/src/types/slice.md b/src/types/slice.md index 79c340a87..3f4f71a7c 100644 --- a/src/types/slice.md +++ b/src/types/slice.md @@ -1,6 +1,5 @@ -# Slice types - r[type.slice] +# Slice types r[type.slice.syntax] > **Syntax**\ diff --git a/src/types/struct.md b/src/types/struct.md index 6a672f7af..eda170e3e 100644 --- a/src/types/struct.md +++ b/src/types/struct.md @@ -1,6 +1,5 @@ -# Struct types - r[type.struct] +# Struct types r[type.struct.intro] A `struct` *type* is a heterogeneous product of other types, called the diff --git a/src/types/textual.md b/src/types/textual.md index 294c791fd..a6ad38ffc 100644 --- a/src/types/textual.md +++ b/src/types/textual.md @@ -1,6 +1,5 @@ -# Textual types - r[type.text] +# Textual types r[type.text.intro] The types `char` and `str` hold textual data. @@ -26,9 +25,8 @@ r[type.text.str-unsized] Since `str` is a [dynamically sized type], it can only be instantiated through a pointer type, such as `&str`. -## Layout and bit validity - r[type.text.layout] +## Layout and bit validity r[type.layout.char-layout] `char` is guaranteed to have the same size and alignment as `u32` on all platforms. diff --git a/src/types/trait-object.md b/src/types/trait-object.md index 0c4c7596b..c3946252c 100644 --- a/src/types/trait-object.md +++ b/src/types/trait-object.md @@ -1,6 +1,5 @@ -# Trait objects - r[type.trait-object] +# Trait objects r[type.trait-object.syntax] > **Syntax**\ @@ -103,9 +102,8 @@ fn main() { In this example, the trait `Printable` occurs as a trait object in both the type signature of `print`, and the cast expression in `main`. -## Trait Object Lifetime Bounds - r[type.trait-object.lifetime-bounds] +## Trait Object Lifetime Bounds Since a trait object can contain references, the lifetimes of those references need to be expressed as part of the trait object. This lifetime is written as diff --git a/src/types/tuple.md b/src/types/tuple.md index 073fbd193..477c78a74 100644 --- a/src/types/tuple.md +++ b/src/types/tuple.md @@ -1,6 +1,5 @@ -# Tuple types - r[type.tuple] +# Tuple types r[type.tuple.syntax] > **Syntax**\ diff --git a/src/types/union.md b/src/types/union.md index c8801ee2f..6c3dbfcaf 100644 --- a/src/types/union.md +++ b/src/types/union.md @@ -1,6 +1,5 @@ -# Union types - r[type.union] +# Union types r[type.union.intro] A *union type* is a nominal, heterogeneous C-like union, denoted by the name of diff --git a/src/unsafe-keyword.md b/src/unsafe-keyword.md index 333140dd1..2443e65c6 100644 --- a/src/unsafe-keyword.md +++ b/src/unsafe-keyword.md @@ -1,6 +1,5 @@ -# The `unsafe` keyword - r[unsafe] +# The `unsafe` keyword r[unsafe.intro] The `unsafe` keyword can occur in several different contexts: @@ -12,9 +11,8 @@ It plays several different roles, depending on where it is used and whether the The following discusses each of these cases. See the [keyword documentation][keyword] for some illustrative examples. -## Unsafe functions (`unsafe fn`) - r[unsafe.fn] +## Unsafe functions (`unsafe fn`) r[unsafe.fn.intro] Unsafe functions are functions that are not safe in all contexts and/or for all possible inputs. @@ -25,9 +23,8 @@ The unsafe function should come with documentation explaining what those extra s r[unsafe.fn.safety] Such a function must be prefixed with the keyword `unsafe` and can only be called from inside an `unsafe` block, or inside `unsafe fn` without the [`unsafe_op_in_unsafe_fn`] lint. -## Unsafe blocks (`unsafe {}`) - r[unsafe.block] +## Unsafe blocks (`unsafe {}`) r[unsafe.block.intro] A block of code can be prefixed with the `unsafe` keyword, to permit calling `unsafe` functions or dereferencing raw pointers. @@ -51,9 +48,8 @@ For example, a doubly-linked list is not a tree structure and can only be repres By using `unsafe` blocks to represent the reverse links as raw pointers, it can be implemented without reference counting. (See ["Learn Rust With Entirely Too Many Linked Lists"](https://rust-unofficial.github.io/too-many-lists/) for a more in-depth exploration of this particular example.) -## Unsafe traits (`unsafe trait`) - r[unsafe.trait] +## Unsafe traits (`unsafe trait`) r[unsafe.trait.intro] An unsafe trait is a trait that comes with extra safety conditions that must be upheld by *implementations* of the trait. @@ -62,9 +58,9 @@ The unsafe trait should come with documentation explaining what those extra safe r[unsafe.trait.safety] Such a trait must be prefixed with the keyword `unsafe` and can only be implemented by `unsafe impl` blocks. +r[unsafe.impl] ## Unsafe trait implementations (`unsafe impl`) -r[unsafe.impl] When implementing an unsafe trait, the implementation needs to be prefixed with the `unsafe` keyword. By writing `unsafe impl`, the programmer states that they have taken care of satisfying the extra safety conditions required by the trait. @@ -75,9 +71,9 @@ Unsafe trait implementations are the logical dual to unsafe traits: where unsafe [`get_unchecked`]: slice::get_unchecked [`unsafe_op_in_unsafe_fn`]: ../rustc/lints/listing/allowed-by-default.html#unsafe-op-in-unsafe-fn +r[unsafe.extern] ## Unsafe external blocks (`unsafe extern`) -r[unsafe.extern] The programmer who declares an [external block] must assure that the signatures of the items contained within are correct. Failing to do so may lead to undefined behavior. That this obligation has been met is indicated by writing `unsafe extern`. @@ -86,9 +82,9 @@ r[unsafe.extern.edition2024] [external block]: items/external-blocks.md +r[unsafe.attribute] ## Unsafe attributes (`#[unsafe(attr)]`) -r[unsafe.attribute] An [unsafe attribute] is one that has extra safety conditions that must be upheld when using the attribute. The compiler cannot check whether these conditions have been upheld. To assert that they have been, these attributes must be wrapped in `unsafe(..)`, e.g. `#[unsafe(no_mangle)]`. diff --git a/src/unsafety.md b/src/unsafety.md index 88aaf373b..6878bbd8a 100644 --- a/src/unsafety.md +++ b/src/unsafety.md @@ -1,6 +1,5 @@ -# Unsafety - r[safety] +# Unsafety r[safety.intro] Unsafe operations are those that can potentially violate the memory-safety diff --git a/src/variables.md b/src/variables.md index 0e22af6a5..31836d584 100644 --- a/src/variables.md +++ b/src/variables.md @@ -1,6 +1,5 @@ -# Variables - r[variable] +# Variables r[variable.intro] A _variable_ is a component of a stack frame, either a named function parameter, diff --git a/src/visibility-and-privacy.md b/src/visibility-and-privacy.md index 58e4b9614..a1f79bb10 100644 --- a/src/visibility-and-privacy.md +++ b/src/visibility-and-privacy.md @@ -1,6 +1,5 @@ -# Visibility and Privacy - r[vis] +# Visibility and Privacy r[vis.syntax] > **Syntax**\ @@ -152,9 +151,8 @@ For a Rust program to pass the privacy checking pass, all paths must be valid accesses given the two rules above. This includes all use statements, expressions, types, etc. -## `pub(in path)`, `pub(crate)`, `pub(super)`, and `pub(self)` - r[vis.scoped] +## `pub(in path)`, `pub(crate)`, `pub(super)`, and `pub(self)` r[vis.scoped.intro] In addition to public and private, Rust allows users to declare an item as @@ -239,9 +237,8 @@ fn main() { bar() } > specified scope. To access an item, all of its parent items up to the > current scope must still be visible as well. -## Re-exporting and Visibility - r[vis.reexports] +## Re-exporting and Visibility r[vis.reexports.intro] Rust allows publicly re-exporting items through a `pub use` directive. Because diff --git a/src/whitespace.md b/src/whitespace.md index cd099946b..45d58b3fa 100644 --- a/src/whitespace.md +++ b/src/whitespace.md @@ -1,6 +1,5 @@ -# Whitespace - r[lex.whitespace] +# Whitespace r[lex.whitespace.intro] Whitespace is any non-empty string containing only characters that have the From 0cccb2a363aa82b31bc4acc0b81bd47a75105cd7 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 5 Jan 2025 18:34:43 +0100 Subject: [PATCH 03/10] fixup margins --- theme/reference.css | 66 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/theme/reference.css b/theme/reference.css index 6d0551b56..a3777a1f6 100644 --- a/theme/reference.css +++ b/theme/reference.css @@ -159,6 +159,16 @@ dfn { font-size: 0.8em; } +/* included in the grid below as 20px */ +.page, .content { + padding-left: 0; + padding-right: 0; +} +/* required to accomodate above, somehow... */ +#menu-bar { + margin-left: 0; +} + main { /* To nicely display rules (`[a.b.c]`) on a side of the main text body we use grid layout. */ @@ -170,6 +180,10 @@ main { [text] auto /* Right margin */ [margin] minmax(20px, 1fr); + + /* We do these by hand via the grid */ + margin: 0; + padding: 0 !important; max-width: none !important; } @@ -190,6 +204,54 @@ main > .rule { grid-column: rules; } +/* This is quite dumb, ugh. + CSS doesn't allow margin colapsing between grid items and anything else + (src: ), which means that the margins + of li's children are not collapsed with ul's margins, adding too much margins. + + Ideally we'd add `

`s for each grid cell, so that margin collapsing happens + as-usual inside of them. But, we don't have that kind of control over mdbook. */ +main > ul > li > *:first-child, +main > ul > li > pre:first-child > pre.playground { + margin-top: 0; +} +main > ul > li > *:last-child, +main > ul > li > pre:last-child > pre.playground { + margin-bottom: 0; +} + +/* Similarly to the above, margin collapse doesn't happen between grid items, + so we have to replace it with grid gap. (p, pre, and ul had 16px vertical margins) */ +main { + row-gap: 16px; +} +main > p, +main > pre, +main > pre > pre.playground, +main > ul { + margin-top: 0; + margin-bottom: 0; +} + +/* Values for h2/h3/h4 margin-top and blockquote margin are taken from mdbook's general.css, + values for h2/h3/h4 margin-bottom are taken from */ +main > h2 { + margin-top: calc(2.5em - 16px); + margin-bottom: calc(0.83em - 16px); +} +main > h3 { + margin-top: calc(2.5em - 16px); + margin-bottom: calc(1em - 16px); +} +main > h4 { + margin-top: calc(2em - 16px); + margin-bottom: calc(1.33em - 16px); +} +main > blockquote { + margin-top: calc(20px - 16px); + margin-bottom: calc(20px - 16px); +} + main > .rule { max-width: unset; justify-self: right; @@ -197,6 +259,10 @@ main > .rule { } .rule-link { + float: right; + text-align: right; + padding-right: 10px; + /* Remove the blue coloring of links on rules that mdbook normally sets. */ color: #999 !important; } From bc02bf95f937b2ea5675cd6eebf54f6ac989945d Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 5 Jan 2025 18:34:43 +0100 Subject: [PATCH 04/10] try to fixup footnote definitioon margins --- theme/reference.css | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/theme/reference.css b/theme/reference.css index a3777a1f6..aa2f8d75e 100644 --- a/theme/reference.css +++ b/theme/reference.css @@ -204,6 +204,25 @@ main > .rule { grid-column: rules; } +/* Unset footnote margin, + see below for more information about margins */ +/* FIXME: this doesn't work. `unset` can still break the margin of the next element, + and since mdbook applies the margin to `:not(.footnore-definition)`, + it can literally be anything, so there is no way to properly fix it, + without changing mdbook... */ +:not(.footnote-definition) + .footnote-definition, +.footnote-definition + :not(.footnote-definition) { + margin-block-start: unset; +} + +:not(.footnote-definition) + .footnote-definition { + margin-top: calc(2em - 16px); +} + +.footnote-definition:has(+ :not(.footnote-definition)) { + margin-bottom: calc(2em - 16px); +} + /* This is quite dumb, ugh. CSS doesn't allow margin colapsing between grid items and anything else (src: ), which means that the margins From d5cdf553cec4df64240a6a77e314213fddd9d16d Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 5 Jan 2025 18:34:43 +0100 Subject: [PATCH 05/10] align rules to the elements after them --- theme/reference.css | 59 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/theme/reference.css b/theme/reference.css index aa2f8d75e..dd5f4cfe7 100644 --- a/theme/reference.css +++ b/theme/reference.css @@ -156,7 +156,10 @@ dfn { /* Rules are generated via r[foo.bar] syntax, processed by mdbook-spec. */ .rule { - font-size: 0.8em; + --font-size-mult: 0.8; + --font-size: calc(1em * var(--font-size-mult)); + + font-size: var(--font-size); } /* included in the grid below as 20px */ @@ -296,6 +299,60 @@ main > .rule { width: 20px; } +/* Align rules to various siblings */ +.rule:has(+ p), +.rule:has(+ ul) { + margin-top: calc((1em - var(--font-size)) / var(--font-size-mult) / 2); +} + +.rule:has(+ h1) { + align-self: center; +} + +.rule:has(+ h2) { + /* multiplying by this turns h2's em into .rule's em*/ + --h2-em-mult: calc( + (1 / var(--font-size-mult)) /* to main font size */ + * 1.5 /* to h2 font size */ + ); + + margin-top: calc( + /* h2 margin top */ + 2.5em * var(--h2-em-mult) - 16px + /* half of the font size difference */ + + (1em * var(--h2-em-mult) - 1em) / 2 + ) +} +.rule:has(+ h3) { + /* multiplying by this turns h3's em into .rule's em*/ + --h3-em-mult: calc( + (1 / var(--font-size-mult)) /* to main font size */ + * 1.17 /* to h3 font size */ + ); + + margin-top: calc( + /* h3 margin top */ + 2.5em * var(--h3-em-mult) - 16px + /* half of the font size difference */ + + (1em * var(--h3-em-mult) - 1em) / 2 + ) +} + +.rule:has(+ h4) { + /* multiplying by this turns h4's em into .rule's em*/ + --h4-em-mult: calc( + (1 / var(--font-size-mult)) /* to main font size */ + * 1 /* to h4 font size */ + ); + + margin-top: calc( + /* h4 margin top */ + 2em * var(--h4-em-mult) - 16px + /* half of the font size difference */ + + (1em * var(--h4-em-mult) - 1em) / 2 + ) +} + /* Sets the color for [!HISTORY] blockquote admonitions. */ .history > blockquote { background: #f7c0eb; From 5f19268317fd315ca1c6455d327f2945899cd8cf Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 5 Jan 2025 18:34:43 +0100 Subject: [PATCH 06/10] word-wrap rule links --- mdbook-spec/src/rules.rs | 5 +++-- theme/reference.css | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mdbook-spec/src/rules.rs b/mdbook-spec/src/rules.rs index b477ab721..e495f4851 100644 --- a/mdbook-spec/src/rules.rs +++ b/mdbook-spec/src/rules.rs @@ -105,9 +105,10 @@ impl Spec { } format!( "
\ - [{rule_id}]\ + [{rule_id_broken}]\ {test_html}\ -
\n" +
\n", + rule_id_broken = rule_id.replace(".", "."), ) }) .to_string() diff --git a/theme/reference.css b/theme/reference.css index dd5f4cfe7..70a503203 100644 --- a/theme/reference.css +++ b/theme/reference.css @@ -284,6 +284,8 @@ main > .rule { float: right; text-align: right; padding-right: 10px; + /* We add `` ourselves and only want breaks there */ + word-break: keep-all; /* Remove the blue coloring of links on rules that mdbook normally sets. */ color: #999 !important; } From ce4c198f69fb2caefb98c2f7be016abd0687f616 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sun, 5 Jan 2025 18:34:43 +0100 Subject: [PATCH 07/10] hide rules behind [*], if the "margin" is too thin --- mdbook-spec/src/rules.rs | 2 +- theme/reference.css | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mdbook-spec/src/rules.rs b/mdbook-spec/src/rules.rs index e495f4851..96d358f85 100644 --- a/mdbook-spec/src/rules.rs +++ b/mdbook-spec/src/rules.rs @@ -105,7 +105,7 @@ impl Spec { } format!( "\n", rule_id_broken = rule_id.replace(".", "."), diff --git a/theme/reference.css b/theme/reference.css index 70a503203..3634ffe2c 100644 --- a/theme/reference.css +++ b/theme/reference.css @@ -278,6 +278,10 @@ main > .rule { max-width: unset; justify-self: right; width: 100%; + /* We use a container query to know the size of the "left margin", + so that we can hide rules is there is not enough space. */ + container-type: inline-size; + container-name: rule; } .rule-link { @@ -301,6 +305,19 @@ main > .rule { width: 20px; } +/* Hide the rules if the width of the container is too small. + The cutoff point is chosen semi-arbitrary, it felt that + when `width < 14em`, there are too many breaks. */ +@container rule (width < 14em) { + main > .rule a span { + display: none; + } + + main > .rule a::before { + content: "[*]"; + } +} + /* Align rules to various siblings */ .rule:has(+ p), .rule:has(+ ul) { From 1f9ea21e3aeba1cabf6d105907559f728602f8bb Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Wed, 8 Jan 2025 17:50:18 +0100 Subject: [PATCH 08/10] title rule links i.e. they'll show their id on hover; good for when they are wrapped or hidden. --- mdbook-spec/src/rules.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mdbook-spec/src/rules.rs b/mdbook-spec/src/rules.rs index 96d358f85..1149826ae 100644 --- a/mdbook-spec/src/rules.rs +++ b/mdbook-spec/src/rules.rs @@ -105,7 +105,7 @@ impl Spec { } format!( "\n", rule_id_broken = rule_id.replace(".", "."), From 13869f4743dd494b358e8d41bb58f521f71c3e68 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Wed, 8 Jan 2025 12:37:35 +0100 Subject: [PATCH 09/10] =?UTF-8?q?Move=20rule=20links=20in=20the=20presence?= =?UTF-8?q?=20of=20=C2=BB=20b/c=20of=20linked=20headers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- theme/reference.css | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/theme/reference.css b/theme/reference.css index 3634ffe2c..7fd63511f 100644 --- a/theme/reference.css +++ b/theme/reference.css @@ -298,11 +298,18 @@ main > .rule { navigate to it. This adds an indicator that the linked rule is the one that is "current", just like normal headers are in mdbook. */ -.rule:target::before { +.rule:target a span::before { display: inline-block; content: "»"; - margin-inline-start: -20px; - width: 20px; + padding-right: 5px; +} + +/* Dodge » from headings */ +.rule:has(+ h1:target), +.rule:has(+ h2:target), +.rule:has(+ h3:target), +.rule:has(+ h4:target) { + padding-right: 24px; } /* Hide the rules if the width of the container is too small. From 1f12877d1cbc5f1c1237c4b07088ac868844cc39 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 14 Jan 2025 09:24:33 -0800 Subject: [PATCH 10/10] Add h5/h6 support --- theme/reference.css | 46 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/theme/reference.css b/theme/reference.css index 7fd63511f..2d6d86c49 100644 --- a/theme/reference.css +++ b/theme/reference.css @@ -255,8 +255,8 @@ main > ul { margin-bottom: 0; } -/* Values for h2/h3/h4 margin-top and blockquote margin are taken from mdbook's general.css, - values for h2/h3/h4 margin-bottom are taken from */ +/* Values for header margin-top and blockquote margin are taken from mdbook's general.css, + values for header margin-bottom are taken from */ main > h2 { margin-top: calc(2.5em - 16px); margin-bottom: calc(0.83em - 16px); @@ -269,6 +269,14 @@ main > h4 { margin-top: calc(2em - 16px); margin-bottom: calc(1.33em - 16px); } +main > h5 { + margin-top: calc(2em - 16px); + margin-bottom: calc(1.67em - 16px); +} +main > h6 { + margin-top: calc(2em - 16px); + margin-bottom: calc(2.33em - 16px); +} main > blockquote { margin-top: calc(20px - 16px); margin-bottom: calc(20px - 16px); @@ -308,7 +316,9 @@ main > .rule { .rule:has(+ h1:target), .rule:has(+ h2:target), .rule:has(+ h3:target), -.rule:has(+ h4:target) { +.rule:has(+ h4:target), +.rule:has(+ h5:target), +.rule:has(+ h6:target) { padding-right: 24px; } @@ -379,6 +389,36 @@ main > .rule { ) } +.rule:has(+ h5) { + /* multiplying by this turns h5's em into .rule's em*/ + --h5-em-mult: calc( + (1 / var(--font-size-mult)) /* to main font size */ + * 0.83 /* to h5 font size */ + ); + + margin-top: calc( + /* h5 margin top */ + 2em * var(--h5-em-mult) - 16px + /* half of the font size difference */ + + (1em * var(--h5-em-mult) - 1em) / 2 + ) +} + +.rule:has(+ h6) { + /* multiplying by this turns h6's em into .rule's em*/ + --h6-em-mult: calc( + (1 / var(--font-size-mult)) /* to main font size */ + * 0.67 /* to h6 font size */ + ); + + margin-top: calc( + /* h6 margin top */ + 2em * var(--h6-em-mult) - 16px + /* half of the font size difference */ + + (1em * var(--h6-em-mult) - 1em) / 2 + ) +} + /* Sets the color for [!HISTORY] blockquote admonitions. */ .history > blockquote { background: #f7c0eb;