diff options
Diffstat (limited to 'src/doc')
66 files changed, 1488 insertions, 408 deletions
diff --git a/src/doc/edition-guide/src/rust-2018/path-changes.md b/src/doc/edition-guide/src/rust-2018/path-changes.md index ca2c27ca2..60bf1155e 100644 --- a/src/doc/edition-guide/src/rust-2018/path-changes.md +++ b/src/doc/edition-guide/src/rust-2018/path-changes.md @@ -206,6 +206,11 @@ mod submodule { } ``` +If you have a local module or item with the same name as an external crate, a +path begining with that name will be taken to refer to the local module or +item. To explicitly refer to the external crate, use the `::name` form. + + ### No more `mod.rs` In Rust 2015, if you have a submodule: @@ -272,7 +277,7 @@ enough to have submodules. In Rust 2018, paths in `use` declarations and in other code work the same way, both in the top-level module and in any submodule. You can use a relative path from the current scope, a path starting from an external crate name, or a path -starting with `crate`, `super`, or `self`. +starting with `::`, `crate`, `super`, or `self`. Code that looked like this: @@ -371,9 +376,3 @@ mod submodule { This makes it easy to move code around in a project, and avoids introducing additional complexity to multi-module projects. - -If a path is ambiguous, such as if you have an external crate and a local -module or item with the same name, you'll get an error, and you'll need to -either rename one of the conflicting names or explicitly disambiguate the path. -To explicitly disambiguate a path, use `::name` for an external crate name, or -`self::name` for a local module or item. diff --git a/src/doc/embedded-book/src/intro/install/verify.md b/src/doc/embedded-book/src/intro/install/verify.md index e60911dc3..45caec90f 100644 --- a/src/doc/embedded-book/src/intro/install/verify.md +++ b/src/doc/embedded-book/src/intro/install/verify.md @@ -3,7 +3,7 @@ In this section we check that some of the required tools / drivers have been correctly installed and configured. -Connect your laptop / PC to the discovery board using a micro USB cable. The +Connect your laptop / PC to the discovery board using a Mini-USB USB cable. The discovery board has two USB connectors; use the one labeled "USB ST-LINK" that sits on the center of the edge of the board. diff --git a/src/doc/nomicon/src/beneath-std.md b/src/doc/nomicon/src/beneath-std.md index 6f05182b2..02a02bd7c 100644 --- a/src/doc/nomicon/src/beneath-std.md +++ b/src/doc/nomicon/src/beneath-std.md @@ -1,10 +1,108 @@ -# Beneath std +# Beneath `std` -This section documents (or will document) features that are provided by the standard library and -that `#![no_std]` developers have to deal with (i.e. provide) to build `#![no_std]` binary crates. A -(likely incomplete) list of such features is shown below: +This section documents features that are normally provided by the `std` crate and +that `#![no_std]` developers have to deal with (i.e. provide) to build +`#![no_std]` binary crates. -- `#[lang = "eh_personality"]` -- `#[lang = "start"]` -- `#[lang = "termination"]` -- `#[panic_implementation]` +## Using `libc` + +In order to build a `#[no_std]` executable we will need `libc` as a dependency. +We can specify this using our `Cargo.toml` file: + +```toml +[dependencies] +libc = { version = "0.2.146", default-features = false } +``` + +Note that the default features have been disabled. This is a critical step - +**the default features of `libc` include the `std` crate and so must be +disabled.** + +Alternatively, we can use the unstable `rustc_private` private feature together +with an `extern crate libc;` declaration as shown in the examples below. + +## Writing an executable without `std` + +We will probably need a nightly version of the compiler to produce +a `#![no_std]` executable because on many platforms, we have to provide the +`eh_personality` [lang item], which is unstable. + +Controlling the entry point is possible in two ways: the `#[start]` attribute, +or overriding the default shim for the C `main` function with your own. +Additionally, it's required to define a [panic handler function](panic-handler.html). + +The function marked `#[start]` is passed the command line parameters +in the same format as C (aside from the exact integer types being used): + +```rust +#![feature(start, lang_items, core_intrinsics, rustc_private)] +#![allow(internal_features)] +#![no_std] + +// Necessary for `panic = "unwind"` builds on some platforms. +#![feature(panic_unwind)] +extern crate unwind; + +// Pull in the system libc library for what crt0.o likely requires. +extern crate libc; + +use core::panic::PanicInfo; + +// Entry point for this program. +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} + +// These functions are used by the compiler, but not for an empty program like this. +// They are normally provided by `std`. +#[lang = "eh_personality"] +fn rust_eh_personality() {} +#[panic_handler] +fn panic_handler(_info: &PanicInfo) -> ! { core::intrinsics::abort() } +``` + +To override the compiler-inserted `main` shim, we have to disable it +with `#![no_main]` and then create the appropriate symbol with the +correct ABI and the correct name, which requires overriding the +compiler's name mangling too: + +```rust +#![feature(lang_items, core_intrinsics, rustc_private)] +#![allow(internal_features)] +#![no_std] +#![no_main] + +// Necessary for `panic = "unwind"` builds on some platforms. +#![feature(panic_unwind)] +extern crate unwind; + +// Pull in the system libc library for what crt0.o likely requires. +extern crate libc; + +use core::ffi::{c_char, c_int}; +use core::panic::PanicInfo; + +// Entry point for this program. +#[no_mangle] // ensure that this symbol is included in the output as `main` +extern "C" fn main(_argc: c_int, _argv: *const *const c_char) -> c_int { + 0 +} + +// These functions are used by the compiler, but not for an empty program like this. +// They are normally provided by `std`. +#[lang = "eh_personality"] +fn rust_eh_personality() {} +#[panic_handler] +fn panic_handler(_info: &PanicInfo) -> ! { core::intrinsics::abort() } +``` + +If you are working with a target that doesn't have binary releases of the +standard library available via rustup (this probably means you are building the +`core` crate yourself) and need compiler-rt intrinsics (i.e. you are probably +getting linker errors when building an executable: +``undefined reference to `__aeabi_memcpy'``), you need to manually link to the +[`compiler_builtins` crate] to get those intrinsics and solve the linker errors. + +[`compiler_builtins` crate]: https://crates.io/crates/compiler_builtins +[lang item]: https://doc.rust-lang.org/nightly/unstable-book/language-features/lang-items.html diff --git a/src/doc/nomicon/src/what-unsafe-does.md b/src/doc/nomicon/src/what-unsafe-does.md index 64694ee4d..67fbe8ae7 100644 --- a/src/doc/nomicon/src/what-unsafe-does.md +++ b/src/doc/nomicon/src/what-unsafe-does.md @@ -71,8 +71,7 @@ Rust considers it "safe" to: * Deadlock * Have a [race condition][race] * Leak memory -* Fail to call destructors -* Overflow integers +* Overflow integers (with the built-in operators such as `+` etc.) * Abort the program * Delete the production database diff --git a/src/doc/reference/src/behavior-considered-undefined.md b/src/doc/reference/src/behavior-considered-undefined.md index 9d1732d07..f140fb20c 100644 --- a/src/doc/reference/src/behavior-considered-undefined.md +++ b/src/doc/reference/src/behavior-considered-undefined.md @@ -14,11 +14,15 @@ undefined behavior, it is *unsound*. <div class="warning"> -***Warning:*** The following list is not exhaustive. There is no formal model of -Rust's semantics for what is and is not allowed in unsafe code, so there may be -more behavior considered unsafe. The following list is just what we know for -sure is undefined behavior. Please read the [Rustonomicon] before writing unsafe -code. +***Warning:*** The following list is not exhaustive; it may grow or shrink. +There is no formal model of Rust's semantics for what is and is not allowed in +unsafe code, so there may be more behavior considered unsafe. We also reserve +the right to make some of the behavior in that list defined in the future. In +other words, this list does not say that anything will *definitely* always be +undefined in all future Rust version (but we might make such commitments for +some list items in the future). + +Please read the [Rustonomicon] before writing unsafe code. </div> diff --git a/src/doc/reference/src/conditional-compilation.md b/src/doc/reference/src/conditional-compilation.md index c3a36effe..e724b21e2 100644 --- a/src/doc/reference/src/conditional-compilation.md +++ b/src/doc/reference/src/conditional-compilation.md @@ -129,6 +129,7 @@ Example values: * `"dragonfly"` * `"openbsd"` * `"netbsd"` +* `"none"` (typical for embedded targets) ### `target_family` diff --git a/src/doc/reference/src/items/implementations.md b/src/doc/reference/src/items/implementations.md index ee651cee5..37965569e 100644 --- a/src/doc/reference/src/items/implementations.md +++ b/src/doc/reference/src/items/implementations.md @@ -205,7 +205,7 @@ Examples of constraining situations: // T constrains by being an argument to GenericTrait. impl<T> GenericTrait<T> for i32 { /* ... */ } -// T constrains by being an arguement to GenericStruct +// T constrains by being an argument to GenericStruct impl<T> Trait for GenericStruct<T> { /* ... */ } // Likewise, N constrains by being an argument to ConstGenericStruct diff --git a/src/doc/reference/src/type-layout.md b/src/doc/reference/src/type-layout.md index 4c87954f3..aae3577f5 100644 --- a/src/doc/reference/src/type-layout.md +++ b/src/doc/reference/src/type-layout.md @@ -88,7 +88,7 @@ String slices are a UTF-8 representation of characters that have the same layout ## Tuple Layout -Tuples are laid out according to the [default representation][Default]. +Tuples are laid out according to the [`Rust` representation][`Rust`]. 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. @@ -110,7 +110,7 @@ All user-defined composite types (`struct`s, `enum`s, and `union`s) have a *representation* that specifies what the layout is for the type. The possible representations for a type are: -- [Default] +- [`Rust`] (default) - [`C`] - The [primitive representations] - [`transparent`] @@ -159,10 +159,12 @@ not change the layout of the fields themselves. For example, a struct with a `C` representation that contains a struct `Inner` with the default representation will not change the layout of `Inner`. -### The Default Representation +### <a id="the-default-representation"></a> The `Rust` Representation -Nominal types without a `repr` attribute have the default representation. -Informally, this representation is also called the `rust` representation. +The `Rust` representation is the default representation for nominal types +without a `repr` attribute. Using this representation explicitly through a +`repr` attribute is guaranteed to be the same as omitting the attribute +entirely. The only data layout guarantees made by this representation are those required for soundness. They are: @@ -543,7 +545,7 @@ important consequence of these rules is that a type with `#[repr(packed(1))]` The `align` and `packed` modifiers cannot be applied on the same type and a `packed` type cannot transitively contain another `align`ed type. `align` and -`packed` may only be applied to the [default] and [`C`] representations. +`packed` may only be applied to the [`Rust`] and [`C`] representations. The `align` modifier can also be applied on an `enum`. When it is, the effect on the `enum`'s alignment is the same as if the `enum` @@ -604,7 +606,7 @@ used with any other representation. [undefined behavior]: behavior-considered-undefined.md [55149]: https://github.com/rust-lang/rust/issues/55149 [`PhantomData<T>`]: special-types-and-traits.md#phantomdatat -[Default]: #the-default-representation +[`Rust`]: #the-rust-representation [`C`]: #the-c-representation [primitive representations]: #primitive-representations [structs]: items/structs.md diff --git a/src/doc/reference/src/types/boolean.md b/src/doc/reference/src/types/boolean.md index d8984025f..7ea99d185 100644 --- a/src/doc/reference/src/types/boolean.md +++ b/src/doc/reference/src/types/boolean.md @@ -92,6 +92,12 @@ boolean type for its operands, they evaluate using the rules of [boolean logic]. * `a < b` is the same as `!(a >= b)` * `a <= b` is the same as `a == b | a < b` +## Bit validity + +The single byte of a `bool` is guaranteed to be initialized (in other words, +`transmute::<bool, u8>(...)` is always sound -- but since some bit patterns +are invalid `bool`s, the inverse is not always sound). + [boolean logic]: https://en.wikipedia.org/wiki/Boolean_algebra [enumerated type]: enum.md [expressions]: ../expressions.md diff --git a/src/doc/reference/src/types/numeric.md b/src/doc/reference/src/types/numeric.md index 8ab53a792..bd59daa6b 100644 --- a/src/doc/reference/src/types/numeric.md +++ b/src/doc/reference/src/types/numeric.md @@ -45,3 +45,8 @@ within an object along with one byte past the end. > `isize` are either 32-bit or 64-bit. As a consequence, 16-bit > pointer support is limited and may require explicit care and acknowledgment > from a library to support. + +## Bit validity + +For every numeric type, `T`, the bit validity of `T` is equivalent to the bit +validity of `[u8; size_of::<T>()]`. An uninitialized byte is not a valid `u8`. diff --git a/src/doc/reference/src/types/pointer.md b/src/doc/reference/src/types/pointer.md index 4a74370a5..cbbf356e8 100644 --- a/src/doc/reference/src/types/pointer.md +++ b/src/doc/reference/src/types/pointer.md @@ -50,6 +50,16 @@ Raw pointers can be created directly using [`core::ptr::addr_of!`] for `*const` The standard library contains additional 'smart pointer' types beyond references and raw pointers. +## Bit validity + +Despite pointers and references being similar to `usize`s in the machine code emitted on most platforms, +the semantics of transmuting a reference or pointer type to a non-pointer type is currently undecided. +Thus, it may not be valid to transmute a pointer or reference type, `P`, to a `[u8; size_of::<P>()]`. + +For thin raw pointers (i.e., for `P = *const T` or `P = *mut T` for `T: Sized`), +the inverse direction (transmuting from an integer or array of integers to `P`) is always valid. +However, the pointer produced via such a transmutation may not be dereferenced (not even if `T` has size zero). + [`core::ptr::addr_of!`]: ../../core/ptr/macro.addr_of.html [`core::ptr::addr_of_mut!`]: ../../core/ptr/macro.addr_of_mut.html [Interior mutability]: ../interior-mutability.md diff --git a/src/doc/reference/src/types/textual.md b/src/doc/reference/src/types/textual.md index 65d563312..41ed35ea1 100644 --- a/src/doc/reference/src/types/textual.md +++ b/src/doc/reference/src/types/textual.md @@ -17,6 +17,12 @@ is valid UTF-8. Calling a `str` method with a non-UTF-8 buffer can cause Since `str` is a [dynamically sized type], it can only be instantiated through a pointer type, such as `&str`. +## Bit validity + +Every byte of a `char` is guaranteed to be initialized (in other words, +`transmute::<char, [u8; size_of::<char>()]>(...)` is always sound -- but since +some bit patterns are invalid `char`s, the inverse is not always sound). + [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value [Undefined Behavior]: ../behavior-considered-undefined.md [dynamically sized type]: ../dynamically-sized-types.md diff --git a/src/doc/rust-by-example/src/error/option_unwrap/defaults.md b/src/doc/rust-by-example/src/error/option_unwrap/defaults.md index 4c1844a20..513bb1df7 100644 --- a/src/doc/rust-by-example/src/error/option_unwrap/defaults.md +++ b/src/doc/rust-by-example/src/error/option_unwrap/defaults.md @@ -113,7 +113,7 @@ fn main() { ### See also: -[`closures`][closures], [`get_or_insert`][get_or_insert], [`get_or_insert_with`][get_or_insert_with], ,[`moved variables`][moved], [`or`][or], [`or_else`][or_else] +[`closures`][closures], [`get_or_insert`][get_or_insert], [`get_or_insert_with`][get_or_insert_with], [`moved variables`][moved], [`or`][or], [`or_else`][or_else] [closures]: https://doc.rust-lang.org/book/ch13-01-closures.html [get_or_insert]: https://doc.rust-lang.org/core/option/enum.Option.html#method.get_or_insert diff --git a/src/doc/rust-by-example/src/scope/borrow.md b/src/doc/rust-by-example/src/scope/borrow.md index 72c70e736..018f00c35 100644 --- a/src/doc/rust-by-example/src/scope/borrow.md +++ b/src/doc/rust-by-example/src/scope/borrow.md @@ -20,7 +20,9 @@ fn borrow_i32(borrowed_i32: &i32) { } fn main() { - // Create a boxed i32, and a stacked i32 + // Create a boxed i32 in the heap, and a i32 on the stack + // Remember: numbers can have arbitrary underscores added for readability + // 5_i32 is the same as 5i32 let boxed_i32 = Box::new(5_i32); let stacked_i32 = 6_i32; diff --git a/src/doc/rust-by-example/src/scope/lifetime/fn.md b/src/doc/rust-by-example/src/scope/lifetime/fn.md index 6c5c8afe6..095f84b6e 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/fn.md +++ b/src/doc/rust-by-example/src/scope/lifetime/fn.md @@ -57,7 +57,8 @@ fn main() { ### See also: -[functions][fn] +[Functions][fn] + +[fn]: ../../fn.md [elision]: elision.md -[fn]: fn.md diff --git a/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md b/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md index 3f31693fa..3c0b8b0b7 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md +++ b/src/doc/rust-by-example/src/scope/lifetime/static_lifetime.md @@ -17,10 +17,10 @@ confusion when learning Rust. Here are some examples for each situation: ## Reference lifetime As a reference lifetime `'static` indicates that the data pointed to by -the reference lives for the entire lifetime of the running program. +the reference lives for the remaining lifetime of the running program. It can still be coerced to a shorter lifetime. -There are two ways to make a variable with `'static` lifetime, and both +There are two common ways to make a variable with `'static` lifetime, and both are stored in the read-only memory of the binary: * Make a constant with the `static` declaration. @@ -62,6 +62,31 @@ fn main() { } ``` +Since `'static` references only need to be valid for the _remainder_ of +a program's life, they can be created while the program is executed. Just to +demonstrate, the below example uses +[`Box::leak`](https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak) +to dynamically create `'static` references. In that case it definitely doesn't +live for the entire duration, but only for the leaking point onward. + +```rust,editable,compile_fail +extern crate rand; +use rand::Fill; + +fn random_vec() -> &'static [usize; 100] { + let mut rng = rand::thread_rng(); + let mut boxed = Box::new([0; 100]); + boxed.try_fill(&mut rng).unwrap(); + Box::leak(boxed) +} + +fn main() { + let first: &'static [usize; 100] = random_vec(); + let second: &'static [usize; 100] = random_vec(); + assert_ne!(first, second) +} +``` + ## Trait bound As a trait bound, it means the type does not contain any non-static diff --git a/src/doc/rustc-dev-guide/.editorconfig b/src/doc/rustc-dev-guide/.editorconfig index cb3312517..443c4c284 100644 --- a/src/doc/rustc-dev-guide/.editorconfig +++ b/src/doc/rustc-dev-guide/.editorconfig @@ -3,6 +3,7 @@ root = true [src/*] end_of_line = lf insert_final_newline = true +max_line_length = 100 [ci/*.sh] indent_style = space diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 97f3503ae..41e16c5e6 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -14,6 +14,7 @@ - [Building Documentation](./building/compiler-documenting.md) - [Rustdoc overview](./rustdoc.md) - [Adding a new target](./building/new-target.md) + - [Optimized build](./building/optimized-build.md) - [Testing the compiler](./tests/intro.md) - [Running tests](./tests/running.md) - [Testing with Docker](./tests/docker.md) @@ -112,7 +113,9 @@ - [Bound vars and Parameters](./bound-vars-and-params.md) - [Type inference](./type-inference.md) - [Trait solving](./traits/resolution.md) - - [Early and Late Bound Parameter Definitions](./early-late-bound.md) + - [Early and Late Bound Parameter Definitions](./early-late-bound-summary.md) + - [What are early and late bound parameters](./what-does-early-late-bound-mean.md) + - [Interactions with turbofishing](./turbofishing-and-early-late-bound.md) - [Higher-ranked trait bounds](./traits/hrtb.md) - [Caching subtleties](./traits/caching.md) - [Specialization](./traits/specialization.md) @@ -139,6 +142,7 @@ - [Tracking moves and initialization](./borrow_check/moves_and_initialization.md) - [Move paths](./borrow_check/moves_and_initialization/move_paths.md) - [MIR type checker](./borrow_check/type_check.md) + - [Drop check](./borrow_check/drop_check.md) - [Region inference](./borrow_check/region_inference.md) - [Constraint propagation](./borrow_check/region_inference/constraint_propagation.md) - [Lifetime parameters](./borrow_check/region_inference/lifetime_parameters.md) diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index 019d31138..27b6cddf2 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -5,6 +5,7 @@ Term | Meaning ------------------------------------------------------|-------- <span id="arena">arena/arena allocation</span> | An _arena_ is a large memory buffer from which other memory allocations are made. This style of allocation is called _arena allocation_. See [this chapter](../memory.md) for more info. <span id="ast">AST</span> | The abstract syntax tree produced by the `rustc_ast` crate; reflects user syntax very closely. +<span id="APIT">APIT</span> | An argument-position `impl Trait`. Also known as an anonymous type parameter. ([see the reference](https://doc.rust-lang.org/reference/types/impl-trait.html#anonymous-type-parameters)). <span id="binder">binder</span> | A "binder" is a place where a variable or type is declared; for example, the `<T>` is a binder for the generic type parameter `T` in `fn foo<T>(..)`, and \|`a`\|` ...` is a binder for the parameter `a`. See [the background chapter for more](./background.md#free-vs-bound). <span id="body-id">BodyId</span> | An identifier that refers to a specific body (definition of a function or constant) in the crate. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). <span id="bound-var">bound variable</span> | A "bound variable" is one that is declared within an expression/term. For example, the variable `a` is bound within the closure expression \|`a`\|` a * 2`. See [the background chapter for more](./background.md#free-vs-bound) @@ -23,7 +24,7 @@ Term | Meaning <span id="double-ptr">double pointer</span> | A pointer with additional metadata. See "fat pointer" for more. <span id="drop-glue">drop glue</span> | (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types. <span id="dst">DST</span> | Short for Dynamically-Sized Type, this is a type for which the compiler cannot statically know the size in memory (e.g. `str` or `[u8]`). Such types don't implement `Sized` and cannot be allocated on the stack. They can only occur as the last field in a struct. They can only be used behind a pointer (e.g. `&str` or `&[u8]`). -<span id="ebl">early-bound lifetime</span> | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `Substs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#bound-regions)) +<span id="ebl">early-bound lifetime</span> | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `GenericArgs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#bound-regions)) <span id="empty-type">empty type</span> | see "uninhabited type". <span id="fat-ptr">fat pointer</span> | A two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of "fat pointers": references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers". <span id="free-var">free variable</span> | A "free variable" is one that is not bound within an expression or term; see [the background chapter for more](./background.md#free-vs-bound) @@ -67,6 +68,8 @@ Term | Meaning <span id="recovery">recovery</span> | Recovery refers to handling invalid syntax during parsing (e.g. a missing comma) and continuing to parse the AST. This avoid showing spurious errors to the user (e.g. showing 'missing field' errors when the struct definition contains errors). <span id="region">region</span> | Another term for "lifetime" often used in the literature and in the borrow checker. <span id="rib">rib</span> | A data structure in the name resolver that keeps track of a single scope for names. ([see more](../name-resolution.md)) +<span id="rpit">RPIT</span> | A return-position `impl Trait`. ([see the reference](https://doc.rust-lang.org/reference/types/impl-trait.html#abstract-return-types)). +<span id="rpitit">RPITIT</span> | A return-position `impl Trait` *in trait*. Unlike RPIT, this is desugared to a generic associated type (GAT). Introduced in [RFC 3425](https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html). ([see more](../return-position-impl-trait-in-trait.md)) <span id="scrutinee">scrutinee</div> | A scrutinee is the expression that is matched on in `match` expressions and similar pattern matching constructs. For example, in `match x { A => 1, B => 2 }`, the expression `x` is the scrutinee. <span id="sess">sess</span> | The compiler session, which stores global data used throughout compilation <span id="side-tables">side tables</span> | Because the AST and HIR are immutable once created, we often carry extra information about them in the form of hashtables, indexed by the id of a particular node. @@ -76,6 +79,7 @@ Term | Meaning <span id="substs">substs</span> | The substitutions for a given generic type or item (e.g. the `i32`, `u32` in `HashMap<i32, u32>`). <span id="sysroot">sysroot</span> | The directory for build artifacts that are loaded by the compiler at runtime. ([see more](../building/bootstrapping.html#what-is-a-sysroot)) <span id="tag">tag</span> | The "tag" of an enum/generator encodes the [discriminant](#discriminant) of the active variant/state. Tags can either be "direct" (simply storing the discriminant in a field) or use a ["niche"](#niche). +<span id="tait">TAIT</span> | A type-alias `impl Trait`. Introduced in [RFC 2515](https://rust-lang.github.io/rfcs/2515-type_alias_impl_trait.html). <span id="tcx">`tcx`</span> | Standard variable name for the "typing context" (`TyCtxt`), main data structure of the compiler. ([see more](../ty.md)) <span id="lifetime-tcx">`'tcx`</span> | The lifetime of the allocation arenas used by `TyCtxt`. Most data interned during a compilation session will use this lifetime with the exception of HIR data which uses the `'hir` lifetime. ([see more](../ty.md)) <span id="token">token</span> | The smallest unit of parsing. Tokens are produced after lexing ([see more](../the-parser.md)). diff --git a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md index 08af10f89..dd16b1e28 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -2,7 +2,7 @@ <!-- toc --> -<!-- date-check: Feb 2023 --> +<!-- date-check: Jul 2023 --> There is no formal policy about when to update LLVM or what it can be updated to, but a few guidelines are applied: @@ -52,7 +52,7 @@ An example PR: ## New LLVM Release Updates -<!-- date-check: Aug 2022 --> +<!-- date-check: Jul 2023 --> Unlike bugfixes, updating to a new release of LLVM typically requires a lot more work. @@ -139,6 +139,7 @@ so let's go through each in detail. > - [LLVM 13](https://github.com/rust-lang/rust/pull/87570) > - [LLVM 14](https://github.com/rust-lang/rust/pull/93577) > - [LLVM 15](https://github.com/rust-lang/rust/pull/99464) + > - [LLVM 16](https://github.com/rust-lang/rust/pull/109474) Note that sometimes it's easiest to land [`llvm-wrapper`] compatibility as a PR before actually updating `src/llvm-project`. diff --git a/src/doc/rustc-dev-guide/src/borrow_check/drop_check.md b/src/doc/rustc-dev-guide/src/borrow_check/drop_check.md new file mode 100644 index 000000000..51d1ddd83 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/borrow_check/drop_check.md @@ -0,0 +1,154 @@ +# Drop Check + +We generally require the type of locals to be well-formed whenever the +local is used. This includes proving the where-bounds of the local and +also requires all regions used by it to be live. + +The only exception to this is when implicitly dropping values when they +go out of scope. This does not necessarily require the value to be live: + +```rust +fn main() { + let x = vec![]; + { + let y = String::from("I am temporary"); + x.push(&y); + } + // `x` goes out of scope here, after the reference to `y` + // is invalidated. This means that while dropping `x` its type + // is not well-formed as it contain regions which are not live. +} +``` + +This is only sound if dropping the value does not try to access any dead +region. We check this by requiring the type of the value to be +drop-live. +The requirements for which are computed in `fn dropck_outlives`. + +The rest of this section uses the following type definition for a type +which requires its region parameter to be live: + +```rust +struct PrintOnDrop<'a>(&'a str); +impl<'a> Drop for PrintOnDrop<'_> { + fn drop(&mut self) { + println!("{}", self.0); + } +} +``` + +## How values are dropped + +At its core, a value of type `T` is dropped by executing its "drop +glue". Drop glue is compiler generated and first calls `<T as +Drop>::drop` and then recursively calls the drop glue of any recursively +owned values. + +- If `T` has an explicit `Drop` impl, call `<T as Drop>::drop`. +- Regardless of whether `T` implements `Drop`, recurse into all values + *owned* by `T`: + - references, raw pointers, function pointers, function items, trait + objects[^traitobj], and scalars do not own anything. + - tuples, slices, and arrays consider their elements to be owned. + For arrays of length zero we do not own any value of the element + type. + - all fields (of all variants) of ADTs are considered owned. We + consider all variants for enums. The exception here is + `ManuallyDrop<U>` which is not considered to own `U`. + `PhantomData<U>` also does not own anything. + closures and generators own their captured upvars. + +Whether a type has drop glue is returned by [`fn +Ty::needs_drop`](https://github.com/rust-lang/rust/blob/320b412f9c55bf480d26276ff0ab480e4ecb29c0/compiler/rustc_middle/src/ty/util.rs#L1086-L1108). + +### Partially dropping a local + +For types which do not implement `Drop` themselves, we can also +partially move parts of the value before dropping the rest. In this case +only the drop glue for the not-yet moved values is called, e.g. + +```rust +fn main() { + let mut x = (PrintOnDrop("third"), PrintOnDrop("first")); + drop(x.1); + println!("second") +} +``` + +During MIR building we assume that a local may get dropped whenever it +goes out of scope *as long as its type needs drop*. Computing the exact +drop glue for a variable happens **after** borrowck in the +`ElaborateDrops` pass. This means that even if some part of the local +have been dropped previously, dropck still requires this value to be +live. This is the case even if we completely moved a local. + +```rust +fn main() { + let mut x; + { + let temp = String::from("I am temporary"); + x = PrintOnDrop(&temp); + drop(x); + } +} //~ ERROR `temp` does not live long enough. +``` + +It should be possible to add some amount of drop elaboration before +borrowck, allowing this example to compile. There is an unstable feature +to move drop elaboration before const checking: +[#73255](https://github.com/rust-lang/rust/issues/73255). Such a feature +gate does not exist for doing some drop elaboration before borrowck, +although there's a [relevant +MCP](https://github.com/rust-lang/compiler-team/issues/558). + +[^traitobj]: you can consider trait objects to have a builtin `Drop` +implementation which directly uses the `drop_in_place` provided by the +vtable. This `Drop` implementation requires all its generic parameters +to be live. + +### `dropck_outlives` + +There are two distinct "liveness" computations that we perform: + +* a value `v` is *use-live* at location `L` if it may be "used" later; a + *use* here is basically anything that is not a *drop* +* a value `v` is *drop-live* at location `L` if it maybe dropped later + +When things are *use-live*, their entire type must be valid at `L`. When +they are *drop-live*, all regions that are required by dropck must be +valid at `L`. The values dropped in the MIR are *places*. + +The constraints computed by `dropck_outlives` for a type closely match +the generated drop glue for that type. Unlike drop glue, +`dropck_outlives` cares about the types of owned values, not the values +itself. For a value of type `T` + +- if `T` has an explicit `Drop`, require all generic arguments to be + live, unless they are marked with `#[may_dangle]` in which case they + are fully ignored +- regardless of whether `T` has an explicit `Drop`, recurse into all + types *owned* by `T` + - references, raw pointers, function pointers, function items, trait + objects[^traitobj], and scalars do not own anything. + - tuples, slices and arrays consider their element type to be owned. + **For arrays we currently do not check whether their length is + zero**. + - all fields (of all variants) of ADTs are considered owned. The + exception here is `ManuallyDrop<U>` which is not considered to own + `U`. **We consider `PhantomData<U>` to own `U`**. + - closures and generators own their captured upvars. + +The sections marked in bold are cases where `dropck_outlives` considers +types to be owned which are ignored by `Ty::needs_drop`. We only rely on +`dropck_outlives` if `Ty::needs_drop` for the containing local returned +`true`.This means liveness requirements can change depending on whether +a type is contained in a larger local. **This is inconsistent, and +should be fixed: an example [for +arrays](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8b5f5f005a03971b22edb1c20c5e6cbe) +and [for +`PhantomData`](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=44c6e2b1fae826329fd54c347603b6c8).**[^core] + +One possible way these inconsistencies can be fixed is by MIR building +to be more pessimistic, probably by making `Ty::needs_drop` weaker, or +alternatively, changing `dropck_outlives` to be more precise, requiring +fewer regions to be live. diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 0865f1955..1012e94fd 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -65,8 +65,8 @@ Also, using `x` rather than `x.py` is recommended as: Notice that this is not absolute, for instance, using Nushell in VSCode on Win10, typing `x` or `./x` still open the `x.py` in editor rather invoke the program :) -In the rest of documents, we use `x` to represent the straightly usage of `x.py`, which -means the following command: +In the rest of this guide, we use `x` rather than `x.py` directly. The following +command: ```bash ./x check diff --git a/src/doc/rustc-dev-guide/src/building/optimized-build.md b/src/doc/rustc-dev-guide/src/building/optimized-build.md new file mode 100644 index 000000000..1e1136b91 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/building/optimized-build.md @@ -0,0 +1,129 @@ +# Optimized build of the compiler + +<!-- toc --> + +There are multiple additional build configuration options and techniques that can used to compile a +build of `rustc` that is as optimized as possible (for example when building `rustc` for a Linux +distribution). The status of these configuration options for various Rust targets is tracked [here]. +This page describes how you can use these approaches when building `rustc` yourself. + +[here]: https://github.com/rust-lang/rust/issues/103595 + +## Link-time optimization + +Link-time optimization is a powerful compiler technique that can increase program performance. To +enable (Thin-)LTO when building `rustc`, set the `rust.lto` config option to `"thin"` +in `config.toml`: + +```toml +[rust] +lto = "thin" +``` + +> Note that LTO for `rustc` is currently supported and tested only for +> the `x86_64-unknown-linux-gnu` target. Other targets *may* work, but no guarantees are provided. +> Notably, LTO-optimized `rustc` currently produces [miscompilations] on Windows. + +[miscompilations]: https://github.com/rust-lang/rust/issues/109114 + +Enabling LTO on Linux has [produced] speed-ups by up to 10%. + +[produced]: https://github.com/rust-lang/rust/pull/101403#issuecomment-1288190019 + +## Memory allocator + +Using a different memory allocator for `rustc` can provide significant performance benefits. If you +want to enable the `jemalloc` allocator, you can set the `rust.jemalloc` option to `true` +in `config.toml`: + +```toml +[rust] +jemalloc = true +``` + +> Note that this option is currently only supported for Linux and macOS targets. + +## Codegen units + +Reducing the amount of codegen units per `rustc` crate can produce a faster build of the compiler. +You can modify the number of codegen units for `rustc` and `libstd` in `config.toml` with the +following options: + +```toml +[rust] +codegen-units = 1 +codegen-units-std = 1 +``` + +## Instruction set + +By default, `rustc` is compiled for a generic (and conservative) instruction set architecture +(depending on the selected target), to make it support as many CPUs as possible. If you want to +compile `rustc` for a specific instruction set architecture, you can set the `target_cpu` compiler +option in `RUSTFLAGS`: + +```bash +RUSTFLAGS="-C target_cpu=x86-64-v3" ./x build ... +``` + +If you also want to compile LLVM for a specific instruction set, you can set `llvm` flags +in `config.toml`: + +```toml +[llvm] +cxxflags = "-march=x86-64-v3" +cflags = "-march=x86-64-v3" +``` + +## Profile-guided optimization + +Applying profile-guided optimizations (or more generally, feedback-directed optimizations) can +produce a large increase to `rustc` performance, by up to 15% ([1], [2]). However, these techniques +are not simply enabled by a configuration option, but rather they require a complex build workflow +that compiles `rustc` multiple times and profiles it on selected benchmarks. + +There is a tool called `opt-dist` that is used to optimize `rustc` with [PGO] (profile-guided +optimizations) and [BOLT] (a post-link binary optimizer) for builds distributed to end users. You +can examine the tool, which is located in `src/tools/opt-dist`, and build a custom PGO build +workflow based on it, or try to use it directly. Note that the tool is currently quite hardcoded to +the way we use it in Rust's continuous integration workflows, and it might require some custom +changes to make it work in a different environment. + +[1]: https://blog.rust-lang.org/inside-rust/2020/11/11/exploring-pgo-for-the-rust-compiler.html#final-numbers-and-a-benchmarking-plot-twist +[2]: https://github.com/rust-lang/rust/pull/96978 + +[PGO]: https://doc.rust-lang.org/rustc/profile-guided-optimization.html + +[BOLT]: https://github.com/llvm/llvm-project/blob/main/bolt/README.md + +To use the tool, you will need to provide some external dependencies: + +- A Python3 interpreter (for executing `x.py`). +- Compiled LLVM toolchain, with the `llvm-profdata` binary. Optionally, if you want to use BOLT, + the `llvm-bolt` and + `merge-fdata` binaries have to be available in the toolchain. + +These dependencies are provided to `opt-dist` by an implementation of the [`Environment`] struct. +It specifies directories where will the PGO/BOLT pipeline take place, and also external dependencies +like Python or LLVM. + +Here is an example of how can `opt-dist` be used locally (outside of CI): + +1. Build the tool with the following command: + ```bash + ./x build tools/opt-dist + ``` +2. Run the tool with the `local` mode and provide necessary parameters: + ```bash + ./build/host/stage0-tools-bin/opt-dist local \ + --target-triple <target> \ # select target, e.g. "x86_64-unknown-linux-gnu" + --checkout-dir <path> \ # path to rust checkout, e.g. "." + --llvm-dir <path> \ # path to built LLVM toolchain, e.g. "/foo/bar/llvm/install" + -- python3 x.py dist # pass the actual build command + ``` + You can run `--help` to see further parameters that you can modify. + +[`Environment`]: https://github.com/rust-lang/rust/blob/ee451f8faccf3050c76cdcd82543c917b40c7962/src/tools/opt-dist/src/environment.rs#L5 + +> Note: if you want to run the actual CI pipeline, instead of running `opt-dist` locally, +> you can execute `DEPLOY=1 src/ci/docker/run.sh dist-x86_64-linux`. diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 0da3f60cf..cb722696e 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -36,8 +36,6 @@ If you have enough free disk space and you would like to be able to run `x` comm rust-analyzer runs in the background, you can also add `--build-dir build-rust-analyzer` to the `overrideCommand` to avoid x locking. -[`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json - If running `./x check` on save is inconvenient, in VS Code you can use a [Build Task] instead: @@ -74,9 +72,9 @@ Rust-Analyzer to already be configured with Neovim. Steps for this can be `neoconf` is able to read and update Rust-Analyzer settings automatically when the project is opened when this file is detected. -If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a -`.vim/coc-settings.json` and copy the settings from -[this file](https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json). +If you're running `coc.nvim`, +you can use `:CocLocalConfig` to create a `.vim/coc-settings.json`, +and copy the settings from [`src/etc/rust_analyzer_settings.json`]. Another way is without a plugin, and creating your own logic in your configuration. To do this you must translate the JSON to Lua yourself. The translation is 1:1 and fairly straight-forward. It @@ -155,7 +153,7 @@ lets you use `cargo fmt`. Sometimes just checking whether the compiler builds is not enough. A common example is that you need to add a `debug!` statement to inspect the value of some -state or better understand the problem. In that case, you really need +state or better understand the problem. In that case, you don't really need a full build. By bypassing bootstrap's cache invalidation, you can often get these builds to complete very fast (e.g., around 30 seconds). The only catch is this requires a bit of fudging and may produce compilers that @@ -282,6 +280,7 @@ let changelog-seen = 2 [build] + patch-binaries-for-nix = true # The path to (or name of) the GDB executable to use. This is only used for # executing the debuginfo test suite. gdb = "${pkgs.gdb}/bin/gdb" @@ -346,3 +345,5 @@ You can use `source ./src/etc/completions/x.py.<extension>` to load completions for your shell of choice, or `source .\src\etc\completions\x.py.ps1` for PowerShell. Adding this to your shell's startup script (e.g. `.bashrc`) will automatically load this completion. + +[`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json diff --git a/src/doc/rustc-dev-guide/src/const-eval.md b/src/doc/rustc-dev-guide/src/const-eval.md index 6d301823b..736405326 100644 --- a/src/doc/rustc-dev-guide/src/const-eval.md +++ b/src/doc/rustc-dev-guide/src/const-eval.md @@ -40,52 +40,11 @@ in which the constant is evaluated (e.g. the function within which the constant and a [`GlobalId`]. The `GlobalId` is made up of an `Instance` referring to a constant or static or of an `Instance` of a function and an index into the function's `Promoted` table. -Constant evaluation returns an [`EvalToValTreeResult`] for type system constants or -[`EvalToConstValueResult`] with either the error, or a representation of the constant. - -Constants for the type system are encoded in "valtree representation". The `ValTree` datastructure -allows us to represent - -* arrays, -* many structs, -* tuples, -* enums and, -* most primitives. - -The basic rule for -being permitted in the type system is that every value must be uniquely represented. In other -words: a specific value must only be representable in one specific way. For example: there is only -one way to represent an array of two integers as a `ValTree`: -`ValTree::Branch(&[ValTree::Leaf(first_int), ValTree::Leaf(second_int)])`. -Even though theoretically a `[u32; 2]` could be encoded in a `u64` and thus just be a -`ValTree::Leaf(bits_of_two_u32)`, that is not a legal construction of `ValTree` -(and is very complex to do, so it is unlikely anyone is tempted to do so). - -These rules also mean that some values are not representable. There can be no `union`s in type -level constants, as it is not clear how they should be represented, because their active variant -is unknown. Similarly there is no way to represent raw pointers, as addresses are unknown at -compile-time and thus we cannot make any assumptions about them. References on the other hand -*can* be represented, as equality for references is defined as equality on their value, so we -ignore their address and just look at the backing value. We must make sure that the pointer values -of the references are not observable at compile time. We thus encode `&42` exactly like `42`. -Any conversion from -valtree back to codegen constants must reintroduce an actual indirection. At codegen time the -addresses may be deduplicated between multiple uses or not, entirely depending on arbitrary -optimization choices. - -As a consequence, all decoding of `ValTree` must happen by matching on the type first and making -decisions depending on that. The value itself gives no useful information without the type that -belongs to it. - -Other constants get represented as [`ConstValue::Scalar`] or -[`ConstValue::Slice`] if possible. These values are only useful outside the -compile-time interpreter. If you need the value of a constant during -interpretation, you need to directly work with [`const_to_op`]. +Constant evaluation returns an [`EvalToValTreeResult`] for type system constants +or [`EvalToConstValueResult`] with either the error, or a representation of the +evaluated constant: a [valtree](mir/index.md#valtrees) or a [MIR constant +value](mir/index.md#mir-constant-values), respectively. [`GlobalId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/struct.GlobalId.html -[`ConstValue::Scalar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.Scalar -[`ConstValue::Slice`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.Slice -[`ConstValue::ByRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.ByRef [`EvalToConstValueResult`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToConstValueResult.html [`EvalToValTreeResult`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToValTreeResult.html -[`const_to_op`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/struct.InterpCx.html#method.const_to_op diff --git a/src/doc/rustc-dev-guide/src/early-late-bound-summary.md b/src/doc/rustc-dev-guide/src/early-late-bound-summary.md new file mode 100644 index 000000000..223e2251d --- /dev/null +++ b/src/doc/rustc-dev-guide/src/early-late-bound-summary.md @@ -0,0 +1,10 @@ +# Early/Late bound parameters + +This section discusses what it means for generic parameters to be early or late bound. + +```rust +fn foo<'a, T>(b: &'a u32) -> &'a u32 { a } +// ^^ ^early bound +// ^^ +// ^^late bound +```
\ No newline at end of file diff --git a/src/doc/rustc-dev-guide/src/generics.md b/src/doc/rustc-dev-guide/src/generics.md index 7512b3b47..6c61ab87f 100644 --- a/src/doc/rustc-dev-guide/src/generics.md +++ b/src/doc/rustc-dev-guide/src/generics.md @@ -1,4 +1,4 @@ -# Generics and substitutions +# Generics and GenericArgs Given a generic type `MyType<A, B, …>`, we may want to swap out the generics `A, B, …` for some other types (possibly other generics or concrete types). We do this a lot while doing type @@ -6,19 +6,20 @@ inference, type checking, and trait solving. Conceptually, during these routines that one type is equal to another type and want to swap one out for the other and then swap that out for another type and so on until we eventually get some concrete types (or an error). -In rustc this is done using [SubstsRef] (“substs” = “substitutions”). -Conceptually, you can think of `SubstsRef` as a list of types that are to be substituted for the -generic type parameters of the ADT. +In rustc this is done using [GenericArgsRef]. +Conceptually, you can think of `GenericArgsRef` as a list of types that are to be substituted for + the generic type parameters of the ADT. -`SubstsRef` is a type alias of `&'tcx List<GenericArg<'tcx>>` (see [`List` rustdocs][list]). +`GenericArgsRef` is a type alias of `&'tcx List<GenericArg<'tcx>>` (see [`List` rustdocs][list]). [`GenericArg`] is essentially a space-efficient wrapper around [`GenericArgKind`], which is an enum -indicating what kind of generic the type parameter is (type, lifetime, or const). Thus, `SubstsRef` -is conceptually like a `&'tcx [GenericArgKind<'tcx>]` slice (but it is actually a `List`). +indicating what kind of generic the type parameter is (type, lifetime, or const). +Thus, `GenericArgsRef` is conceptually like a `&'tcx [GenericArgKind<'tcx>]` slice (but it is +actually a `List`). [list]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.List.html -[`GenericArg`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/struct.GenericArg.html -[`GenericArgKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/enum.GenericArgKind.html -[SubstsRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/type.SubstsRef.html +[`GenericArg`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.GenericArg.html +[`GenericArgKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.GenericArgKind.html +[GenericArgsRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.GenericArgsRef.html So why do we use this `List` type instead of making it really a slice? It has the length "inline", so `&List` is only 32 bits. As a consequence, it cannot be "subsliced" (that only works if the @@ -36,10 +37,10 @@ struct MyStruct<T> - There would be an `AdtDef` (and corresponding `DefId`) for `MyStruct`. - There would be a `TyKind::Param` (and corresponding `DefId`) for `T` (more later). -- There would be a `SubstsRef` containing the list `[GenericArgKind::Type(Ty(T))]` +- There would be a `GenericArgsRef` containing the list `[GenericArgKind::Type(Ty(T))]` - The `Ty(T)` here is my shorthand for entire other `ty::Ty` that has `TyKind::Param`, which we mentioned in the previous point. -- This is one `TyKind::Adt` containing the `AdtDef` of `MyStruct` with the `SubstsRef` above. +- This is one `TyKind::Adt` containing the `AdtDef` of `MyStruct` with the `GenericArgsRef` above. Finally, we will quickly mention the [`Generics`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html) type. It @@ -113,33 +114,31 @@ This example has a few different substitutions: Let’s look a bit more closely at that last substitution to see why we use indexes. If we want to find the type of `foo.x`, we can get generic type of `x`, which is `Vec<Param(0)>`. Now we can take -the index `0` and use it to find the right type substitution: looking at `Foo`'s `SubstsRef`, we -have the list `[u32, f32]` , since we want to replace index `0`, we take the 0-th index of this +the index `0` and use it to find the right type substitution: looking at `Foo`'s `GenericArgsRef`, +we have the list `[u32, f32]` , since we want to replace index `0`, we take the 0-th index of this list, which is `u32`. Voila! You may have a couple of followup questions… - **`type_of`** How do we get the “generic type of `x`"? You can get the type of pretty much anything + **`type_of`** How do we get the "generic type of `x`"? You can get the type of pretty much anything with the `tcx.type_of(def_id)` query. In this case, we would pass the `DefId` of the field `x`. The `type_of` query always returns the definition with the generics that are in scope of the definition. For example, `tcx.type_of(def_id_of_my_struct)` would return the “self-view” of `MyStruct`: `Adt(Foo, &[Param(0), Param(1)])`. -**`subst`** How do we actually do the substitutions? There is a function for that too! You use -[`subst`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/struct.EarlyBinder.html#method.subst) to -replace a `SubstsRef` with another list of types. +How do we actually do the substitutions? There is a function for that too! You +use [`instantiate`] to replace a `GenericArgsRef` with another list of types. -[Here is an example of actually using `subst` in the compiler][substex]. The exact details are not -too important, but in this piece of code, we happen to be converting from the `rustc_hir::Ty` to -a real `ty::Ty`. You can see that we first get some substitutions (`substs`). Then we call -`type_of` to get a type and call `ty.subst(substs)` to get a new version of `ty` with -the substitutions made. +[Here is an example of actually using `instantiate` in the compiler][instantiatex]. +The exact details are not too important, but in this piece of code, we happen to be +converting from the `rustc_hir::Ty` to a real `ty::Ty`. You can see that we first get some args +(`args`). Then we call `type_of` to get a type and call `ty.instantiate(tcx, args)` to get a new +version of `ty` with the args made. -[substex]: https://github.com/rust-lang/rust/blob/0940040c0486a536be4f8685c7dd9a078f9e87c2/compiler/rustc_hir_analysis/src/astconv/mod.rs#L1231-L1242 +[`instantiate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/generic_args/struct.EarlyBinder.html#method.instantiate +[instantiatex]: https://github.com/rust-lang/rust/blob/8a562f9671e36cf29c9c794c2646bcf252d55535/compiler/rustc_hir_analysis/src/astconv/mod.rs#L905-L927 **Note on indices:** It is possible for the indices in `Param` to not match with what we expect. For example, the index could be out of bounds or it could be the index of a lifetime when we were expecting a type. These sorts of errors would be caught earlier in the compiler when translating from a `rustc_hir::Ty` to a `ty::Ty`. If they occur later, that is a compiler bug. - - diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index 80c3d3793..a12cb068c 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -123,6 +123,10 @@ compiler. You can see a list of diagnostic issues [here][diagnostic-issues]. [diagnostic-issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AA-diagnostics+no%3Aassignee +### Contributing to std (standard library) + +See [std-dev-guide](https://std-dev-guide.rust-lang.org/). + ### Contributing code to other Rust projects There are a bunch of other projects that you can contribute to outside of the diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index 6c5c64685..4208305a9 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -201,6 +201,24 @@ and just want to get a clean copy of the repository back, you can use `git reset git reset --hard master ``` +### failed to push some refs + +`git push` will not work properly and say something like this: + +``` + ! [rejected] issue-xxxxx -> issue-xxxxx (non-fast-forward) +error: failed to push some refs to 'https://github.com/username/rust.git' +hint: Updates were rejected because the tip of your current branch is behind +hint: its remote counterpart. Integrate the remote changes (e.g. +hint: 'git pull ...') before pushing again. +hint: See the 'Note about fast-forwards' in 'git push --help' for details. +``` + +The advice this gives is incorrect! Because of Rust's +["no-merge" policy](#no-merge-policy) the merge commit created by `git pull` +will not be allowed in the final PR, in addition to defeating the point of the +rebase! Use `git push --force-with-lease` instead. + ### Git is trying to rebase commits I didn't write? If you see many commits in your rebase list, or merge commits, or commits by other people that you @@ -306,22 +324,6 @@ Git know that you've resolved the conflicts and it should finish the rebase. Once the rebase has succeeded, you'll want to update the associated branch on your fork with `git push --force-with-lease`. -Note that `git push` will not work properly and say something like this: - -``` - ! [rejected] issue-xxxxx -> issue-xxxxx (non-fast-forward) -error: failed to push some refs to 'https://github.com/username/rust.git' -hint: Updates were rejected because the tip of your current branch is behind -hint: its remote counterpart. Integrate the remote changes (e.g. -hint: 'git pull ...') before pushing again. -hint: See the 'Note about fast-forwards' in 'git push --help' for details. -``` - -The advice this gives is incorrect! Because of Rust's -["no-merge" policy](#no-merge-policy) the merge commit created by `git pull` -will not be allowed in the final PR, in addition to defeating the point of the -rebase! Use `git push --force-with-lease` instead. - ### Keeping things up to date The above section on [Rebasing](#rebasing) is a specific @@ -351,6 +353,8 @@ upstream. ## Advanced Rebasing +### Squash your commits + If your branch contains multiple consecutive rewrites of the same code, or if the rebase conflicts are extremely severe, you can use `git rebase --interactive master` to gain more control over the process. This diff --git a/src/doc/rustc-dev-guide/src/img/coverage-graphviz-01.png b/src/doc/rustc-dev-guide/src/img/coverage-graphviz-01.png Binary files differdeleted file mode 100644 index cf7e1e76b..000000000 --- a/src/doc/rustc-dev-guide/src/img/coverage-graphviz-01.png +++ /dev/null diff --git a/src/doc/rustc-dev-guide/src/img/coverage-spanview-01.png b/src/doc/rustc-dev-guide/src/img/coverage-spanview-01.png Binary files differdeleted file mode 100644 index f3e4b3535..000000000 --- a/src/doc/rustc-dev-guide/src/img/coverage-spanview-01.png +++ /dev/null diff --git a/src/doc/rustc-dev-guide/src/licenses.md b/src/doc/rustc-dev-guide/src/licenses.md index 06cd8ae6b..aa8286714 100644 --- a/src/doc/rustc-dev-guide/src/licenses.md +++ b/src/doc/rustc-dev-guide/src/licenses.md @@ -3,3 +3,45 @@ The `rustc` compiler source and standard library are dual licensed under the [Apache License v2.0](https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE) and the [MIT License](https://github.com/rust-lang/rust/blob/master/LICENSE-MIT) unless otherwise specified. Detailed licensing information is available in the [COPYRIGHT document](https://github.com/rust-lang/rust/blob/master/COPYRIGHT) of the `rust-lang/rust` repository. + +## Guidelines for reviewers + +In general, reviewers need to be looking not only for the code quality of contributions but also +that they are properly licensed. +We have some tips below for things to look out for when reviewing, but if you ever feel uncertain +as to whether some code might be properly licensed, err on the safe side — reach out to the Council +or Compiler Team Leads for feedback! + +Things to watch out for: + +- The PR author states that they copied, ported, or adapted the code from some other source. +- There is a comment in the code pointing to a webpage or describing where the algorithm was taken +from. +- The algorithm or code pattern seems like it was likely copied from somewhere else. +- When adding new dependencies, double check the dependency's license. + +In all of these cases, we will want to check that source to make sure it it is licensed in a way +that is compatible with Rust’s license. + +Examples + +- Porting C code from a GPL project, like GNU binutils, is not allowed. That would require Rust +itself to be licensed under the GPL. +- Copying code from an algorithms text book may be allowed, but some algorithms are patented. + +## Porting + +Contributions to rustc, especially around platform and compiler intrinsics, often include porting +over work from other projects, mainly LLVM and GCC. + +Some general rules apply: + +- Copying work needs to adhere to the original license + - This applies to direct copy & paste + - This also applies to code you looked at and ported + +In general, taking inspiration from other codebases is fine, but please exercise caution when +porting code. + +Ports of full libraries (e.g. C libraries shipped with LLVM) must keep the license of the original +library. diff --git a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md index 2b1677ef4..9379a57f6 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -28,7 +28,7 @@ them), and generate various reports for analysis, for example: <br/> Detailed instructions and examples are documented in the -[Rustc Book][rustc-book-instrument-coverage]. +[rustc book][rustc-book-instrument-coverage]. [llvm-instrprof-increment]: https://llvm.org/docs/LangRef.html#llvm-instrprof-increment-intrinsic [coverage map]: https://llvm.org/docs/CoverageMappingFormat.html @@ -56,14 +56,14 @@ statically links coverage-instrumented binaries with LLVM runtime code ([compiler-rt][compiler-rt-profile]) that implements program hooks (such as an `exit` hook) to write the counter values to the `.profraw` file. -In the `rustc` source tree, `library/profiler_builtins` bundles the LLVM -`compiler-rt` code into a Rust library crate. (When building `rustc`, the -`profiler_builtins` library is only included when `profiler = true` is set -in `rustc`'s `config.toml`.) +In the `rustc` source tree, +`library/profiler_builtins` bundles the LLVM `compiler-rt` code into a Rust library crate. +Note that when building `rustc`, +`profiler_builtins` is only included when `build.profiler = true` is set in `config.toml`. When compiling with `-C instrument-coverage`, -[`CrateLoader::postprocess()`][crate-loader-postprocess] dynamically loads the -`profiler_builtins` library by calling `inject_profiler_runtime()`. +[`CrateLoader::postprocess()`][crate-loader-postprocess] dynamically loads +`profiler_builtins` by calling `inject_profiler_runtime()`. [compiler-rt-profile]: https://github.com/llvm/llvm-project/tree/main/compiler-rt/lib/profile [crate-loader-postprocess]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/creader/struct.CrateLoader.html#method.postprocess @@ -84,10 +84,10 @@ the Rust source code. Note that many of these `Coverage` statements will _not_ be converted into physical counters (or any other executable instructions) in the final binary. -Some of them will be (see `CoverageKind::`[`Counter`][counter-coverage-kind]), +Some of them will be (see [`CoverageKind::Counter`]), but other counters can be computed on the fly, when generating a coverage report, by mapping a `CodeRegion` to a -`CoverageKind`::[`Expression`][expression-coverage-kind]. +[`CoverageKind::Expression`]. As an example: @@ -131,8 +131,8 @@ The `InstrumentCoverage` MIR pass is documented in [mir-passes]: mir/passes.md [mir-instrument-coverage]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_mir_transform/src/coverage [code-region]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/struct.CodeRegion.html -[counter-coverage-kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Counter -[expression-coverage-kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Expression +[`CoverageKind::Counter`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Counter +[`CoverageKind::Expression`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/coverage/enum.CoverageKind.html#variant.Expression [coverage-statement]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.StatementKind.html#variant.Coverage [instrument-coverage-pass-details]: #implementation-details-of-the-instrumentcoverage-mir-pass @@ -223,7 +223,7 @@ details of the [_LLVM Coverage Mapping Format_][coverage-mapping-format] (Version 6).[^llvm-and-covmap-versions] [^llvm-and-covmap-versions]: -The Rust compiler (as of <!-- date-check: --> Feb 2023) supports _LLVM Coverage Mapping Format_ 6. +The Rust compiler (as of <!-- date-check: --> Jul 2023) supports _LLVM Coverage Mapping Format_ 6. The Rust compiler will automatically use the most up-to-date coverage mapping format version that is compatible with the compiler's built-in version of LLVM. @@ -274,31 +274,42 @@ since it will not be called), and adds a new `FunctionCoverage`, with ## Testing LLVM Coverage +[(See also the compiletest documentation for the `tests/coverage-map` and +`tests/run-coverage` test suites.)](./tests/compiletest.md#coverage-tests) + Coverage instrumentation in the MIR is validated by a `mir-opt` test: -[`instrument-coverage`][mir-opt-test]. +[`tests/mir-opt/instrument_coverage.rs`]. + +Coverage instrumentation in LLVM IR is validated by the [`tests/coverage-map`] +test suite. These tests compile a test program to LLVM IR assembly, and then +use the [`src/tools/coverage-dump`] tool to extract and pretty-print the +coverage mappings that would be embedded in the final binary. -More complete testing of end-to-end coverage instrumentation and reports are -done in the `run-make-fulldeps` tests, with sample Rust programs (to be -instrumented) in the [`tests/run-coverage`] directory, -together with the actual tests and expected results. +End-to-end testing of coverage instrumentation and coverage reporting is +performed by the [`tests/run-coverage`] and [`tests/run-coverage-rustdoc`] +test suites. These tests compile and run a test program with coverage +instrumentation, then use LLVM tools to convert the coverage data into a +human-readable coverage report. -Finally, the [`coverage-llvmir`] test compares compiles a simple Rust program +Finally, the [`coverage-llvmir`] test compiles a simple Rust program with `-C instrument-coverage` and compares the compiled program's LLVM IR to expected LLVM IR instructions and structured data for a coverage-enabled program, including various checks for Coverage Map-related metadata and the LLVM intrinsic calls to increment the runtime counters. -Expected results for both the `mir-opt` tests and the `coverage*` tests under -`run-make-fulldeps` can be refreshed by running: +Expected results for the `coverage-map`, `run-coverage`, `run-coverage-rustdoc`, +and `mir-opt` tests can be refreshed by running: ```shell -$ ./x test mir-opt --bless -$ ./x test tests/run-make-fulldeps/coverage --bless +./x test tests/*coverage* --bless +./x test tests/mir-opt --bless ``` -[mir-opt-test]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/instrument_coverage.rs +[`tests/mir-opt/instrument_coverage.rs`]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/instrument_coverage.rs +[`tests/coverage-map`]: https://github.com/rust-lang/rust/tree/master/tests/coverage-map +[`src/tools/coverage-dump`]: https://github.com/rust-lang/rust/tree/master/src/tools/coverage-dump [`tests/run-coverage`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage -[spanview-debugging]: compiler-debugging.md#viewing-spanview-output +[`tests/run-coverage-rustdoc`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage-rustdoc [`coverage-llvmir`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-llvmir ## Implementation Details of the `InstrumentCoverage` MIR Pass @@ -310,7 +321,7 @@ function, generic, or closure), the `Instrumentor`'s constructor prepares a [`inject_counters()`][inject-counters]. ```rust - Instrumentor::new(&self.name(), tcx, mir_body).inject_counters(); +Instrumentor::new(&self.name(), tcx, mir_body).inject_counters(); ``` The `CoverageGraph` is a coverage-specific simplification of the MIR control @@ -324,20 +335,14 @@ The `Instrumentor`'s `inject_counters()` uses the `CoverageGraph` to compute the best places to inject coverage counters, as MIR `Statement`s, with the following steps: -1. Depending on the debugging configurations in `rustc`'s, `config.toml`, - and `rustc` command line flags, various debugging features may be enabled - to enhance `debug!()` messages in logs, and to generate various "dump" files, - to help developers understand the MIR transformation process for coverage. - Most of the debugging features are implemented in the [`debug`][debug] - sub-module. -2. [`generate_coverage_spans()`][generate-coverage-spans] computes the minimum set of distinct, +1. [`generate_coverage_spans()`][generate-coverage-spans] computes the minimum set of distinct, non-branching code regions, from the MIR. These `CoverageSpan`s represent a span of code that must be counted. -3. [`make_bcb_counters()`][make-bcb-counters] generates `CoverageKind::Counter`s and +2. [`make_bcb_counters()`][make-bcb-counters] generates `CoverageKind::Counter`s and `CoverageKind::Expression`s for each `CoverageSpan`, plus additional `intermediate_expressions`[^intermediate-expressions], not associated with any `CodeRegion`, but are required to compute a final `Expression` value for a `CodeRegion`. -4. Inject the new counters into the MIR, as new `StatementKind::Coverage` +3. Inject the new counters into the MIR, as new `StatementKind::Coverage` statements. This is done by three distinct functions: - `inject_coverage_span_counters()` - `inject_indirect_counters()` @@ -409,66 +414,12 @@ The BCB CFG is critical to simplifying the coverage analysis by ensuring graph p queries (`is_dominated_by()`, `predecessors`, `successors`, etc.) have branch (control flow) significance. -To visualize the `CoverageGraph`, you can generate a _graphviz_ `*.dot` -file with the following `rustc` flags:[^graphviz-dark-mode] - -[^graphviz-dark-mode]: This image also applies `-Z graphviz-dark-mode`, to -produce a Graphviz document with "dark mode" styling. If you use a dark mode or -theme in your development environment, you will probably want to use this -option so you can review the graphviz output without straining your vision. - -```shell -$ rustc -C instrument-coverage -Z dump-mir=InstrumentCoverage \ - -Z dump-mir-graphviz some_rust_source.rs -``` - -The `-Z dump-mir` flag requests [MIR debugging -output][mir-debugging] (generating `*.mir` files, by default). -`-Z dump-mir-graphviz` additionally generates `*.dot` files. -`-Z dump-mir=InstrumentCoverage` restricts these files to the -`InstrumentCoverage` pass. All files are written to the `./mir_dump/` -directory, by default. - -Files with names ending in `.-------.InstrumentCoverage.0.dot` contain the -_graphviz_ representations of a `CoverageGraph` (one for each MIR, that is, -for each function and closure): - -<img alt="cropped image of a sample CoverageGraph in graphviz format" - src="img/coverage-graphviz-01.png" style="border: 1px solid gray" class="center"/> -<br/> - -This image shows each `BasicCoverageBlock` as a rectangular _node_, with -directional edges (the arrows) leading from each node to its `successors()`. -The nodes contain information in sections: - -1. The gray header has a label showing the BCB ID (or _index_ for looking up - its `BasicCoverageBlockData`). -2. The first content section shows the assigned `Counter` or `Expression` for - each contiguous section of code. (There may be more than one `Expression` - incremented by the same `Counter` for noncontiguous sections of code - representing the same sequential actions.) Note the code is represented by - the line and column ranges (for example: `52:28-52:33`, representing the - original source line 52, for columns 28-33). These are followed by the MIR - `Statement` or `Terminator` represented by that source range. (How these - coverage regions are determined is discussed in the following section.) -3. The final section(s) show the MIR `BasicBlock`s (by ID/index and its - `TerminatorKind`) contained in this BCB. The last BCB is separated out - because its `successors()` determine the edges leading out of the BCB, and - into the `leading_bb()` (first `BasicBlock`) of each successor BCB. - -Note, to find the `BasicCoverageBlock` from a final BCB `Terminator`'s -successor `BasicBlock`, there is an index and helper -function--[`bcb_from_bb()`][bcb-from-bb]--to look up a `BasicCoverageBlock` from -*any* contained `BasicBlock`. - [directed-graph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/trait.DirectedGraph.html [graph-traits]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/index.html#traits [mir-dev-guide]: mir/index.md [compute-basic-coverage-blocks]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.compute_basic_coverage_blocks [simplify-cfg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/simplify/enum.SimplifyCfg.html [rust-lang/rust#78544]: https://github.com/rust-lang/rust/issues/78544 -[mir-debugging]: mir/debugging.md -[bcb-from-bb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.bcb_from_bb ### `CoverageSpans` @@ -487,32 +438,6 @@ The final stage of `generate_coverage_spans()` is handled by merges and de-duplicates them, and returns an optimal, minimal set of `CoverageSpan`s that can be used to assign coverage `Counter`s or `Expression`s, one-for-one. -An visual, interactive representation of the final `CoverageSpan`s can be -generated with the following `rustc` flags: - -```shell -$ rustc -C instrument-coverage -Z dump-mir=InstrumentCoverage \ - -Z dump-mir-spanview some_rust_source.rs -``` - -These flags request Spanview output for the `InstrumentCoverage` pass, and the -resulting files (one for each MIR, that is, for each function or closure) can be -found in the `mir_dump` directory (by default), with the extension: -`.-------.InstrumentCoverage.0.html`. - -<img alt="cropped image of a sample Spanview in a browser" - src="img/coverage-spanview-01.png" style="border: 1px solid gray" class="center"/> -<br/> - -The image above shows one such example. The orange and blue backgrounds -highlight alternating `CoverageSpan`s from the refined set. Hovering over a -line expands the output on that line to show the MIR `BasicBlock` IDs covered -by each `CoverageSpan`. While hovering, the `CoverageSpan` under the pointer -also has a _tooltip_ block of text, showing even more detail, including the -MIR `Statement`s and `Terminator`s contributing to the `CoverageSpan`, and -their individual `Span`s (which should be encapsulated within the code region -of the refined `CoverageSpan`) - [coverage-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html [coverage-span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpan.html [to-refined-spans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/spans/struct.CoverageSpans.html#method.to_refined_spans @@ -611,12 +536,3 @@ so the counter is only incremented when traversing the branch edge. [inject-coverage-span-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_coverage_span_counters [inject-indirect-counters]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/struct.Instrumentor.html#method.inject_indirect_counters [inject-intermediate-expression]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/fn.inject_intermediate_expression.html - -### Additional Debugging Support - -See the -[crate documentation for `rustc_mir::transform::coverage::debug`][coverage-debugging] -for a detailed description of the debug output, logging, and configuration options -available to developers working on the `InstrumentCoverage` pass. - -[coverage-debugging]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/debug/index.html diff --git a/src/doc/rustc-dev-guide/src/memory.md b/src/doc/rustc-dev-guide/src/memory.md index e5122deb2..4072d4f33 100644 --- a/src/doc/rustc-dev-guide/src/memory.md +++ b/src/doc/rustc-dev-guide/src/memory.md @@ -40,16 +40,16 @@ to that buffer is freed and our `'tcx` references would be invalid. In addition to types, there are a number of other arena-allocated data structures that you can allocate, and which are found in this module. Here are a few examples: -- [`Substs`][subst], allocated with `mk_substs` – this will intern a slice of types, often used to - specify the values to be substituted for generics (e.g. `HashMap<i32, u32>` would be represented - as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`). +- [`GenericArgs`], allocated with `mk_args` – this will intern a slice of types, often used +to specify the values to be substituted for generics args (e.g. `HashMap<i32, u32>` would be +represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`). - [`TraitRef`], typically passed by value – a **trait reference** consists of a reference to a trait along with its various type parameters (including `Self`), like `i32: Display` (here, the def-id - would reference the `Display` trait, and the substs would contain `i32`). Note that `def-id` is + would reference the `Display` trait, and the args would contain `i32`). Note that `def-id` is defined and discussed in depth in the `AdtDef and DefId` section. - [`Predicate`] defines something the trait system has to prove (see `traits` module). -[subst]: ./generic_arguments.html#subst +[`GenericArgs`]: ./generic_arguments.html#GenericArgs [`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TraitRef.html [`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html diff --git a/src/doc/rustc-dev-guide/src/mir/index.md b/src/doc/rustc-dev-guide/src/mir/index.md index dc0be167b..36733c598 100644 --- a/src/doc/rustc-dev-guide/src/mir/index.md +++ b/src/doc/rustc-dev-guide/src/mir/index.md @@ -62,6 +62,12 @@ show you the MIR for your program. Try putting this program into play button on the top: [sample-play]: https://play.rust-lang.org/?gist=30074856e62e74e91f06abd19bd72ece&version=stable +MIR shown by above link is optimized. +Some statements like `StorageLive` are removed in optimization. +This happens because the compiler notices the value is never accessed in the code. +We can use `rustc [filename].rs -Z mir-opt-level=0 --emit mir` to view unoptimized MIR. +This requires the nightly toolchain. + ```rust fn main() { @@ -249,7 +255,75 @@ but [you can read about those below](#promoted)). ## Representing constants -*to be written* +When code has reached the MIR stage, constants can generally come in two forms: +*MIR constants* ([`mir::Constant`]) and *type system constants* ([`ty::Const`]). +MIR constants are used as operands: in `x + CONST`, `CONST` is a MIR constant; +similarly, in `x + 2`, `2` is a MIR constant. Type system constants are used in +the type system, in particular for array lengths but also for const generics. + +Generally, both kinds of constants can be "unevaluated" or "already evaluated". +And unevaluated constant simply stores the `DefId` of what needs to be evaluated +to compute this result. An evaluated constant (a "value") has already been +computed; their representation differs between type system constants and MIR +constants: MIR constants evaluate to a `mir::ConstValue`; type system constants +evaluate to a `ty::ValTree`. + +Type system constants have some more variants to support const generics: they +can refer to local const generic parameters, and they are subject to inference. +Furthermore, the `mir::Constant::Ty` variant lets us use an arbitrary type +system constant as a MIR constant; this happens whenever a const generic +parameter is used as an operand. + +### MIR constant values + +In general, a MIR constant value (`mir::ConstValue`) was computed by evaluating +some constant the user wrote. This [const evaluation](../const-eval.md) produces +a very low-level representation of the result in terms of individual bytes. We +call this an "indirect" constant (`mir::ConstValue::Indirect`) since the value +is stored in-memory. + +However, storing everything in-memory would be awfully inefficient. Hence there +are some other variants in `mir::ConstValue` that can represent certain simple +and common values more efficiently. In particular, everything that can be +directly written as a literal in Rust (integers, floats, chars, bools, but also +`"string literals"` and `b"byte string literals"`) has an optimized variant that +avoids the full overhead of the in-memory representation. + +### ValTrees + +An evaluated type system constant is a "valtree". The `ty::ValTree` datastructure +allows us to represent + +* arrays, +* many structs, +* tuples, +* enums and, +* most primitives. + +The most important rule for +this representation is that every value must be uniquely represented. In other +words: a specific value must only be representable in one specific way. For example: there is only +one way to represent an array of two integers as a `ValTree`: +`ValTree::Branch(&[ValTree::Leaf(first_int), ValTree::Leaf(second_int)])`. +Even though theoretically a `[u32; 2]` could be encoded in a `u64` and thus just be a +`ValTree::Leaf(bits_of_two_u32)`, that is not a legal construction of `ValTree` +(and is very complex to do, so it is unlikely anyone is tempted to do so). + +These rules also mean that some values are not representable. There can be no `union`s in type +level constants, as it is not clear how they should be represented, because their active variant +is unknown. Similarly there is no way to represent raw pointers, as addresses are unknown at +compile-time and thus we cannot make any assumptions about them. References on the other hand +*can* be represented, as equality for references is defined as equality on their value, so we +ignore their address and just look at the backing value. We must make sure that the pointer values +of the references are not observable at compile time. We thus encode `&42` exactly like `42`. +Any conversion from +valtree back a to MIR constant value must reintroduce an actual indirection. At codegen time the +addresses may be deduplicated between multiple uses or not, entirely depending on arbitrary +optimization choices. + +As a consequence, all decoding of `ValTree` must happen by matching on the type first and making +decisions depending on that. The value itself gives no useful information without the type that +belongs to it. <a name="promoted"></a> @@ -277,3 +351,5 @@ See the const-eval WG's [docs on promotion](https://github.com/rust-lang/const-e [`ProjectionElem::Deref`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.ProjectionElem.html#variant.Deref [`Rvalue`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.Rvalue.html [`Operand`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.Operand.html +[`mir::Constant`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Constant.html +[`ty::Const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Const.html diff --git a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md index 2ad9494e8..03c7fb6b7 100644 --- a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md +++ b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md @@ -34,7 +34,7 @@ We record `lifetime_mapping`s for the opaque type, described below. lifetimes into new lifetime parameters local to the opaque. The main reason we do this is because RPITs need to be able to "reify"[^1] any captured late-bound arguments, or make them into early-bound ones. This -is so they can be used as substs for the opaque, and later to +is so they can be used as generic args for the opaque, and later to instantiate hidden types. Since we don't know which lifetimes are early- or late-bound during AST lowering, we just do this for all lifetimes. @@ -355,7 +355,7 @@ error[E0308]: mismatched types #### Well-formedness checking -We check well-formedness of RPITITs just like regular associated types. +We check well-formedness of RPITITs just like regular associated types. Since we added lifetime bounds in `predicates_of` that link the duplicated early-bound lifetimes to their original lifetimes, and we diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index e78c4bb25..c35f01549 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -26,7 +26,7 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> | rbv::ResolvedArg::Free(_, node_id), ) = def { - if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() { + if let Some(lt) = cx.args.get(&node_id).and_then(|p| p.as_lt()).cloned() { return lt; } } @@ -109,7 +109,7 @@ Here is the list of passes as of <!-- date-check --> March 2023: `Go to https://example.com/.` It suggests wrapping the link with angle brackets: `Go to <https://example.com/>.` to linkify it. This is the code behind the <!-- date-check: may 2022 --> `rustdoc::bare_urls` lint. - + - `check_code_block_syntax` validates syntax inside Rust code blocks (<code>```rust</code>) diff --git a/src/doc/rustc-dev-guide/src/serialization.md b/src/doc/rustc-dev-guide/src/serialization.md index 78b065311..c79628106 100644 --- a/src/doc/rustc-dev-guide/src/serialization.md +++ b/src/doc/rustc-dev-guide/src/serialization.md @@ -108,7 +108,7 @@ and `Encodable`. - `MetadataEncodable` and `MetadataDecodable` generate implementations that only allow decoding by [`rustc_metadata::rmeta::encoder::EncodeContext`] and [`rustc_metadata::rmeta::decoder::DecodeContext`]. These are used for types - that contain `rustc_metadata::rmeta::Lazy`. + that contain `rustc_metadata::rmeta::Lazy*`. - `TyEncodable` and `TyDecodable` generate implementation that apply to any `TyEncoder` or `TyDecoder`. These should be used for types that are only serialized in crate metadata and/or the incremental cache, which is most @@ -130,7 +130,7 @@ some deserialization needs to be deferred from the initial loading of metadata. The [`LazyValue<T>`] type wraps the (relative) offset in the crate metadata where a `T` has been serialized. There are also some variants, [`LazyArray<T>`] and [`LazyTable<I, T>`]. -The `Lazy<[T]>` and `LazyTable<I, T>` types provide some functionality over +The `LazyArray<[T]>` and `LazyTable<I, T>` types provide some functionality over `Lazy<Vec<T>>` and `Lazy<HashMap<I, T>>`: - It's possible to encode a `LazyArray<T>` directly from an iterator, without diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 86ebe3a49..5cacb3013 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -67,6 +67,12 @@ The following test suites are available, with links for more information: - `run-make-fulldeps` — `run-make` tests which require a linkable build of `rustc`, or the rust demangler - [`run-pass-valgrind`](#valgrind-tests) — tests run with Valgrind +- [`coverage-map`](#coverage-tests) - tests for coverage maps produced by + coverage instrumentation +- [`run-coverage`](#coverage-tests) - tests that run an instrumented program + and check its coverage report +- [`run-coverage-rustdoc`](#coverage-tests) - coverage tests that also run + instrumented doctests - [Rustdoc tests](../rustdoc.md#tests): - `rustdoc` — tests for rustdoc, making sure that the generated files contain the expected documentation. @@ -394,6 +400,55 @@ These may be removed in the future. [`tests/run-pass-valgrind`]: https://github.com/rust-lang/rust/tree/master/tests/run-pass-valgrind +### Coverage tests + +The tests in [`tests/coverage-map`] test the mappings between source code +regions and coverage counters that are emitted by LLVM. +They compile the test with `--emit=llvm-ir`, +then use a custom tool ([`src/tools/coverage-dump`]) +to extract and pretty-print the coverage mappings embedded in the IR. +These tests don't require the profiler runtime, so they run in PR CI jobs and +are easy to run/bless locally. + +These coverage map tests can be sensitive to changes in MIR lowering or MIR +optimizations, producing mappings that are different but produce identical +coverage reports. + +As a rule of thumb, any PR that doesn't change coverage-specific +code should **feel free to re-bless** the `coverage-map` tests as necessary, +without worrying about the actual changes, as long as the `run-coverage` tests +still pass. + +--- + +The tests in [`tests/run-coverage`] perform an end-to-end test of coverage reporting. +They compile a test program with coverage instrumentation, run that program to +produce raw coverage data, and then use LLVM tools to process that data into a +human-readable code coverage report. + +Instrumented binaries need to be linked against the LLVM profiler runtime, +so `run-coverage` tests are **automatically skipped** +unless the profiler runtime is enabled in `config.toml`: + +```toml +# config.toml +[build] +profiler = true +``` + +This also means that they typically don't run in PR CI jobs, +though they do run as part of the full set of CI jobs used for merging. + +The tests in [`tests/run-coverage-rustdoc`] also run instrumented doctests and +include them in the coverage report. This avoids having to build rustdoc when +only running the main `run-coverage` suite. + +[`tests/coverage-map`]: https://github.com/rust-lang/rust/tree/master/tests/coverage-map +[`src/tools/coverage-dump`]: https://github.com/rust-lang/rust/tree/master/src/tools/coverage-dump +[`tests/run-coverage`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage +[`tests/run-coverage-rustdoc`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage-rustdoc + + ## Building auxiliary crates It is common that some tests require additional auxiliary crates to be compiled. @@ -467,9 +522,6 @@ fn main() { ## Revisions -Certain classes of tests support "revisions" (as of <!-- date-check --> July 2022, -this includes UI, assembly, codegen, debuginfo, incremental, and rustdoc UI tests, -though incremental tests are somewhat different). Revisions allow a single test file to be used for multiple tests. This is done by adding a special header at the top of the file: @@ -503,6 +555,15 @@ currently only apply to the test as a whole, not to particular revisions. The only headers that are intended to really work when customized to a revision are error patterns and compiler flags. +<!-- date-check jul 2023 --> +Following is classes of tests that support revisions: +- UI +- assembly +- codegen +- debuginfo +- rustdoc UI tests +- incremental (these are special in that they inherently cannot be run in parallel) + ## Compare modes Compiletest can be run in different modes, called _compare modes_, which can diff --git a/src/doc/rustc-dev-guide/src/turbofishing-and-early-late-bound.md b/src/doc/rustc-dev-guide/src/turbofishing-and-early-late-bound.md new file mode 100644 index 000000000..a1d8a64e8 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/turbofishing-and-early-late-bound.md @@ -0,0 +1,120 @@ +# Turbofishing's interactions with early/late bound parameters + +The early/late bound parameter distinction on functions introduces some complications +when providing generic arguments to functions. This document discusses what those are +and how they might interact with future changes to make more things late bound. + +## Can't turbofish generic arguments on functions sometimes + +When a function has any late bound lifetime parameters (be they explicitly defined or +implicitly introduced via lifetime elision) we disallow specifying any lifetime arguments +on the function. Sometimes this is a hard error other times it is a future compat lint +([`late_bound_lifetime_arguments`](https://github.com/rust-lang/rust/issues/42868)). + +```rust +fn early<'a: 'a>(a: &'a ()) -> &'a () { a } +fn late<'a>(a: &'a ()) -> &'a () { a } + +fn mixed<'a, 'b: 'b>(a: &'a (), b: &'b ()) -> &'a () { a } + +struct Foo; +impl Foo { + fn late<'a>(self, a: &'a ()) -> &'a () { a } +} + +fn main() { + // fine + let f = early::<'static>; + + // some variation of hard errors and future compat lints + Foo.late::<'static>(&()); + let f = late::<'static>; + let f = mixed::<'static, 'static>; + let f = mixed::<'static>; + late::<'static>(&()); +} +``` + +The justification for this is that late bound parameters are not present on the +`FnDef` so the arguments to late bound parameters can't be present in the substs +for the type. i.e. the `late` function in the above code snippet would not have +any generic parameters on the `FnDef` zst: +```rust +// example desugaring of the `late` function and its zst + builtin Fn impl +struct LateFnDef; +impl<'a> Fn<(&'a ())> for LateFnDef { + type Output = &'a (); + ... +} +``` + +The cause for some situations giving future compat lints and others giving hard errors +is a little arbitrary but explainable: +- It's always a hard error for method calls +- It's only a hard error on paths to free functions if there is no unambiguous way to +create the substs for the fndef from the lifetime arguments. (i.e. the amount of +lifetimes provided must be exactly equal to the amount of early bound lifetimes or +else it's a hard error) + +## Back compat issues from turning early bound to late bound + +Because of the previously mentioned restriction on turbofishing generic arguments, it +is a breaking change to upgrade a lifetime from early bound to late bound as it can cause +existing turbofishies to become hard errors/future compat lints. + +Many t-types members have expressed interest in wanting more parameters to be late bound. +We cannot do so if making something late bound is going to break code that many would +expect to work (judging by the future compat lint issue many people do expect to be able +to turbofish late bound parameters). + +## Interactions with late bound type/const parameters + +If we were to make some type/const parameters late bound we would definitely not want +to disallow turbofishing them as it presumably(?) would break a Tonne of code. + +While lifetimes do differ from type/consts in some ways I(BoxyUwU) do not believe there +is any justification for why it would make sense to allow turbofishing late bound +type/const parameters but not late bound lifetimes. + +## Removing the hard error/fcw + +From reasons above it seems reasonable that we may want to remove the hard error and fcw +(removing the errors/fcw is definitely a blocker for making more things late bound). + +example behaviour: +```rust +fn late<'a>(a: &'a ()) -> &'a () { a } + +fn accepts_fn(_: impl for<'a> Fn(&'a ()) -> &'a ()) {} +fn accepts_fn_2(_: impl Fn(&'static ()) -> &'static ()) {} + +fn main() { + let f = late::<'static>; + + accepts_fn(f); //~ error: `f` doesnt implement `for<'a> Fn(&'a ()) -> &'a ()` + accepts_fn_2(f) // works + + accepts_fn(late) // works +} +```` + +one potential complication is that we would want a way to specify a generic argument +to a function without having to specify arguments for all previous parameters. i.e. +ideally you could write the following code somehow. +```rust +fn late<'a, 'b>(_: &'a (), _: &'b ()) {} + +fn accepts_fn(_: impl for<'a> Fn(&'a (), &'static ())) {} + +fn main() { + // a naive implementation would have a `ReInfer` as the subst for `'a` parameter + // no longer allowing the FnDef to satisfy the `for<'a> Fn(&'a ()` bound + let f = late::<'_, 'static>; + accepts_fn(f); +} +``` +Maybe we can just special case astconv for `_`/`'_` arguments for late bound parameters somehow +and have it not mean the same thing as `_` for early bound parameters. Regardless I think we +would need a solution that would allow writing the above code even if it was done by some new +syntax such as havign to write `late::<k#no_argument, 'static>` (naturally `k#no_argument` +would only make sense as an argument to late bound parameters). diff --git a/src/doc/rustc-dev-guide/src/ty.md b/src/doc/rustc-dev-guide/src/ty.md index 4a6cdb7c7..b7a2ba8e4 100644 --- a/src/doc/rustc-dev-guide/src/ty.md +++ b/src/doc/rustc-dev-guide/src/ty.md @@ -74,9 +74,9 @@ HIR is built, some basic type inference and type checking is done. During the ty figure out what the `ty::Ty` of everything is and we also check if the type of something is ambiguous. The `ty::Ty` is then used for type checking while making sure everything has the expected type. The [`astconv` module][astconv] is where the code responsible for converting a -`rustc_hir::Ty` into a `ty::Ty` is located. This occurs during the type-checking phase, -but also in other parts of the compiler that want to ask questions like "what argument types does -this function expect?" +`rustc_hir::Ty` into a `ty::Ty` is located. The main routine used is `ast_ty_to_ty`. This occurs +during the type-checking phase, but also in other parts of the compiler that want to ask +questions like "what argument types does this function expect?" [astconv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/astconv/index.html @@ -137,11 +137,13 @@ benefits of interning. ## Allocating and working with types -To allocate a new type, you can use the various `mk_` methods defined on the `tcx`. These have names +To allocate a new type, you can use the various `new_*` methods defined on +[`Ty`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html). +These have names that correspond mostly to the various kinds of types. For example: ```rust,ignore -let array_ty = tcx.mk_array(elem_ty, len * 2); +let array_ty = Ty::new_array_with_const_len(tcx, ty, count); ``` These methods all return a `Ty<'tcx>` – note that the lifetime you get back is the lifetime of the @@ -198,11 +200,11 @@ the function calls if one is available in some place (like during type checking) If no inference context is available at all, then one can be created as described in [type-inference]. But this is only useful when the involved types (for example, if they came from a query like `tcx.type_of()`) are actually substituted with fresh -inference variables using [`fresh_substs_for_item`]. This can be used to answer questions +inference variables using [`fresh_args_for_item`]. This can be used to answer questions like "can `Vec<T>` for any `T` be unified with `Vec<u32>`?". [type-inference]: ./type-inference.md#creating-an-inference-context -[`fresh_substs_for_item`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.fresh_substs_for_item +[`fresh_args_for_item`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.fresh_substs_for_item ## `ty::TyKind` Variants @@ -285,7 +287,7 @@ struct MyStruct<T> { x: u32, y: T } The type `MyStruct<u32>` would be an instance of `TyKind::Adt`: ```rust,ignore -Adt(&'tcx AdtDef, SubstsRef<'tcx>) +Adt(&'tcx AdtDef, GenericArgsRef<'tcx>) // ------------ --------------- // (1) (2) // @@ -299,12 +301,12 @@ There are two parts: parameters. In our example, this is the `MyStruct` part *without* the argument `u32`. (Note that in the HIR, structs, enums and unions are represented differently, but in `ty::Ty`, they are all represented using `TyKind::Adt`.) -- The [`SubstsRef`][substsref] is an interned list of values that are to be substituted for the - generic parameters. In our example of `MyStruct<u32>`, we would end up with a list like `[u32]`. - We’ll dig more into generics and substitutions in a little bit. +- The [`GenericArgsRef`][GenericArgsRef] is an interned list of values that are to be substituted +for the generic parameters. In our example of `MyStruct<u32>`, we would end up with a list like +`[u32]`. We’ll dig more into generics and substitutions in a little bit. [adtdef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.AdtDef.html -[substsref]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/type.SubstsRef.html +[GenericArgsRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/type.GenericArgsRef.html **`AdtDef` and `DefId`** @@ -361,13 +363,13 @@ delaying a redundant span bug. ## Question: Why not substitute “inside” the `AdtDef`? -Recall that we represent a generic struct with `(AdtDef, substs)`. So why bother with this scheme? +Recall that we represent a generic struct with `(AdtDef, args)`. So why bother with this scheme? Well, the alternate way we could have chosen to represent types would be to always create a new, fully-substituted form of the `AdtDef` where all the types are already substituted. This seems like -less of a hassle. However, the `(AdtDef, substs)` scheme has some advantages over this. +less of a hassle. However, the `(AdtDef, args)` scheme has some advantages over this. -First, `(AdtDef, substs)` scheme has an efficiency win: +First, `(AdtDef, args)` scheme has an efficiency win: ```rust,ignore struct MyStruct<T> { diff --git a/src/doc/rustc-dev-guide/src/early-late-bound.md b/src/doc/rustc-dev-guide/src/what-does-early-late-bound-mean.md index 8fb856742..9a6a0b139 100644 --- a/src/doc/rustc-dev-guide/src/early-late-bound.md +++ b/src/doc/rustc-dev-guide/src/what-does-early-late-bound-mean.md @@ -1,8 +1,8 @@ # Early and Late Bound Parameter Definitions Understanding this page likely requires a rudimentary understanding of higher ranked -trait bounds/`for<'a>`and also what types such as `dyn for<'a> Trait<'a>` and -`for<'a> fn(&'a u32)` mean. Reading [the nomincon chapter](https://doc.rust-lang.org/nomicon/hrtb.html) +trait bounds/`for<'a>`and also what types such as `dyn for<'a> Trait<'a>` and + `for<'a> fn(&'a u32)` mean. Reading [the nomincon chapter](https://doc.rust-lang.org/nomicon/hrtb.html) on HRTB may be useful for understanding this syntax. The meaning of `for<'a> fn(&'a u32)` is incredibly similar to the meaning of `T: for<'a> Trait<'a>`. @@ -21,7 +21,7 @@ fn foo<'a>(_: &'a u32) {} fn main() { let b = foo; - // ^ `b` has type `FnDef(foo, [])` (no substs because `'a` is late bound) + // ^ `b` has type `FnDef(foo, [])` (no args because `'a` is late bound) assert!(std::mem::size_of_val(&b) == 0); } ``` @@ -38,7 +38,7 @@ fn main() { } ``` -Because late bound parameters are not part of the `FnDef`'s substs this allows us to prove trait +Because late bound parameters are not part of the `FnDef`'s args this allows us to prove trait bounds such as `F: for<'a> Fn(&'a u32)` where `F` is `foo`'s `FnDef`. e.g. ```rust fn foo_early<'a, T: Trait<'a>>(_: &'a u32, _: T) {} @@ -52,7 +52,7 @@ fn main() { // of the borrow in the function argument must be the same as the lifetime // on the `FnDef`. accepts_hr_func(foo_early); - + // works, the substituted bound is `for<'a> FnDef: Fn(&'a u32, u32)` accepts_hr_func(foo_late); } @@ -85,7 +85,7 @@ making `generics_of` behave this way. ## What parameters are currently late bound Below are the current requirements for determining if a generic parameter is late bound. It is worth -keeping in mind that these are not necessarily set in stone and it is almost certainly possible to +keeping in mind that these are not necessarily set in stone and it is almost certainly possible to be more flexible. ### Must be a lifetime parameter @@ -161,7 +161,7 @@ this is simpler than the rules for checking impl headers constrain all the param We only have to ensure that all late bound parameters appear at least once in the function argument types outside of an alias (e.g. an associated type). -The requirement that they not indirectly be in the substs of an alias for it to count is the +The requirement that they not indirectly be in the args of an alias for it to count is the same as why the follow code is forbidden: ```rust impl<T: Trait> OtherTrait for <T as Trait>::Assoc { type Assoc = T } @@ -174,13 +174,13 @@ same is true of the builtin `Fn*` impls. It is generally considered desirable for more parameters to be late bound as it makes the builtin `Fn*` impls more flexible. Right now many of the requirements for making -a parameter late bound are overly restrictive as they are tied to what we can currently +a parameter late bound are overly restrictive as they are tied to what we can currently (or can ever) do with fn ptrs. -It would be theoretically possible to support late bound params in `where`-clauses in the -language by introducing implication types which would allow us to express types such as: +It would be theoretically possible to support late bound params in `where`-clauses in the +language by introducing implication types which would allow us to express types such as: `for<'a, 'b: 'a> fn(Inv<&'a u32>, Inv<&'b u32>)` which would ensure `'b: 'a` is upheld when -calling the function pointer. +calling the function pointer. It would also be theoretically possible to support it by making the coercion to a fn ptr instantiate the parameter with an infer var while still allowing the FnDef to not have the diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 94605e2a2..5c6633864 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -28,6 +28,7 @@ - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) - [\*-android and \*-androideabi](platform-support/android.md) - [\*-linux-ohos](platform-support/openharmony.md) + - [\*-hurd-gnu](platform-support/hurd.md) - [aarch64-unknown-teeos](platform-support/aarch64-unknown-teeos.md) - [\*-esp-espidf](platform-support/esp-idf.md) - [\*-unknown-fuchsia](platform-support/fuchsia.md) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index f882a31de..d72543c7e 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -263,7 +263,7 @@ flavor. Valid options are: * `lld-link`: use the LLVM `lld` executable with the [`-flavor link` flag][lld-flavor] for Microsoft's `link.exe`. -[lld-flavor]: https://lld.llvm.org/Driver.html +[lld-flavor]: https://releases.llvm.org/12.0.0/tools/lld/docs/Driver.html ## linker-plugin-lto diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 2c7c05c0c..4d32897cc 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -260,6 +260,10 @@ The valid types of print values are: This returns rustc's minimum supported deployment target if no `*_DEPLOYMENT_TARGET` variable is present in the environment, or otherwise returns the variable's parsed value. +A filepath may optionally be specified for each requested information kind, in +the format `--print KIND=PATH`, just like for `--emit`. When a path is +specified, information will be written there instead of to stdout. + [conditional compilation]: ../reference/conditional-compilation.html [deployment target]: https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md index 2535cd4f1..5b7663183 100644 --- a/src/doc/rustc/src/instrument-coverage.md +++ b/src/doc/rustc/src/instrument-coverage.md @@ -173,9 +173,9 @@ Some of the more notable options in this example include: [`llvm-cov report`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report [`llvm-cov show`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-show -> **Note**: Coverage can also be disabled on an individual function by annotating the function with the [`no_coverage` attribute] (which requires the feature flag `#![feature(no_coverage)]`). +> **Note**: Coverage can also be disabled on an individual function by annotating the function with the [`coverage(off)` attribute] (which requires the feature flag `#![feature(coverage)]`). -[`no_coverage` attribute]: ../unstable-book/language-features/no-coverage.html +[`coverage` attribute]: ../unstable-book/language-features/coverage.html ## Interpreting reports diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 68b70a4f3..ff831a205 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -36,7 +36,7 @@ target | notes `i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support] `i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support] `i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) -`x86_64-apple-darwin` | 64-bit macOS (10.7+, Lion+) +`x86_64-apple-darwin` | 64-bit macOS (10.12+, Sierra+) `x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 7+) [^windows-support] `x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 7+) [^windows-support] `x86_64-unknown-linux-gnu` | 64-bit Linux (kernel 3.2+, glibc 2.17+) @@ -63,8 +63,9 @@ Tools](#tier-1-with-host-tools). ## Tier 2 with Host Tools Tier 2 targets can be thought of as "guaranteed to build". The Rust project -builds official binary releases for each tier 2 target, and automated builds -ensure that each tier 2 target builds after each change. Automated tests are +builds official binary releases of the standard library (or, in some cases, +only the `core` library) for each tier 2 target, and automated builds +ensure that each tier 2 target can be used as build target after each change. Automated tests are not always run so it's not guaranteed to produce a working build, but tier 2 targets often work to quite a good degree and patches are always welcome! @@ -103,11 +104,12 @@ target | notes `x86_64-unknown-linux-musl` | 64-bit Linux with MUSL [`x86_64-unknown-netbsd`](platform-support/netbsd.md) | NetBSD/amd64 -## Tier 2 +## Tier 2 without Host Tools Tier 2 targets can be thought of as "guaranteed to build". The Rust project -builds official binary releases for each tier 2 target, and automated builds -ensure that each tier 2 target builds after each change. Automated tests are +builds official binary releases of the standard library (or, in some cases, +only the `core` library) for each tier 2 target, and automated builds +ensure that each tier 2 target can be used as build target after each change. Automated tests are not always run so it's not guaranteed to produce a working build, but tier 2 targets often work to quite a good degree and patches are always welcome! For the full requirements, see [Tier 2 target @@ -155,6 +157,8 @@ target | std | notes `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD `i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL [`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI +[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64D ABI) +[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64S ABI) `mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL `mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL `mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL @@ -176,11 +180,10 @@ target | std | notes `thumbv8m.base-none-eabi` | * | Bare ARMv8-M Baseline `thumbv8m.main-none-eabi` | * | Bare ARMv8-M Mainline `thumbv8m.main-none-eabihf` | * | Bare ARMv8-M Mainline, hardfloat -[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | Bare 32-bit SPARC V7+ `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI -[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads +[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | | WebAssembly with WASI Preview 1 and threads `x86_64-apple-ios` | ✓ | 64-bit x86 iOS [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX `x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia` @@ -244,7 +247,6 @@ target | std | host | notes `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD [`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv6 NetBSD w/hard-float [`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain) -`armv7-apple-ios` | ✓ | | ARMv7-A Cortex-A8 iOS [`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ? | | ARMv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) [`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | ARMv7-A OpenHarmony | [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7-A Linux with uClibc, softfloat @@ -264,16 +266,16 @@ target | std | host | notes `hexagon-unknown-linux-musl` | ? | | `i386-apple-ios` | ✓ | | 32-bit x86 iOS [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS | -`i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+) +`i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+) `i686-pc-windows-msvc` | * | | 32-bit Windows XP support +[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku +[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd [`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 with SSE2 [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD `i686-uwp-windows-gnu` | ? | | `i686-uwp-windows-msvc` | ? | | `i686-wrs-vxworks` | ? | | -[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64D ABI) -[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64S ABI) [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux `mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc [`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux MUSL @@ -315,6 +317,7 @@ target | std | host | notes [`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android `s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux +[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+ [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64 [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64 `thumbv4t-none-eabi` | * | | Thumb-mode Bare ARMv4T diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md index 8bc938134..f8cd92f92 100644 --- a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md +++ b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md @@ -8,6 +8,7 @@ TEEOS is a mini os run in TrustZone, for trusted/security apps. The kernel of TE It's very small that there is no RwLock, no network, no stdin, and no file system for apps in TEEOS. Some abbreviation: + | Abbreviation | The full text | Description | | ---- | ---- | ---- | | TEE | Trusted Execution Environment | ARM TrustZone divides the system into two worlds/modes -- the secure world/mode and the normal world/mode. TEE is in the secure world/mode. | diff --git a/src/doc/rustc/src/platform-support/hurd.md b/src/doc/rustc/src/platform-support/hurd.md new file mode 100644 index 000000000..ddf40213e --- /dev/null +++ b/src/doc/rustc/src/platform-support/hurd.md @@ -0,0 +1,35 @@ +# `i686-unknown-hurd-gnu` + +**Tier: 3** + +[GNU/Hurd] is the GNU Hurd is the GNU project's replacement for the Unix kernel. + +## Target maintainers + +- Samuel Thibault, `samuel.thibault@ens-lyon.org`, https://github.com/sthibaul/ + +## Requirements + +The target supports host tools. + +The GNU/Hurd target supports `std` and uses the standard ELF file format. + +## Building the target + +This target can be built by adding `i686-unknown-hurd-gnu` as target in the rustc list. + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +## Testing + +Tests can be run in the same way as a regular binary. + +## Cross-compilation toolchains and C code + +The target supports C code, the GNU toolchain calls the target +`i686-unknown-gnu`. diff --git a/src/doc/rustc/src/platform-support/loongarch-none.md b/src/doc/rustc/src/platform-support/loongarch-none.md index d0ae3425f..68d7c9d85 100644 --- a/src/doc/rustc/src/platform-support/loongarch-none.md +++ b/src/doc/rustc/src/platform-support/loongarch-none.md @@ -1,6 +1,6 @@ # `loongarch*-unknown-none*` -**Tier: 3** +**Tier: 2** Freestanding/bare-metal LoongArch64 binaries in ELF format: firmware, kernels, etc. diff --git a/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md b/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md index fb0cea05d..a6246fa3b 100644 --- a/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md +++ b/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md @@ -6,6 +6,7 @@ Windows targets similar to `*-pc-windows-gnu` but using UCRT as the runtime and Target triples available so far: - `aarch64-pc-windows-gnullvm` +- `i686-pc-windows-gnullvm` - `x86_64-pc-windows-gnullvm` ## Target maintainers @@ -42,7 +43,7 @@ Once these targets bootstrap themselves on native hardware they should pass Rust ## Cross-compilation toolchains and C code -Compatible C code can be built with Clang's `aarch64-pc-windows-gnu` and `x86_64-pc-windows-gnu` targets as long as LLVM based C toolchains are used. +Compatible C code can be built with Clang's `aarch64-pc-windows-gnu`, `i686-pc-windows-gnullvm` and `x86_64-pc-windows-gnu` targets as long as LLVM based C toolchains are used. Those include: - [llvm-mingw](https://github.com/mstorsjo/llvm-mingw) - [MSYS2 with CLANG* environment](https://www.msys2.org/docs/environments) diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md index 03fa28462..68cd7fae3 100644 --- a/src/doc/rustc/src/platform-support/unknown-uefi.md +++ b/src/doc/rustc/src/platform-support/unknown-uefi.md @@ -19,8 +19,8 @@ Available targets: ## Requirements All UEFI targets can be used as `no-std` environments via cross-compilation. -Support for `std` is missing, but actively worked on. `alloc` is supported if -an allocator is provided by the user. No host tools are supported. +Support for `std` is present, but incomplete and extremely new. `alloc` is supported if +an allocator is provided by the user or if using std. No host tools are supported. The UEFI environment resembles the environment for Microsoft Windows, with some minor differences. Therefore, cross-compiling for UEFI works with the same @@ -230,3 +230,76 @@ pub extern "C" fn main(_h: efi::Handle, st: *mut efi::SystemTable) -> efi::Statu efi::Status::SUCCESS } ``` + +## Rust std for UEFI +This section contains information on how to use std on UEFI. + +### Build std +The building std part is pretty much the same as the official [docs](https://rustc-dev-guide.rust-lang.org/getting-started.html). +The linker that should be used is `rust-lld`. Here is a sample `config.toml`: +```toml +[rust] +lld = true +``` +Then just build using `x.py`: +```sh +./x.py build --target x86_64-unknown-uefi --stage 1 +``` +Alternatively, it is possible to use the `build-std` feature. However, you must use a toolchain which has the UEFI std patches. +Then just build the project using the following command: +```sh +cargo build --target x86_64-unknown-uefi -Zbuild-std=std,panic_abort +``` + +### Implemented features +#### alloc +- Implemented using `EFI_BOOT_SERVICES.AllocatePool()` and `EFI_BOOT_SERVICES.FreePool()`. +- Passes all the tests. +- Currently uses `EfiLoaderData` as the `EFI_ALLOCATE_POOL->PoolType`. +#### cmath +- Provided by compiler-builtins. +#### env +- Just some global constants. +#### locks +- The provided locks should work on all standard single-threaded UEFI implementations. +#### os_str +- While the strings in UEFI should be valid UCS-2, in practice, many implementations just do not care and use UTF-16 strings. +- Thus, the current implementation supports full UTF-16 strings. + +## Example: Hello World With std +The following code features a valid UEFI application, including stdio and `alloc` (`OsString` and `Vec`): + +This example can be compiled as binary crate via `cargo` using the toolchain +compiled from the above source (named custom): + +```sh +cargo +custom build --target x86_64-unknown-uefi +``` + +```rust,ignore (platform-specific) +#![feature(uefi_std)] + +use r_efi::{efi, protocols::simple_text_output}; +use std::{ + ffi::OsString, + os::uefi::{env, ffi::OsStrExt} +}; + +pub fn main() { + let st = env::system_table().as_ptr() as *mut efi::SystemTable; + let mut s: Vec<u16> = OsString::from("Hello World!\n").encode_wide().collect(); + s.push(0); + let r = + unsafe { + let con_out: *mut simple_text_output::Protocol = (*st).con_out; + let output_string: extern "efiapi" fn(_: *mut simple_text_output::Protocol, *mut u16) -> efi::Status = (*con_out).output_string; + output_string(con_out, s.as_ptr() as *mut efi::Char16) + }; + assert!(!r.is_error()) +} +``` + +### BootServices +The current implementation of std makes `BootServices` unavailable once `ExitBootServices` is called. Refer to [Runtime Drivers](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/7_driver_entry_point/711_runtime_drivers) for more information regarding how to handle switching from using physical addresses to using virtual addresses. + +Note: It should be noted that it is up to the user to drop all allocated memory before `ExitBootServices` is called. diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index 12a8b2b8d..3b6883c0d 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -4,6 +4,7 @@ - [Command-line arguments](command-line-arguments.md) - [How to read rustdoc output](how-to-read-rustdoc.md) - [In-doc settings](read-documentation/in-doc-settings.md) + - [Search](read-documentation/search.md) - [How to write documentation](how-to-write-documentation.md) - [What to include (and exclude)](write-documentation/what-to-include.md) - [The `#[doc]` attribute](write-documentation/the-doc-attribute.md) diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md index 9deb7009c..dade62c54 100644 --- a/src/doc/rustdoc/src/how-to-read-rustdoc.md +++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md @@ -38,6 +38,22 @@ followed by a list of fields or variants for Rust types. Finally, the page lists associated functions and trait implementations, including automatic and blanket implementations that `rustdoc` knows about. +### Sections + +<!-- FIXME: Implementations --> +<!-- FIXME: Trait Implementations --> +<!-- FIXME: Implementors --> +<!-- FIXME: Auto Trait Implementations --> + +#### Aliased Type + +A type alias is expanded at compile time to its +[aliased type](https://doc.rust-lang.org/reference/items/type-aliases.html). +That may involve substituting some or all of the type parameters in the target +type with types provided by the type alias definition. The Aliased Type section +shows the result of this expansion, including the types of public fields or +variants, which may depend on those substitutions. + ### Navigation Subheadings, variants, fields, and many other things in this documentation @@ -59,56 +75,11 @@ or the current item whose documentation is being displayed. ## The Theme Picker and Search Interface When viewing `rustdoc`'s output in a browser with JavaScript enabled, -a dynamic interface appears at the top of the page composed of the search -interface, help screen, and options. - -### The Search Interface - -Typing in the search bar instantly searches the available documentation for -the string entered with a fuzzy matching algorithm that is tolerant of minor -typos. - -By default, the search results given are "In Names", -meaning that the fuzzy match is made against the names of items. -Matching names are shown on the left, and the first few words of their -descriptions are given on the right. -By clicking an item, you will navigate to its particular documentation. - -There are two other sets of results, shown as tabs in the search results pane. -"In Parameters" shows matches for the string in the types of parameters to -functions, and "In Return Types" shows matches in the return types of functions. -Both are very useful when looking for a function whose name you can't quite -bring to mind when you know the type you have or want. - -Names in the search interface can be prefixed with an item type followed by a -colon (such as `mod:`) to restrict the results to just that kind of item. Also, -searching for `println!` will search for a macro named `println`, just like -searching for `macro:println` does. - -Function signature searches can query generics, wrapped in angle brackets, and -traits are normalized like types in the search engine. For example, a function -with the signature `fn my_function<I: Iterator<Item=u32>>(input: I) -> usize` -can be matched with the following queries: - -* `Iterator<u32> -> usize` -* `trait:Iterator<primitive:u32> -> primitive:usize` -* `Iterator -> usize` - -Generics and function parameters are order-agnostic, but sensitive to nesting -and number of matches. For example, a function with the signature -`fn read_all(&mut self: impl Read) -> Result<Vec<u8>, Error>` -will match these queries: - -* `Read -> Result<Vec<u8>, Error>` -* `Read -> Result<Error, Vec>` -* `Read -> Result<Vec<u8>>` - -But it *does not* match `Result<Vec, u8>` or `Result<u8<Vec>>`. - -Function signature searches also support arrays and slices. The explicit name -`primitive:slice<u8>` and `primitive:array<u8>` can be used to match a slice -or array of bytes, while square brackets `[u8]` will match either one. Empty -square brackets, `[]`, will match any slice regardless of what it contains. +a dynamic interface appears at the top of the page composed of the [search] +interface, help screen, and [options]. + +[options]: read-documentation/in-doc-settings.html +[search]: read-documentation/search.md Paths are supported as well, you can look for `Vec::new` or `Option::Some` or even `module::module_child::another_child::struct::field`. Whitespace characters diff --git a/src/doc/rustdoc/src/how-to-write-documentation.md b/src/doc/rustdoc/src/how-to-write-documentation.md index 1fa9f8144..acab1a936 100644 --- a/src/doc/rustdoc/src/how-to-write-documentation.md +++ b/src/doc/rustdoc/src/how-to-write-documentation.md @@ -254,6 +254,19 @@ characters: So, no need to manually enter those Unicode characters! +### Adding a warning block + +If you want to make a warning or similar note stand out in the documentation, +you can wrap it like this: + +```md +/// documentation +/// +/// <div class="warning">A big warning!</div> +/// +/// more documentation +``` + [`backtrace`]: https://docs.rs/backtrace/0.3.50/backtrace/ [commonmark markdown specification]: https://commonmark.org/ [commonmark quick reference]: https://commonmark.org/help/ diff --git a/src/doc/rustdoc/src/read-documentation/search.md b/src/doc/rustdoc/src/read-documentation/search.md new file mode 100644 index 000000000..56a5016d0 --- /dev/null +++ b/src/doc/rustdoc/src/read-documentation/search.md @@ -0,0 +1,237 @@ +# Rustdoc search + +Typing in the search bar instantly searches the available documentation, +matching either the name and path of an item, or a function's approximate +type signature. + +## Search By Name + +To search by the name of an item (items include modules, types, traits, +functions, and macros), write its name or path. As a special case, the parts +of a path that normally get divided by `::` double colons can instead be +separated by spaces. For example: + + * [`vec new`] and [`vec::new`] both show the function `std::vec::Vec::new` + as a result. + * [`vec`], [`vec vec`], [`std::vec`], and [`std::vec::Vec`] all include the struct + `std::vec::Vec` itself in the results (and all but the last one also + include the module in the results). + +[`vec new`]: ../../std/vec/struct.Vec.html?search=vec%20new&filter-crate=std +[`vec::new`]: ../../std/vec/struct.Vec.html?search=vec::new&filter-crate=std +[`vec`]: ../../std/vec/struct.Vec.html?search=vec&filter-crate=std +[`vec vec`]: ../../std/vec/struct.Vec.html?search=vec%20vec&filter-crate=std +[`std::vec`]: ../../std/vec/struct.Vec.html?search=std::vec&filter-crate=std +[`std::vec::Vec`]: ../../std/vec/struct.Vec.html?search=std::vec::Vec&filter-crate=std +[`std::vec::Vec`]: ../../std/vec/struct.Vec.html?search=std::vec::Vec&filter-crate=std + +As a quick way to trim down the list of results, there's a drop-down selector +below the search input, labeled "Results in \[std\]". Clicking it can change +which crate is being searched. + +Rustdoc uses a fuzzy matching function that can tolerate typos for this, +though it's based on the length of the name that's typed in, so a good example +of how this works would be [`HahsMap`]. To avoid this, wrap the item in quotes, +searching for `"HahsMap"` (in this example, no results will be returned). + +[`HahsMap`]: ../../std/collections/struct.HashMap.html?search=HahsMap&filter-crate=std + +### Tabs in the Search By Name interface + +In fact, using [`HahsMap`] again as the example, it tells you that you're +using "In Names" by default, but also lists two other tabs below the crate +drop-down: "In Parameters" and "In Return Types". + +These two tabs are lists of functions, defined on the closest matching type +to the search (for `HahsMap`, it loudly auto-corrects to `hashmap`). This +auto-correct only kicks in if nothing is found that matches the literal. + +These tabs are not just methods. For example, searching the alloc crate for +[`Layout`] also lists functions that accept layouts even though they're +methods on the allocator or free functions. + +[`Layout`]: ../../alloc/index.html?search=Layout&filter-crate=alloc + +## Searching By Type Signature for functions + +If you know more specifically what the function you want to look at does, +Rustdoc can search by more than one type at once in the parameters and return +value. Multiple parameters are separated by `,` commas, and the return value +is written with after a `->` arrow. + +Before describing the syntax in more detail, here's a few sample searches of +the standard library and functions that are included in the results list: + +| Query | Results | +|-------|--------| +| [`usize -> vec`][] | `slice::repeat` and `Vec::with_capacity` | +| [`vec, vec -> bool`][] | `Vec::eq` | +| [`option<T>, fnonce -> option<U>`][] | `Option::map` and `Option::and_then` | +| [`option<T>, fnonce -> option<T>`][] | `Option::filter` and `Option::inspect` | +| [`option -> default`][] | `Option::unwrap_or_default` | +| [`stdout, [u8]`][stdoutu8] | `Stdout::write` | +| [`any -> !`][] | `panic::panic_any` | +| [`vec::intoiter<T> -> [T]`][iterasslice] | `IntoIter::as_slice` and `IntoIter::next_chunk` | + +[`usize -> vec`]: ../../std/vec/struct.Vec.html?search=usize%20-%3E%20vec&filter-crate=std +[`vec, vec -> bool`]: ../../std/vec/struct.Vec.html?search=vec,%20vec%20-%3E%20bool&filter-crate=std +[`option<T>, fnonce -> option<U>`]: ../../std/vec/struct.Vec.html?search=option<T>%2C%20fnonce%20->%20option<U>&filter-crate=std +[`option<T>, fnonce -> option<T>`]: ../../std/vec/struct.Vec.html?search=option<T>%2C%20fnonce%20->%20option<T>&filter-crate=std +[`option -> default`]: ../../std/vec/struct.Vec.html?search=option%20-%3E%20default&filter-crate=std +[`any -> !`]: ../../std/vec/struct.Vec.html?search=any%20-%3E%20!&filter-crate=std +[stdoutu8]: ../../std/vec/struct.Vec.html?search=stdout%2C%20[u8]&filter-crate=std +[iterasslice]: ../../std/vec/struct.Vec.html?search=vec%3A%3Aintoiter<T>%20->%20[T]&filter-crate=std + +### How type-based search works + +In a complex type-based search, Rustdoc always treats every item's name as literal. +If a name is used and nothing in the docs matches the individual item, such as +a typo-ed [`uize -> vec`][] search, the item `uize` is treated as a generic +type parameter (resulting in `vec::from` and other generic vec constructors). + +[`uize -> vec`]: ../../std/vec/struct.Vec.html?search=uize%20-%3E%20vec&filter-crate=std + +After deciding which items are type parameters and which are actual types, it +then searches by matching up the function parameters (written before the `->`) +and the return types (written after the `->`). Type matching is order-agnostic, +and allows items to be left out of the query, but items that are present in the +query must be present in the function for it to match. + +Function signature searches can query generics, wrapped in angle brackets, and +traits will be normalized like types in the search engine if no type parameters +match them. For example, a function with the signature +`fn my_function<I: Iterator<Item=u32>>(input: I) -> usize` +can be matched with the following queries: + +* `Iterator<u32> -> usize` +* `Iterator -> usize` + +Generics and function parameters are order-agnostic, but sensitive to nesting +and number of matches. For example, a function with the signature +`fn read_all(&mut self: impl Read) -> Result<Vec<u8>, Error>` +will match these queries: + +* `Read -> Result<Vec<u8>, Error>` +* `Read -> Result<Error, Vec>` +* `Read -> Result<Vec<u8>>` + +But it *does not* match `Result<Vec, u8>` or `Result<u8<Vec>>`. + +Function signature searches also support arrays and slices. The explicit name +`primitive:slice<u8>` and `primitive:array<u8>` can be used to match a slice +or array of bytes, while square brackets `[u8]` will match either one. Empty +square brackets, `[]`, will match any slice or array regardless of what +it contains, while a slice with a type parameter, like `[T]`, will only match +functions that actually operate on generic slices. + +### Limitations and quirks of type-based search + +Type-based search is still a buggy, experimental, work-in-progress feature. +Most of these limitations should be addressed in future version of Rustdoc. + + * There's no way to write trait constraints on generic parameters. + You can name traits directly, and if there's a type parameter + with that bound, it'll match, but `option<T> -> T where T: Default` + cannot be precisely searched for (use `option<Default> -> Default`). + + * Type parameters match type parameters, such that `Option<A>` matches + `Option<T>`, but never match concrete types in function signatures. + A trait named as if it were a type, such as `Option<Read>`, will match + a type parameter constrained by that trait, such as + `Option<T> where T: Read`, as well as matching `dyn Trait` and + `impl Trait`. + + * `impl Trait` in argument position is treated exactly like a type + parameter, but in return position it will not match type parameters. + + * Any type named in a complex type-based search will be assumed to be a + type parameter if nothing matching the name exactly is found. If you + want to force a type parameter, write `generic:T` and it will be used + as a type parameter even if a matching name is found. If you know + that you don't want a type parameter, you can force it to match + something else by giving it a different prefix like `struct:T`. + + * It's impossible to search for references, pointers, or tuples. The + wrapped types can be searched for, so a function that takes `&File` can + be found with `File`, but you'll get a parse error when typing an `&` + into the search field. Similarly, `Option<(T, U)>` can be matched with + `Option<T, U>`, but `(` will give a parse error. + + * Searching for lifetimes is not supported. + + * It's impossible to search for closures based on their parameters or + return values. + + * It's impossible to search based on the length of an array. + +## Item filtering + +Names in the search interface can be prefixed with an item type followed by a +colon (such as `mod:`) to restrict the results to just that kind of item. Also, +searching for `println!` will search for a macro named `println`, just like +searching for `macro:println` does. The complete list of available filters is +given under the <kbd>?</kbd> Help area, and in the detailed syntax below. + +Item filters can be used in both name-based and type signature-based searches. + +## Search query syntax + +```text +ident = *(ALPHA / DIGIT / "_") +path = ident *(DOUBLE-COLON ident) [!] +slice = OPEN-SQUARE-BRACKET [ nonempty-arg-list ] CLOSE-SQUARE-BRACKET +arg = [type-filter *WS COLON *WS] (path [generics] / slice / [!]) +type-sep = COMMA/WS *(COMMA/WS) +nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep) +generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list ] *(type-sep) + CLOSE-ANGLE-BRACKET +return-args = RETURN-ARROW *(type-sep) nonempty-arg-list + +exact-search = [type-filter *WS COLON] [ RETURN-ARROW ] *WS QUOTE ident QUOTE [ generics ] +type-search = [ nonempty-arg-list ] [ return-args ] + +query = *WS (exact-search / type-search) *WS + +type-filter = ( + "mod" / + "externcrate" / + "import" / + "struct" / + "enum" / + "fn" / + "type" / + "static" / + "trait" / + "impl" / + "tymethod" / + "method" / + "structfield" / + "variant" / + "macro" / + "primitive" / + "associatedtype" / + "constant" / + "associatedconstant" / + "union" / + "foreigntype" / + "keyword" / + "existential" / + "attr" / + "derive" / + "traitalias" / + "generic") + +OPEN-ANGLE-BRACKET = "<" +CLOSE-ANGLE-BRACKET = ">" +OPEN-SQUARE-BRACKET = "[" +CLOSE-SQUARE-BRACKET = "]" +COLON = ":" +DOUBLE-COLON = "::" +QUOTE = %x22 +COMMA = "," +RETURN-ARROW = "->" + +ALPHA = %x41-5A / %x61-7A ; A-Z / a-z +DIGIT = %x30-39 +WS = %x09 / " " +``` diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index f69156b7c..7473b0992 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -375,7 +375,7 @@ library, as an equivalent command-line argument is provided to `rustc` when buil This feature allows you to generate an index-page with a given markdown file. A good example of it is the [rust documentation index](https://doc.rust-lang.org/nightly/index.html). -With this, you'll have a page which you can custom as much as you want at the top of your crates. +With this, you'll have a page which you can customize as much as you want at the top of your crates. Using `index-page` option enables `enable-index-page` option as well. @@ -625,3 +625,47 @@ and check the values of `feature`: `foo` and `bar`. This flag enables the generation of links in the source code pages which allow the reader to jump to a type definition. + +### Custom CSS classes for code blocks + +```rust +#![feature(custom_code_classes_in_docs)] + +/// ```custom,{class=language-c} +/// int main(void) { return 0; } +/// ``` +pub struct Bar; +``` + +The text `int main(void) { return 0; }` is rendered without highlighting in a code block +with the class `language-c`. This can be used to highlight other languages through JavaScript +libraries for example. + +Without the `custom` attribute, it would be generated as a Rust code example with an additional +`language-C` CSS class. Therefore, if you specifically don't want it to be a Rust code example, +don't forget to add the `custom` attribute. + +To be noted that you can replace `class=` with `.` to achieve the same result: + +```rust +#![feature(custom_code_classes_in_docs)] + +/// ```custom,{.language-c} +/// int main(void) { return 0; } +/// ``` +pub struct Bar; +``` + +To be noted, `rust` and `.rust`/`class=rust` have different effects: `rust` indicates that this is +a Rust code block whereas the two others add a "rust" CSS class on the code block. + +You can also use double quotes: + +```rust +#![feature(custom_code_classes_in_docs)] + +/// ```"not rust" {."hello everyone"} +/// int main(void) { return 0; } +/// ``` +pub struct Bar; +``` diff --git a/src/doc/rustdoc/src/write-documentation/re-exports.md b/src/doc/rustdoc/src/write-documentation/re-exports.md index 593428b8a..8ce059cc2 100644 --- a/src/doc/rustdoc/src/write-documentation/re-exports.md +++ b/src/doc/rustdoc/src/write-documentation/re-exports.md @@ -86,7 +86,7 @@ pub use self::Hidden as InlinedHidden; ``` The same applies on re-exports themselves: if you have multiple re-exports and some of them have -`#[doc(hidden)]`, then these ones (and only these) own't appear in the documentation: +`#[doc(hidden)]`, then these ones (and only these) won't appear in the documentation: ```rust,ignore (inline) mod private_mod { diff --git a/src/doc/style-guide/src/README.md b/src/doc/style-guide/src/README.md index f4d759673..9a59d8055 100644 --- a/src/doc/style-guide/src/README.md +++ b/src/doc/style-guide/src/README.md @@ -32,6 +32,19 @@ This should not be interpreted as forbidding developers from following a non-default style, or forbidding tools from adding any particular configuration options. +## Bugs + +If the style guide differs from rustfmt, that may represent a bug in rustfmt, +or a bug in the style guide; either way, please report it to the style team or +the rustfmt team or both, for investigation and fix. + +If implementing a new formatting tool based on the style guide and default Rust +style, please test it on the corpus of existing Rust code, and avoid causing +widespread breakage. The implementation and testing of such a tool may surface +bugs in either the style guide or rustfmt, as well as bugs in the tool itself. + +We typically resolve bugs in a fashion that avoids widespread breakage. + ## Formatting conventions ### Indentation and line width diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 32c604f9f..12037b599 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -328,6 +328,26 @@ foo_bar Prefer line-breaking at an assignment operator (either `=` or `+=`, etc.) rather than at other binary operators. +### Casts (`as`) + +Format `as` casts like a binary operator. In particular, always include spaces +around `as`, and if line-breaking, break before the `as` (never after) and +block-indent the subsequent line. Format the type on the right-hand side using +the rules for types. + +However, unlike with other binary operators, if chaining a series of `as` casts +that require line-breaking, and line-breaking before the first `as` suffices to +make the remainder fit on the next line, don't break before any subsequent +`as`; instead, leave the series of types all on the same line: + +```rust +let cstr = very_long_expression() + as *const str as *const [u8] as *const std::os::raw::c_char; +``` + +If the subsequent line still requires line-breaking, break and block-indent +before each `as` as with other binary operators. + ## Control flow Do not include extraneous parentheses for `if` and `while` expressions. @@ -400,7 +420,12 @@ constructs. For example, a macro use `foo!(a, b, c)` can be parsed like a function call (ignoring the `!`), so format it using the rules for function calls. -### Special case macros +The style guide defines specific formatting for particular macros in the +language or standard library. The style guide does not define formatting for +any third-party macros, even if similar to those in the language or standard +library. + +### Format string macros For macros which take a format string, if all other arguments are *small*, format the arguments before the format string on a single line if they fit, and @@ -421,14 +446,6 @@ assert_eq!( ); ``` -## Casts (`as`) - -Put spaces before and after `as`: - -```rust -let cstr = "Hi\0" as *const str as *const [u8] as *const std::os::raw::c_char; -``` - ## Chains of fields and method calls A chain is a sequence of field accesses, method calls, and/or uses of the try diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md index a6d941f6d..b215de6ad 100644 --- a/src/doc/style-guide/src/items.md +++ b/src/doc/style-guide/src/items.md @@ -367,26 +367,52 @@ where ## Type aliases Keep type aliases on one line when they fit. If necessary to break the line, do -so after the `=`, and block-indent the right-hand side: +so before the `=`, and block-indent the right-hand side: ```rust pub type Foo = Bar<T>; // If multi-line is required -type VeryLongType<T, U: SomeBound> = - AnEvenLongerType<T, U, Foo<T>>; +type VeryLongType<T, U: SomeBound> + = AnEvenLongerType<T, U, Foo<T>>; ``` -Where possible avoid `where` clauses and keep type constraints inline. Where -that is not possible split the line before and after the `where` clause (and -split the `where` clause as normal), e.g., +When there is a trailing `where` clause after the type, and no `where` clause +present before the type, break before the `=` and indent. Then break before the +`where` keyword and format the clauses normally, e.g., ```rust +// With only a trailing where clause type VeryLongType<T, U> + = AnEvenLongerType<T, U, Foo<T>> +where + T: U::AnAssociatedType, + U: SomeBound; +``` + +When there is a `where` clause before the type, format it normally, and break +after the last clause. Do not indent before the `=` to leave it visually +distinct from the indented clauses that precede it. If there is additionally a +`where` clause after the type, break before the `where` keyword and format the +clauses normally. + +```rust +// With only a preceding where clause. +type WithPrecedingWC<T, U> where T: U::AnAssociatedType, U: SomeBound, = AnEvenLongerType<T, U, Foo<T>>; + +// Or with both a preceding and trailing where clause. +type WithPrecedingWC<T, U> +where + T: U::AnAssociatedType, + U: SomeBound, += AnEvenLongerType<T, U, Foo<T>> +where + T: U::AnAssociatedType2, + U: SomeBound2; ``` ## Associated types diff --git a/src/doc/unstable-book/src/compiler-flags/link-native-libraries.md b/src/doc/unstable-book/src/compiler-flags/link-native-libraries.md new file mode 100644 index 000000000..a1fcb631c --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/link-native-libraries.md @@ -0,0 +1,8 @@ +# `link-native-libraries` + +This option allows ignoring libraries specified in `#[link]` attributes instead of passing them to the linker. +This can be useful in build systems that manage native libraries themselves and pass them manually, +e.g. with `-Clink-arg`. + +- `yes` - Pass native libraries to the linker. Default. +- `no` - Don't pass native libraries to the linker. diff --git a/src/doc/unstable-book/src/compiler-flags/path-options.md b/src/doc/unstable-book/src/compiler-flags/path-options.md deleted file mode 100644 index 0786ef1f1..000000000 --- a/src/doc/unstable-book/src/compiler-flags/path-options.md +++ /dev/null @@ -1,11 +0,0 @@ -# `--print` Options - -The behavior of the `--print` flag can be modified by optionally be specifying a filepath -for each requested information kind, in the format `--print KIND=PATH`, just like for -`--emit`. When a path is specified, information will be written there instead of to stdout. - -This is unstable feature, so you have to provide `-Zunstable-options` to enable it. - -## Examples - -`rustc main.rs -Z unstable-options --print cfg=cfgs.txt` diff --git a/src/doc/unstable-book/src/language-features/no-coverage.md b/src/doc/unstable-book/src/language-features/coverage-attribute.md index 327cdb397..0a9bd07de 100644 --- a/src/doc/unstable-book/src/language-features/no-coverage.md +++ b/src/doc/unstable-book/src/language-features/coverage-attribute.md @@ -1,4 +1,4 @@ -# `no_coverage` +# `coverage_attribute` The tracking issue for this feature is: [#84605] @@ -6,7 +6,7 @@ The tracking issue for this feature is: [#84605] --- -The `no_coverage` attribute can be used to selectively disable coverage +The `coverage` attribute can be used to selectively disable coverage instrumentation in an annotated function. This might be useful to: - Avoid instrumentation overhead in a performance critical function @@ -16,14 +16,14 @@ instrumentation in an annotated function. This might be useful to: ## Example ```rust -#![feature(no_coverage)] +#![feature(coverage_attribute)] // `foo()` will get coverage instrumentation (by default) fn foo() { // ... } -#[no_coverage] +#[coverage(off)] fn bar() { // ... } diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 9e20662ff..32b882e76 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -37,7 +37,7 @@ Most lang items are defined by `core`, but if you're trying to build an executable without the `std` crate, you might run into the need for lang item definitions. -[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/personality/gcc.rs +[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/sys/personality/gcc.rs ## Example: Implementing a `Box` diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 1fade6ce9..189cc910a 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -43,14 +43,14 @@ extern crate rustc_ast; // Load rustc as a plugin to get macros extern crate rustc_driver; -#[macro_use] extern crate rustc_lint; #[macro_use] extern crate rustc_session; -use rustc_driver::plugin::Registry; -use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; use rustc_ast::ast; +use rustc_driver::plugin::Registry; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; + declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); declare_lint_pass!(Pass => [TEST_LINT]); @@ -58,9 +58,7 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { if it.ident.name.as_str() == "lintme" { - cx.lint(TEST_LINT, |lint| { - lint.build("item is named 'lintme'").set_span(it.span).emit() - }); + cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span)); } } } |