diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:03:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:03:36 +0000 |
commit | 17d40c6057c88f4c432b0d7bac88e1b84cb7e67f (patch) | |
tree | 3f66c4a5918660bb8a758ab6cda5ff8ee4f6cdcd /src/doc | |
parent | Adding upstream version 1.64.0+dfsg1. (diff) | |
download | rustc-upstream/1.65.0+dfsg1.tar.xz rustc-upstream/1.65.0+dfsg1.zip |
Adding upstream version 1.65.0+dfsg1.upstream/1.65.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/doc')
88 files changed, 1732 insertions, 650 deletions
diff --git a/src/doc/book/2018-edition/book.toml b/src/doc/book/2018-edition/book.toml index 9c71e2a91..03b59090b 100644 --- a/src/doc/book/2018-edition/book.toml +++ b/src/doc/book/2018-edition/book.toml @@ -3,5 +3,5 @@ title = "The Rust Programming Language" author = "Steve Klabnik and Carol Nichols, with Contributions from the Rust Community" [output.html] -additional-css = ["ferris.css", "src/theme/2018-edition.css"] +additional-css = ["ferris.css"] additional-js = ["ferris.js"] diff --git a/src/doc/book/2018-edition/src/theme/2018-edition.css b/src/doc/book/2018-edition/src/theme/2018-edition.css deleted file mode 100644 index b1dcf9364..000000000 --- a/src/doc/book/2018-edition/src/theme/2018-edition.css +++ /dev/null @@ -1,9 +0,0 @@ -span.caption { - font-size: .8em; - font-weight: 600; -} - -span.caption code { - font-size: 0.875em; - font-weight: 400; -} diff --git a/src/doc/book/2018-edition/src/theme/index.hbs b/src/doc/book/2018-edition/src/theme/index.hbs deleted file mode 100644 index f3f1b52fa..000000000 --- a/src/doc/book/2018-edition/src/theme/index.hbs +++ /dev/null @@ -1,37 +0,0 @@ -<!DOCTYPE HTML> -<html lang="{{ language }}" class="no-js"> - <head> - <!-- Book generated using mdBook --> - <meta charset="UTF-8"> - <title>Outdated link: {{ title }}</title> - <meta name="robots" content="noindex,follow"> - <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> - - <base href="{{ path_to_root }}"> - - <link rel="stylesheet" href="book.css"> - <link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css"> - <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css"> - - <link rel="stylesheet" href="highlight.css"> - <link rel="stylesheet" href="tomorrow-night.css"> - <link rel="stylesheet" href="ayu-highlight.css"> - - <!-- Custom theme stylesheets --> - {{#each additional_css}} - <link rel="stylesheet" href="{{this}}"> - {{/each}} - </head> - <body class="light"> - <div id="page-wrapper" class="page-wrapper"> - <div class="page"> - {{> header}} - <div id="content" class="content"> - <main> - {{{ content }}} - </main> - </div> - </div> - </div> - </body> -</html> diff --git a/src/doc/book/listings/ch20-web-server/listing-20-24/src/lib.rs b/src/doc/book/listings/ch20-web-server/listing-20-24/src/lib.rs index 55e8fef8f..28c0dea26 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-24/src/lib.rs +++ b/src/doc/book/listings/ch20-web-server/listing-20-24/src/lib.rs @@ -70,7 +70,9 @@ struct Worker { impl Worker { fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker { let thread = thread::spawn(move || loop { - match receiver.lock().unwrap().recv() { + let message = receiver.lock().unwrap().recv(); + + match message { Ok(job) => { println!("Worker {id} got a job; executing."); diff --git a/src/doc/book/src/ch01-03-hello-cargo.md b/src/doc/book/src/ch01-03-hello-cargo.md index 135eacd2f..9979e76dd 100644 --- a/src/doc/book/src/ch01-03-hello-cargo.md +++ b/src/doc/book/src/ch01-03-hello-cargo.md @@ -66,6 +66,8 @@ name = "hello_cargo" version = "0.1.0" edition = "2021" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [dependencies] ``` diff --git a/src/doc/book/src/ch06-02-match.md b/src/doc/book/src/ch06-02-match.md index a24936829..2dfe6c34b 100644 --- a/src/doc/book/src/ch06-02-match.md +++ b/src/doc/book/src/ch06-02-match.md @@ -17,7 +17,7 @@ the value falls into the associated code block to be used during execution. Speaking of coins, let’s use them as an example using `match`! We can write a function that takes an unknown United States coin and, in a similar way as the -counting machine, determines which coin it is and return its value in cents, as +counting machine, determines which coin it is and returns its value in cents, as shown here in Listing 6-3. ```rust diff --git a/src/doc/book/src/ch09-02-recoverable-errors-with-result.md b/src/doc/book/src/ch09-02-recoverable-errors-with-result.md index 61931f08d..347ef9aa7 100644 --- a/src/doc/book/src/ch09-02-recoverable-errors-with-result.md +++ b/src/doc/book/src/ch09-02-recoverable-errors-with-result.md @@ -524,7 +524,7 @@ returns integers from executables to be compatible with this convention. The `main` function may return any types that implement [the `std::process::Termination` trait][termination]<!-- ignore -->, which contains -a function `report` that returns an `ExitCode` Consult the standard library +a function `report` that returns an `ExitCode`. Consult the standard library documentation for more information on implementing the `Termination` trait for your own types. diff --git a/src/doc/book/src/ch20-02-multithreaded.md b/src/doc/book/src/ch20-02-multithreaded.md index bd1dc25ab..5a4a50ac0 100644 --- a/src/doc/book/src/ch20-02-multithreaded.md +++ b/src/doc/book/src/ch20-02-multithreaded.md @@ -387,7 +387,7 @@ this data structure *Worker*, which is a common term in pooling implementations. The Worker picks up code that needs to be run and runs the code in the Worker’s thread. Think of people working in the kitchen at a restaurant: the workers wait until orders come in from customers, and then -they’re responsible for taking those orders and filling them. +they’re responsible for taking those orders and fulfilling them. Instead of storing a vector of `JoinHandle<()>` instances in the thread pool, we’ll store instances of the `Worker` struct. Each `Worker` will store a single diff --git a/src/doc/book/src/title-page.md b/src/doc/book/src/title-page.md index 47226dc84..ed55a6839 100644 --- a/src/doc/book/src/title-page.md +++ b/src/doc/book/src/title-page.md @@ -20,3 +20,7 @@ Press][nsprust]. [editions]: appendix-05-editions.html [nsprust]: https://nostarch.com/rust [translations]: appendix-06-translation.html + +> **🚨 Want a more interactive learning experience? Try out a different version +> of the Rust Book, featuring: quizzes, highlighting, visualizations, and +> more**: <https://rust-book.cs.brown.edu> diff --git a/src/doc/edition-guide/README.md b/src/doc/edition-guide/README.md index 559498257..3f3994381 100644 --- a/src/doc/edition-guide/README.md +++ b/src/doc/edition-guide/README.md @@ -8,8 +8,8 @@ online](https://doc.rust-lang.org/nightly/edition-guide/). ## License -The Edition Guide is dual licensed under `MIT`/`Apache2`, just like Rust itself. -See the `LICENSE-*` files in this repository for more details. +The Rust Edition Guide is dual licensed under `MIT`/`Apache2`, just like Rust +itself. See the `LICENSE-*` files in this repository for more details. ## Building locally diff --git a/src/doc/edition-guide/book.toml b/src/doc/edition-guide/book.toml index 8d8b26322..7841b647d 100644 --- a/src/doc/edition-guide/book.toml +++ b/src/doc/edition-guide/book.toml @@ -2,7 +2,7 @@ authors = ["The Rust Project Developers"] multilingual = false src = "src" -title = "The Edition Guide" +title = "The Rust Edition Guide" [output.html] git-repository-url = "https://github.com/rust-lang/edition-guide" diff --git a/src/doc/edition-guide/src/SUMMARY.md b/src/doc/edition-guide/src/SUMMARY.md index dac77913b..9ac69923f 100644 --- a/src/doc/edition-guide/src/SUMMARY.md +++ b/src/doc/edition-guide/src/SUMMARY.md @@ -1,4 +1,4 @@ -# The Edition Guide +# The Rust Edition Guide [Introduction](introduction.md) diff --git a/src/doc/edition-guide/src/editions/creating-a-new-project.md b/src/doc/edition-guide/src/editions/creating-a-new-project.md index 319d6996c..8ec71d67e 100644 --- a/src/doc/edition-guide/src/editions/creating-a-new-project.md +++ b/src/doc/edition-guide/src/editions/creating-a-new-project.md @@ -1,12 +1,12 @@ # Creating a new project -When you create a new project with Cargo, it will automatically add -configuration for the latest edition: +A new project created with Cargo is configured to use the latest edition by +default: ```console -> cargo new foo +$ cargo new foo Created binary (application) `foo` project -> cat foo/Cargo.toml +$ cat foo/Cargo.toml [package] name = "foo" version = "0.1.0" @@ -15,11 +15,41 @@ edition = "2021" [dependencies] ``` -That `edition = "2021"` setting will configure your package to use Rust 2021. -No more configuration needed! +That `edition = "2021"` setting configures your package to be built using the +Rust 2021 edition. No further configuration needed! -If you'd prefer to use an older edition, you can change the value in that -key, for example: +You can use the `--edition <YEAR>` option of `cargo new` to create the project +using some specific edition. For example, creating a new project to use the +Rust 2018 edition could be done like this: + +```console +$ cargo new --edition 2018 foo + Created binary (application) `foo` project +$ cat foo/Cargo.toml +[package] +name = "foo" +version = "0.1.0" +edition = "2018" + +[dependencies] +``` + +Don't worry about accidentally using an invalid year for the edition; the +`cargo new` invocation will not accept an invalid edition year value: + +```console +$ cargo new --edition 2019 foo +error: "2019" isn't a valid value for '--edition <YEAR>' + [possible values: 2015, 2018, 2021] + + Did you mean "2018"? + +For more information try --help +``` + +You can change the value of the `edition` key by simply editing the +`Cargo.toml` file. For example, to cause your package to be built using the +Rust 2015 edition, you would set the key as in the following example: ```toml [package] @@ -29,5 +59,3 @@ edition = "2015" [dependencies] ``` - -This will build your package in Rust 2015. diff --git a/src/doc/edition-guide/src/editions/index.md b/src/doc/edition-guide/src/editions/index.md index e12285c49..b5480e809 100644 --- a/src/doc/edition-guide/src/editions/index.md +++ b/src/doc/edition-guide/src/editions/index.md @@ -1,6 +1,8 @@ # What are Editions? -The release of Rust 1.0 established +The release of Rust 1.0 +([in May 2015](https://blog.rust-lang.org/2015/05/15/Rust-1.0.html)) +established ["stability without stagnation"](https://blog.rust-lang.org/2014/10/30/Stability.html) as a core Rust deliverable. Ever since the 1.0 release, @@ -51,11 +53,11 @@ there might be some corner cases where manual changes are still required. The tooling tries hard to avoid changes to semantics that could affect the correctness or performance of the code. -In addition to tooling, we also maintain this Edition Migration Guide that covers +In addition to tooling, we also maintain this Rust Edition Guide that covers the changes that are part of an edition. This guide describes each change and gives pointers to where you can learn more about it. It also covers any corner cases or details you should be aware of. -This guide serves both as an overview of the edition +This guide serves as an overview of editions, +as a migration guide for specific editions, and as a quick troubleshooting reference if you encounter problems with the automated tooling. - diff --git a/src/doc/edition-guide/src/introduction.md b/src/doc/edition-guide/src/introduction.md index c23508b2f..a36a620a8 100644 --- a/src/doc/edition-guide/src/introduction.md +++ b/src/doc/edition-guide/src/introduction.md @@ -1,6 +1,6 @@ # Introduction -Welcome to the Rust Edition Guide! "Editions" are Rust's way of introducing +Welcome to The Rust Edition Guide! "Editions" are Rust's way of introducing changes into the language that would not otherwise be backwards compatible. diff --git a/src/doc/index.md b/src/doc/index.md index b77790e33..744c7f709 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -101,7 +101,7 @@ accomplishing various tasks. Many of Rust's errors come with error codes, and you can request extended diagnostics from the compiler on those errors. You can also [read them -here](error-index.html), if you prefer to read them that way. +here](error_codes/index.html), if you prefer to read them that way. # Master Rust diff --git a/src/doc/nomicon/src/lifetime-mismatch.md b/src/doc/nomicon/src/lifetime-mismatch.md index 0494d492a..1da2d285c 100644 --- a/src/doc/nomicon/src/lifetime-mismatch.md +++ b/src/doc/nomicon/src/lifetime-mismatch.md @@ -76,7 +76,7 @@ care about, but the lifetime system is too coarse-grained to handle that. The following code fails to compile, because Rust sees that a variable, `map`, is borrowed twice, and can not infer that the first borrow stops to be needed before the second one occurs. This is caused by Rust conservatively falling back -to using a whole scope for the first borow. This will eventually get fixed. +to using a whole scope for the first borrow. This will eventually get fixed. ```rust,compile_fail # use std::collections::HashMap; diff --git a/src/doc/nomicon/src/lifetimes.md b/src/doc/nomicon/src/lifetimes.md index ef86b7b53..f55ea8c2a 100644 --- a/src/doc/nomicon/src/lifetimes.md +++ b/src/doc/nomicon/src/lifetimes.md @@ -55,7 +55,7 @@ likely desugar to the following: let y: &'b i32 = &'b x; 'c: { // ditto on 'c - let z: &'c &'b i32 = &'c y; + let z: &'c &'b i32 = &'c y; // "a reference to a reference to an i32" (with lifetimes annotated) } } } diff --git a/src/doc/nomicon/src/other-reprs.md b/src/doc/nomicon/src/other-reprs.md index 93da7297e..228b22bda 100644 --- a/src/doc/nomicon/src/other-reprs.md +++ b/src/doc/nomicon/src/other-reprs.md @@ -56,24 +56,26 @@ compiled as normal.) ## repr(transparent) -This can only be used on structs with a single non-zero-sized field (there may -be additional zero-sized fields). The effect is that the layout and ABI of the -whole struct is guaranteed to be the same as that one field. +`#[repr(transparent)]` can only be used on a struct or single-variant enum that has a single non-zero-sized field (there may be additional zero-sized fields). +The effect is that the layout and ABI of the whole struct/enum is guaranteed to be the same as that one field. + +> NOTE: There's a `transparent_unions` nightly feature to apply `repr(transparent)` to unions, +> but it hasn't been stabilized due to design concerns. See the [tracking issue][issue-60405] for more details. The goal is to make it possible to transmute between the single field and the -struct. An example of that is [`UnsafeCell`], which can be transmuted into +struct/enum. An example of that is [`UnsafeCell`], which can be transmuted into the type it wraps ([`UnsafeCell`] also uses the unstable [no_niche][no-niche-pull], so its ABI is not actually guaranteed to be the same when nested in other types). -Also, passing the struct through FFI where the inner field type is expected on -the other side is guaranteed to work. In particular, this is necessary for `struct -Foo(f32)` to always have the same ABI as `f32`. +Also, passing the struct/enum through FFI where the inner field type is expected on +the other side is guaranteed to work. In particular, this is necessary for +`struct Foo(f32)` or `enum Foo { Bar(f32) }` to always have the same ABI as `f32`. This repr is only considered part of the public ABI of a type if either the single field is `pub`, or if its layout is documented in prose. Otherwise, the layout should not be relied upon by other crates. -More details are in the [RFC][rfc-transparent]. +More details are in the [RFC 1758][rfc-transparent] and the [RFC 2645][rfc-transparent-unions-enums]. ## repr(u*), repr(i*) @@ -153,8 +155,10 @@ This is a modifier on `repr(C)` and `repr(Rust)`. It is incompatible with [unsafe code guidelines]: https://rust-lang.github.io/unsafe-code-guidelines/layout.html [drop flags]: drop-flags.html [ub loads]: https://github.com/rust-lang/rust/issues/27060 +[issue-60405]: https://github.com/rust-lang/rust/issues/60405 [`UnsafeCell`]: ../std/cell/struct.UnsafeCell.html [rfc-transparent]: https://github.com/rust-lang/rfcs/blob/master/text/1758-repr-transparent.md +[rfc-transparent-unions-enums]: https://rust-lang.github.io/rfcs/2645-transparent-unions.html [really-tagged]: https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md [rust-bindgen]: https://rust-lang.github.io/rust-bindgen/ [cbindgen]: https://github.com/eqrion/cbindgen diff --git a/src/doc/reference/book.toml b/src/doc/reference/book.toml index 2bc218fe4..19b9afc79 100644 --- a/src/doc/reference/book.toml +++ b/src/doc/reference/book.toml @@ -6,6 +6,7 @@ author = "The Rust Project Developers" [output.html] additional-css = ["theme/reference.css"] git-repository-url = "https://github.com/rust-lang/reference/" +edit-url-template = "https://github.com/rust-lang/reference/edit/master/{path}" [output.html.redirect] "/expressions/enum-variant-expr.html" = "struct-expr.html" diff --git a/src/doc/reference/src/attributes/testing.md b/src/doc/reference/src/attributes/testing.md index 63df999ad..2c3b29286 100644 --- a/src/doc/reference/src/attributes/testing.md +++ b/src/doc/reference/src/attributes/testing.md @@ -12,9 +12,8 @@ functions are only compiled when in test mode. Test functions must be free, monomorphic functions that take no arguments, and the return type must implement the [`Termination`] trait, for example: * `()` -* `Result<(), E> where E: Debug` +* `Result<T, E> where T: Termination, E: Debug` * `!` -<!-- * Result<!, E> where E: Debug` --> <!-- If the previous section needs updating (from "must take no arguments" onwards, also update it in the crates-and-source-files.md file --> diff --git a/src/doc/reference/src/attributes/type_system.md b/src/doc/reference/src/attributes/type_system.md index 729069d26..71b0243a6 100644 --- a/src/doc/reference/src/attributes/type_system.md +++ b/src/doc/reference/src/attributes/type_system.md @@ -127,6 +127,14 @@ match message { } ``` +It's also not allowed to cast non-exhaustive types from foreign crates. +```rust, ignore +use othercrate::NonExhaustiveEnum; + +// Cannot cast a non-exhaustive enum outside of its defining crate. +let _ = NonExhaustiveEnum::default() as u8; +``` + Non-exhaustive types are always considered inhabited in downstream crates. [_MetaWord_]: ../attributes.md#meta-item-attribute-syntax diff --git a/src/doc/reference/src/crates-and-source-files.md b/src/doc/reference/src/crates-and-source-files.md index 6922b0ee3..8d54c3f6b 100644 --- a/src/doc/reference/src/crates-and-source-files.md +++ b/src/doc/reference/src/crates-and-source-files.md @@ -123,10 +123,9 @@ fn main() -> impl std::process::Termination { > > * `()` > * [`!`] +> * [`Infallible`] > * [`ExitCode`] -> * `Result<(), E> where E: Debug` -> * `Result<Infallible, E> where E: Debug` -<!-- > * Result<!, E> where E: Debug` --> +> * `Result<T, E> where T: Termination, E: Debug` <!-- If the previous section needs updating (from "must take no arguments" onwards, also update it in the testing.md file --> @@ -165,6 +164,7 @@ or `_` (U+005F) characters. [_shebang_]: https://en.wikipedia.org/wiki/Shebang_(Unix) [_utf8 byte order mark_]: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 [`ExitCode`]: ../std/process/struct.ExitCode.html +[`Infallible`]: ../std/convert/enum.Infallible.html [`Termination`]: ../std/process/trait.Termination.html [attribute]: attributes.md [attributes]: attributes.md diff --git a/src/doc/rust-by-example/book.toml b/src/doc/rust-by-example/book.toml index 19db456b6..61fb4057f 100644 --- a/src/doc/rust-by-example/book.toml +++ b/src/doc/rust-by-example/book.toml @@ -6,6 +6,7 @@ author = "The Rust Community" [output.html.playpen] editable = true editor = "ace" +line-numbers = true [output.html.fold] enable = true diff --git a/src/doc/rust-by-example/src/SUMMARY.md b/src/doc/rust-by-example/src/SUMMARY.md index 223a5d8dd..9d7001690 100644 --- a/src/doc/rust-by-example/src/SUMMARY.md +++ b/src/doc/rust-by-example/src/SUMMARY.md @@ -219,4 +219,4 @@ - [Meta](meta.md) - [Documentation](meta/doc.md) - - [Playpen](meta/playpen.md) + - [Playground](meta/playground.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 c998ad9ad..eb515aee6 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 @@ -8,7 +8,7 @@ The is more than one way to unpack an `Option` and fall back on a default if it `or()`is chainable and eagerly evaluates its argument, as is shown in the following example. Note that because `or`'s arguments are evaluated eagerly, the variable passed to `or` is moved. -``` +```rust,editable #[derive(Debug)] enum Fruit { Apple, Orange, Banana, Kiwi, Lemon } @@ -33,7 +33,7 @@ fn main() { Another alternative is to use `or_else`, which is also chainable, and evaluates lazily, as is shown in the following example: -``` +```rust,editable #[derive(Debug)] enum Fruit { Apple, Orange, Banana, Kiwi, Lemon } @@ -58,11 +58,11 @@ fn main() { } ``` -## `get_or_insert()` evaluates eagerly, modifies empty value im place +## `get_or_insert()` evaluates eagerly, modifies empty value in place To make sure that an `Option` contains a value, we can use `get_or_insert` to modify it in place with a fallback value, as is shown in the following example. Note that `get_or_insert` eagerly evaluaes its parameter, so variable `apple` is moved: -``` +```rust,editable #[derive(Debug)] enum Fruit { Apple, Orange, Banana, Kiwi, Lemon } @@ -79,10 +79,10 @@ fn main() { } ``` -## `get_or_insert_with()` evaluates lazily, modifies empty value im place +## `get_or_insert_with()` evaluates lazily, modifies empty value in place Instead of explicitly providing a value to fall back on, we can pass a closure to `get_or_insert_with`, as follows: -``` +```rust,editable #[derive(Debug)] enum Fruit { Apple, Orange, Banana, Kiwi, Lemon } diff --git a/src/doc/rust-by-example/src/flow_control.md b/src/doc/rust-by-example/src/flow_control.md index c8a2f9ed8..79ef7e1f6 100644 --- a/src/doc/rust-by-example/src/flow_control.md +++ b/src/doc/rust-by-example/src/flow_control.md @@ -1,4 +1,4 @@ # Flow of Control -An essential part of any programming languages are ways to modify control flow: +An integral part of any programming language are ways to modify control flow: `if`/`else`, `for`, and others. Let's talk about them in Rust. diff --git a/src/doc/rust-by-example/src/hello/print.md b/src/doc/rust-by-example/src/hello/print.md index 34dc9f0dd..c28dd9125 100644 --- a/src/doc/rust-by-example/src/hello/print.md +++ b/src/doc/rust-by-example/src/hello/print.md @@ -31,18 +31,20 @@ fn main() { // Different formatting can be invoked by specifying the format character after a // `:`. - println!("Base 10 repr: {}", 69420); - println!("Base 2 (binary) repr: {:b}", 69420); - println!("Base 8 (octal) repr: {:o}", 69420); - println!("Base 16 (hexadecimal) repr: {:x}", 69420); - println!("Base 16 (hexadecimal) repr: {:X}", 69420); - - // You can right-align text with a specified width. This will output - // " 1". 4 white spaces and a "1", for a total width of 5. + println!("Base 10: {}", 69420); //69420 + println!("Base 2 (binary): {:b}", 69420); //10000111100101100 + println!("Base 8 (octal): {:o}", 69420); //207454 + println!("Base 16 (hexadecimal): {:x}", 69420); //10f2c + println!("Base 16 (hexadecimal): {:X}", 69420); //10F2C + + + // You can right-justify text with a specified width. This will + // output " 1". (Four white spaces and a "1", for a total width of 5.) println!("{number:>5}", number=1); - // You can pad numbers with extra zeroes. This will output "00001". - println!("{number:0>5}", number=1); + // You can pad numbers with extra zeroes, + //and left-adjust by flipping the sign. This will output "10000". + println!("{number:0<5}", number=1); // You can use named arguments in the format specifier by appending a `$` println!("{number:0>width$}", number=1, width=5); diff --git a/src/doc/rust-by-example/src/meta.md b/src/doc/rust-by-example/src/meta.md index 367c7e121..8fcea1df0 100644 --- a/src/doc/rust-by-example/src/meta.md +++ b/src/doc/rust-by-example/src/meta.md @@ -6,7 +6,7 @@ everyone. These topics include: - [Documentation][doc]: Generate library documentation for users via the included `rustdoc`. -- [Playpen][playpen]: Integrate the Rust Playpen (also known as the Rust Playground) in your documentation. +- [Playground][playground]: Integrate the Rust Playground in your documentation. [doc]: meta/doc.md -[playpen]: meta/playpen.md +[playground]: meta/playground.md diff --git a/src/doc/rust-by-example/src/meta/doc.md b/src/doc/rust-by-example/src/meta/doc.md index 63e0b4101..e9e51186f 100644 --- a/src/doc/rust-by-example/src/meta/doc.md +++ b/src/doc/rust-by-example/src/meta/doc.md @@ -44,7 +44,7 @@ impl Person { /// Gives a friendly hello! /// - /// Says "Hello, [name]" to the `Person` it is called on. + /// Says "Hello, [name](Person::name)" to the `Person` it is called on. pub fn hello(& self) { println!("Hello, {}!", self.name); } diff --git a/src/doc/rust-by-example/src/meta/playpen.md b/src/doc/rust-by-example/src/meta/playground.md index a125f139d..7fcfad1a7 100644 --- a/src/doc/rust-by-example/src/meta/playpen.md +++ b/src/doc/rust-by-example/src/meta/playground.md @@ -1,6 +1,6 @@ -# Playpen +# Playground -The [Rust Playpen](https://github.com/rust-lang/rust-playpen) is a way to experiment with Rust code through a web interface. This project is now commonly referred to as [Rust Playground](https://play.rust-lang.org/). +The [Rust Playground](https://play.rust-lang.org/) is a way to experiment with Rust code through a web interface. ## Using it with `mdbook` @@ -35,11 +35,11 @@ You may have noticed in some of the [official Rust docs][official-rust-docs] a b ### See also: - [The Rust Playground][rust-playground] -- [The next-gen playpen][next-gen-playpen] +- [rust-playground][rust-playground] - [The rustdoc Book][rustdoc-book] [rust-playground]: https://play.rust-lang.org/ -[next-gen-playpen]: https://github.com/integer32llc/rust-playground/ +[rust-playground]: https://github.com/integer32llc/rust-playground/ [mdbook]: https://github.com/rust-lang/mdBook [official-rust-docs]: https://doc.rust-lang.org/core/ [rustdoc-book]: https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html diff --git a/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md b/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md index 28075164f..ee25b1661 100644 --- a/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md +++ b/src/doc/rust-by-example/src/std_misc/threads/testcase_mapreduce.md @@ -17,9 +17,11 @@ its tiny block of digits, and subsequently we will sum the intermediate sums pro thread. Note that, although we're passing references across thread boundaries, Rust understands that we're -only passing read-only references, and that thus no unsafety or data races can occur. Because -we're `move`-ing the data segments into the thread, Rust will also ensure the data is kept alive -until the threads exit, so no dangling pointers occur. +only passing read-only references, and that thus no unsafety or data races can occur. Also because +the references we're passing have `'static` lifetimes, Rust understands that our data won't be +destroyed while these threads are still running. (When you need to share non-`static` data between +threads, you can use a smart pointer like `Arc` to keep the data alive and avoid non-`static` +lifetimes.) ```rust,editable use std::thread; diff --git a/src/doc/rustc-dev-guide/book.toml b/src/doc/rustc-dev-guide/book.toml index 51dc8ecb0..c86ec5638 100644 --- a/src/doc/rustc-dev-guide/book.toml +++ b/src/doc/rustc-dev-guide/book.toml @@ -15,7 +15,7 @@ command = "mdbook-mermaid" [output.html] git-repository-url = "https://github.com/rust-lang/rustc-dev-guide" -edit-url-template = "https://github.com/rust-lang/rustc-dev-guide/tree/master/{path}?mode=edit" +edit-url-template = "https://github.com/rust-lang/rustc-dev-guide/edit/master/{path}" additional-js = ["mermaid.min.js", "mermaid-init.js"] [output.html.fold] diff --git a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs index bbea2bf38..70fce8b1c 100644 --- a/src/doc/rustc-dev-guide/ci/date-check/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/date-check/src/main.rs @@ -3,9 +3,11 @@ use std::{ convert::TryInto as _, env, fmt, fs, path::{Path, PathBuf}, + process, + str::FromStr, }; -use chrono::{Datelike as _, TimeZone as _, Utc}; +use chrono::{Datelike as _, Month, TimeZone as _, Utc}; use glob::glob; use regex::Regex; @@ -38,12 +40,18 @@ impl fmt::Display for Date { fn make_date_regex() -> Regex { Regex::new( r"(?x) # insignificant whitespace mode - <!--\s* - [dD]ate:\s* - (?P<y>\d{4}) # year - - - (?P<m>\d{2}) # month - \s*-->", + (<!--\s* + date-check:\s* + (?P<m1>[[:alpha:]]+)\s+ + (?P<y1>\d{4})\s*--> + ) + | + (<!--\s* + date-check\s*-->\s+ + (?P<m2>[[:alpha:]]+)\s+ + (?P<y2>\d{4})\b + ) + ", ) .unwrap() } @@ -52,15 +60,22 @@ fn collect_dates_from_file(date_regex: &Regex, text: &str) -> Vec<(usize, Date)> let mut line = 1; let mut end_of_last_cap = 0; date_regex - .captures_iter(&text) - .map(|cap| { - ( - cap.get(0).unwrap().range(), - Date { - year: cap["y"].parse().unwrap(), - month: cap["m"].parse().unwrap(), - }, - ) + .captures_iter(text) + .filter_map(|cap| { + if let (Some(month), Some(year), None, None) | (None, None, Some(month), Some(year)) = ( + cap.name("m1"), + cap.name("y1"), + cap.name("m2"), + cap.name("y2"), + ) { + let year = year.as_str().parse().expect("year"); + let month = Month::from_str(month.as_str()) + .expect("month") + .number_from_month(); + Some((cap.get(0).expect("all").range(), Date { year, month })) + } else { + None + } }) .map(|(byte_range, date)| { line += text[end_of_last_cap..byte_range.end] @@ -110,9 +125,12 @@ fn filter_dates( } fn main() { - let root_dir = env::args() - .nth(1) - .expect("expect root Markdown directory as CLI argument"); + let mut args = env::args(); + if args.len() == 1 { + eprintln!("error: expected root Markdown directory as CLI argument"); + process::exit(1); + } + let root_dir = args.nth(1).unwrap(); let root_dir_path = Path::new(&root_dir); let glob_pat = format!("{}/**/*.md", root_dir); let today_chrono = Utc::today(); @@ -136,7 +154,7 @@ fn main() { up-to-date. Each date should be updated (in the Markdown file where it appears) to \ use the current month ({current_month}), or removed if the docs it annotates are not \ expected to fall out of date quickly.", - current_month = current_month + current_month = today_chrono.format("%B %Y"), ); println!(); println!( @@ -153,7 +171,7 @@ fn main() { for (path, dates) in dates_by_file { println!( "- [ ] {}", - path.strip_prefix(&root_dir_path).unwrap().display() + path.strip_prefix(&root_dir_path).unwrap_or(&path).display(), ); for (line, date) in dates { println!(" - [ ] line {}: {}", line, date); @@ -182,61 +200,153 @@ mod tests { #[test] fn test_date_regex() { - let regex = make_date_regex(); - assert!(regex.is_match("foo <!-- date: 2021-01 --> bar")); + let regex = &make_date_regex(); + assert!(regex.is_match("<!-- date-check: jan 2021 -->")); + assert!(regex.is_match("<!-- date-check: january 2021 -->")); + assert!(regex.is_match("<!-- date-check: Jan 2021 -->")); + assert!(regex.is_match("<!-- date-check: January 2021 -->")); + assert!(regex.is_match("<!-- date-check --> jan 2021")); + assert!(regex.is_match("<!-- date-check --> january 2021")); + assert!(regex.is_match("<!-- date-check --> Jan 2021")); + assert!(regex.is_match("<!-- date-check --> January 2021")); + + assert!(regex.is_match("<!-- date-check --> jan 2021 ")); + assert!(regex.is_match("<!-- date-check --> jan 2021.")); } #[test] - fn test_date_regex_capitalized() { - let regex = make_date_regex(); - assert!(regex.is_match("foo <!-- Date: 2021-08 --> bar")); + fn test_date_regex_fail() { + let regexes = &make_date_regex(); + assert!(!regexes.is_match("<!-- date-check: jan 221 -->")); + assert!(!regexes.is_match("<!-- date-check: jan 20221 -->")); + assert!(!regexes.is_match("<!-- date-check: 01 2021 -->")); + assert!(!regexes.is_match("<!-- date-check --> jan 221")); + assert!(!regexes.is_match("<!-- date-check --> jan 20222")); + assert!(!regexes.is_match("<!-- date-check --> 01 2021")); } #[test] fn test_collect_dates_from_file() { - let text = "Test1\n<!-- date: 2021-01 -->\nTest2\nFoo<!-- date: 2021-02 \ - -->\nTest3\nTest4\nFoo<!-- date: 2021-03 -->Bar\n<!-- date: 2021-04 \ - -->\nTest5\nTest6\nTest7\n<!-- date: \n\n2021-05 -->\nTest8 + let text = r" +Test1 +<!-- date-check: jan 2021 --> +Test2 +Foo<!-- date-check: february 2021 +--> +Test3 +Test4 +Foo<!-- date-check: Mar 2021 -->Bar +<!-- date-check:April 2021 +--> +Test5 +Test6 +Test7 +<!-- date-check: + +may 2021 --> +Test8 +Test1 +<!-- date-check --> jan 2021 +Test2 +Foo<!-- date-check +--> february 2021 +Test3 +Test4 +Foo<!-- date-check --> mar 2021 Bar +<!-- date-check +--> apr 2021 +Test5 +Test6 +Test7 +<!-- date-check + + --> may 2021 +Test8 + <!-- + date-check + --> june 2021. "; assert_eq!( collect_dates_from_file(&make_date_regex(), text), vec![ ( - 2, + 3, + Date { + year: 2021, + month: 1, + } + ), + ( + 6, + Date { + year: 2021, + month: 2, + } + ), + ( + 9, + Date { + year: 2021, + month: 3, + } + ), + ( + 11, + Date { + year: 2021, + month: 4, + } + ), + ( + 17, + Date { + year: 2021, + month: 5, + } + ), + ( + 20, Date { year: 2021, month: 1, } ), ( - 4, + 23, Date { year: 2021, month: 2, } ), ( - 7, + 26, Date { year: 2021, month: 3, } ), ( - 8, + 28, Date { year: 2021, month: 4, } ), ( - 14, + 34, Date { year: 2021, month: 5, } ), - ] + ( + 38, + Date { + year: 2021, + month: 6, + } + ), + ], ); } } diff --git a/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md b/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md index 271e6a16f..ea50cd754 100644 --- a/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md +++ b/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md @@ -2,15 +2,12 @@ <!-- toc --> -As of <!-- date: 2021-10 --> October 2021, `rustc_codegen_ssa` provides an +As of <!-- date-check --> Aug 2022, `rustc_codegen_ssa` provides an abstract interface for all backends to implement, to allow other codegen backends (e.g. [Cranelift]). [Cranelift]: https://github.com/bytecodealliance/wasmtime/tree/HEAD/cranelift -> The following is a copy/paste of a README from the rust-lang/rust repo. -> Please submit a PR if it needs updating. - # Refactoring of `rustc_codegen_llvm` by Denis Merigoux, October 23rd 2018 diff --git a/src/doc/rustc-dev-guide/src/backend/codegen.md b/src/doc/rustc-dev-guide/src/backend/codegen.md index 1a6c2fa76..5feea5202 100644 --- a/src/doc/rustc-dev-guide/src/backend/codegen.md +++ b/src/doc/rustc-dev-guide/src/backend/codegen.md @@ -1,13 +1,16 @@ # Code generation -Code generation or "codegen" is the part of the compiler that actually -generates an executable binary. Usually, rustc uses LLVM for code generation; -there is also support for [Cranelift]. The key is that rustc doesn't implement -codegen itself. It's worth noting, though, that in the Rust source code, many -parts of the backend have `codegen` in their names (there are no hard -boundaries). - -[Cranelift]: https://github.com/bytecodealliance/wasmtime/tree/HEAD/cranelift +Code generation (or "codegen") is the part of the compiler +that actually generates an executable binary. +Usually, rustc uses LLVM for code generation, +bu there is also support for [Cranelift] and [GCC]. +The key is that rustc doesn't implement codegen itself. +It's worth noting, though, that in the Rust source code, +many parts of the backend have `codegen` in their names +(there are no hard boundaries). + +[Cranelift]: https://github.com/bytecodealliance/wasmtime/tree/main/cranelift +[GCC]: https://github.com/rust-lang/rustc_codegen_gcc > NOTE: If you are looking for hints on how to debug code generation bugs, > please see [this section of the debugging chapter][debugging]. 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 0de0767b6..81ebbbb40 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -43,7 +43,7 @@ the branch we're already using. The steps for this are: 1. Make sure the bugfix is in upstream LLVM. 2. Identify the branch that rustc is currently using. The `src/llvm-project` submodule is always pinned to a branch of the - [rust-lang/llvm-project](https://github.com/rust-lang/llvm-project) repository. + [rust-lang/llvm-project repository]. 3. Fork the rust-lang/llvm-project repository 4. Check out the appropriate branch (typically named `rustc/a.b-yyyy-mm-dd`) 5. Cherry-pick the upstream commit onto the branch @@ -66,8 +66,8 @@ Example PRs look like: ## Feature updates -> Note that this information is as of the time of this writing <!-- date: -2021-10 --> (October 2021). The process for updating LLVM changes with +> Note that this information is as of the time of this writing, <!-- +date-check --> October 2021. The process for updating LLVM changes with practically all LLVM updates, so this may be out of date! Unlike bugfixes, updating to pick up a new feature of LLVM typically requires a @@ -146,9 +146,6 @@ easiest to land [`llvm-wrapper`] compatibility as a PR before actually updating interested in trying out the new LLVM can benefit from work you've done to update the C++ bindings. -[rust-lang/llvm-project repository]: https://github.com/rust-lang/llvm-project -[`llvm-wrapper`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_llvm/llvm-wrapper - ### Caveats and gotchas Ideally the above instructions are pretty smooth, but here's some caveats to @@ -161,8 +158,6 @@ keep in mind while going through them: * Creating branches is a privileged operation on GitHub, so you'll need someone with write access to create the branches for you most likely. -[wg-llvm]: https://rust-lang.zulipchat.com/#narrow/stream/187780-t-compiler.2Fwg-llvm - ## New LLVM Release Updates Updating to a new release of LLVM is very similar to the "feature updates" @@ -172,7 +167,7 @@ section above is generally around branch naming. The sequence of events typically looks like: 1. LLVM announces that its latest release version has branched. This will show - up as a branch in https://github.com/llvm/llvm-project typically named + up as a branch in the [llvm/llvm-project repository] typically named `release/$N.x` where `$N` is the version of LLVM that's being released. 2. We then follow the "feature updates" section above to create a new branch of @@ -192,3 +187,8 @@ typically looks like: to create a new branch in the rust-lang/llvm-project repository, this time with a new date. The commit history should look much cleaner as just a few Rust-specific commits stacked on top of stock LLVM's release branch. + +[rust-lang/llvm-project repository]: https://github.com/rust-lang/llvm-project +[llvm/llvm-project repository]: https://github.com/llvm/llvm-project +[`llvm-wrapper`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_llvm/llvm-wrapper +[wg-llvm]: https://rust-lang.zulipchat.com/#narrow/stream/187780-t-compiler.2Fwg-llvm diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/member_constraints.md b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/member_constraints.md index c7c107e1e..e236e0124 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/member_constraints.md +++ b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/member_constraints.md @@ -94,7 +94,7 @@ member constraints come in. ## Choices are always lifetime parameters At present, the "choice" regions from a member constraint are always lifetime -parameters from the current function. As of <!-- date: 2021-10 --> October 2021, +parameters from the current function. As of <!-- date-check --> October 2021, this falls out from the placement of impl Trait, though in the future it may not be the case. We take some advantage of this fact, as it simplifies the current code. In particular, we don't have to consider a case like `'0 member of ['1, diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping.md b/src/doc/rustc-dev-guide/src/building/bootstrapping.md index fd54de20c..939c47f1b 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping.md @@ -18,7 +18,34 @@ rustc, then uses it to compile the new compiler. ## Stages of bootstrapping -Compiling `rustc` is done in stages. +Compiling `rustc` is done in stages. Here's a diagram, adapted from Joshua Nelson's +[talk on bootstrapping][rustconf22-talk] at RustConf 2022, with detailed explanations below. + +The `A`, `B`, `C`, and `D` show the ordering of the stages of bootstrapping. +<span style="background-color: lightblue; color: black">Blue</span> nodes are downloaded, +<span style="background-color: yellow; color: black">yellow</span> nodes are built with the +stage0 compiler, and +<span style="background-color: lightgreen; color: black">green</span> nodes are built with the +stage1 compiler. + +[rustconf22-talk]: https://rustconf.com/schedule#bootstrapping-the-once-and-future-compiler + +```mermaid +graph TD + s0c["stage0 compiler (1.63)"]:::downloaded -->|A| s0l("stage0 std (1.64)"):::with-s0c; + s0c & s0l --- stepb[ ]:::empty; + stepb -->|B| s0ca["stage0 compiler artifacts (1.64)"]:::with-s0c; + s0ca -->|copy| s1c["stage1 compiler (1.64)"]:::with-s0c; + s1c -->|C| s1l("stage1 std (1.64)"):::with-s1c; + s1c & s1l --- stepd[ ]:::empty; + stepd -->|D| s1ca["stage1 compiler artifacts (1.64)"]:::with-s1c; + s1ca -->|copy| s2c["stage2 compiler"]:::with-s1c; + + classDef empty width:0px,height:0px; + classDef downloaded fill: lightblue; + classDef with-s0c fill: yellow; + classDef with-s1c fill: lightgreen; +``` ### Stage 0 diff --git a/src/doc/rustc-dev-guide/src/building/prerequisites.md b/src/doc/rustc-dev-guide/src/building/prerequisites.md index a5ab23d91..0783e82ee 100644 --- a/src/doc/rustc-dev-guide/src/building/prerequisites.md +++ b/src/doc/rustc-dev-guide/src/building/prerequisites.md @@ -12,7 +12,8 @@ Before building the compiler, you need the following things installed: If building LLVM from source (the default), you'll need additional tools: -* `g++` 5.1 or later, `clang++` 3.5 or later, or MSVC 2017 or later. +* `g++`, `clang++`, or MSVC with versions listed on <!-- date-check: Aug 2022 --> + [LLVM's documentation](https://releases.llvm.org/13.0.0/docs/GettingStarted.html#host-c-toolchain-both-compiler-and-standard-library) * `ninja`, or GNU `make` 3.81 or later (ninja is recommended, especially on Windows) * `cmake` 3.13.4 or later diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 1c2229335..3e077977d 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -22,7 +22,7 @@ You can also install the hook as a step of running `./x.py setup`! a file. By default, `rust-analyzer` runs the `cargo check` and `rustfmt` commands, but you can override these commands to use more adapted versions of these tools when hacking on `rustc`. For example, for Visual Studio Code, -you can write: <!-- date: 2022-04 --><!-- the date comment is for the edition below --> +you can write: <!-- date-check: apr 2022 --><!-- the date comment is for the edition below --> ```JSON { diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index 8f46e896e..35458b55c 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -16,9 +16,36 @@ set `debug = true` in your config.toml. Setting `debug = true` turns on many different debug options (e.g., `debug-assertions`, `debug-logging`, etc.) which can be individually tweaked if you want to, but many people -simply set `debug = true`. Check out the comments in config.toml.example for more info. +simply set `debug = true`. -You will need to rebuild the compiler once you've changed any configuration options. +If you want to use GDB to debug rustc, please set `config.toml` with options: + +```toml +[rust] +debug = true +debuginfo-level = 2 +``` + +> NOTE: +> This will use a lot of disk space +> (upwards of <!-- date-check Aug 2022 --> 35GB), +> and will take a lot more compile time. +> With `debuginfo-level = 1` (the default when `debug = true`), +> you will be able to track the execution path, +> but will lose the symbol information for debugging. + +The default configuration will enable `symbol-mangling-version` v0. +This requires at least GDB v10.2, +otherwise you need to disable new symbol-mangling-version in `config.toml`. + +```toml +[rust] +new-symbol-mangling = false +``` + +> See the comments in `config.toml.example` for more info. + +You will need to rebuild the compiler after changing any configuration option. ## `-Z` flags diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 45f8c9033..e59bb0a77 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -437,17 +437,35 @@ Just a few things to keep in mind: the project. - The date the comment was added, e.g. instead of writing _"Currently, ..."_ - or _"As of now, ..."_, consider writing - _"As of January 2021, ..."_. - Try to format the date as `<MONTH> <YEAR>` to ease search. + or _"As of now, ..."_, + consider adding the date, in one of the following formats: + - Jan 2021 + - January 2021 + - jan 2021 + - january 2021 - - Additionally, include a machine-readable comment of the form `<!-- date: - 2022-04 -->` (if the current month is April 2022). We have an automated - tool that uses these (in `ci/date-check`). + There is a CI action (in `~/.github/workflows/date-check.yml`) + that generates a monthly issue with any of these that are over 6 months old. - So, for the month of April 2022, the comment would look like: `As of <!-- - date: 2022-04 --> April 2022`. Make sure to put the comment *between* `as of` - and `April 2022`; see [PR #1066][rdg#1066] for the rationale. + For the action to pick the date, + add a special annotation before specifying the date: + + ```md + <!-- date-check --> Jul 2022 + ``` + + Example: + + ```md + As of <!-- date-check --> Jul 2022, the foo did the bar. + ``` + + For cases where the date should not be part of the visible rendered output, + use the following instead: + + ```md + <!-- date-check: Jul 2022 --> + ``` - A link to a relevant WG, tracking issue, `rustc` rustdoc page, or similar, that may provide further explanation for the change process or a way to verify that the information is not @@ -459,7 +477,6 @@ Just a few things to keep in mind: [rdg]: https://rustc-dev-guide.rust-lang.org/ [rdgrepo]: https://github.com/rust-lang/rustc-dev-guide -[rdg#1066]: https://github.com/rust-lang/rustc-dev-guide/pull/1066 ## Issue Triage diff --git a/src/doc/rustc-dev-guide/src/conventions.md b/src/doc/rustc-dev-guide/src/conventions.md index 15d125377..0d5f17b99 100644 --- a/src/doc/rustc-dev-guide/src/conventions.md +++ b/src/doc/rustc-dev-guide/src/conventions.md @@ -14,14 +14,14 @@ special config, so this may result in different style from normal [`rustfmt`]. Therefore, formatting this repository using `cargo fmt` is not recommended. Instead, formatting should be done using `./x.py fmt`. It's a good habit to run -`./x.py fmt` before every commit, as this reduces conflicts later. +`./x.py fmt` before every commit, as this reduces conflicts later. Formatting is checked by the `tidy` script. It runs automatically when you do `./x.py test` and can be run in isolation with `./x.py fmt --check`. If you want to use format-on-save in your editor, the pinned version of `rustfmt` is built under `build/<target>/stage0/bin/rustfmt`. You'll have to -pass the <!-- date: 2022-04 --> `--edition=2021` argument yourself when calling +pass the <!-- date-check: April 2022 --> `--edition=2021` argument yourself when calling `rustfmt` directly. [fmt]: https://github.com/rust-dev-tools/fmt-rfcs diff --git a/src/doc/rustc-dev-guide/src/crates-io.md b/src/doc/rustc-dev-guide/src/crates-io.md index 8c8fd0c38..f012c5bb5 100644 --- a/src/doc/rustc-dev-guide/src/crates-io.md +++ b/src/doc/rustc-dev-guide/src/crates-io.md @@ -1,20 +1,20 @@ # crates.io Dependencies The Rust compiler supports building with some dependencies from `crates.io`. -For example, `log` and `env_logger` come from `crates.io`. +Examples are `log` and `env_logger`. -In general, you should avoid adding dependencies to the compiler for several -reasons: +In general, +you should avoid adding dependencies to the compiler for several reasons: -- The dependency may not be high quality or well-maintained, whereas we want - the compiler to be high-quality. +- The dependency may not be of high quality or well-maintained. - The dependency may not be using a compatible license. - The dependency may have transitive dependencies that have one of the above problems. -As of <!-- date: 2022-02 --> February 2022, there is no official policy for vetting -new dependencies to the compiler. Generally, new dependencies are not added -to the compiler unless there is a good reason to do so. +As of <!-- date-check --> Aug 2022, +there is no official policy for vetting new dependencies to the compiler. +Decisions are made on a case-by-case basis, +during code review. ## Permitted dependencies diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md index b6b6e0fa9..dcaba533e 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md @@ -1,4 +1,5 @@ # Diagnostic Items + While writing lints it's common to check for specific types, traits and functions. This raises the question on how to check for these. Types can be checked by their complete type path. However, this requires hard coding paths @@ -7,7 +8,8 @@ rustc has introduced diagnostic items that are used to identify types via [`Symbol`]s. ## Finding diagnostic items -Diagnostic items are added to items inside `rustc`/`std`/`core` with the + +Diagnostic items are added to items inside `rustc`/`std`/`core`/`alloc` with the `rustc_diagnostic_item` attribute. The item for a specific type can be found by opening the source code in the documentation and looking for this attribute. Note that it's often added with the `cfg_attr` attribute to avoid compilation @@ -19,12 +21,15 @@ errors during tests. A definition often looks like this: struct Penguin; ``` -Diagnostic items are usually only added to traits, types and standalone -functions. If the goal is to check for an associated type or method, please use -the diagnostic item of the item and reference [*How To Use Diagnostic -Items*](#how-to-use-diagnostic-items). +Diagnostic items are usually only added to traits, +types, +and standalone functions. +If the goal is to check for an associated type or method, +please use the diagnostic item of the item and reference +[*Using Diagnostic Items*](#using-diagnostic-items). ## Adding diagnostic items + A new diagnostic item can be added with these two steps: 1. Find the target item inside the Rust repo. Now add the diagnostic item as a @@ -43,45 +48,55 @@ A new diagnostic item can be added with these two steps: For the naming conventions of diagnostic items, please refer to [*Naming Conventions*](#naming-conventions). -2. As of <!-- date: 2022-02 --> February 2022, diagnostic items in code are - accessed via symbols in [`rustc_span::symbol::sym`]. To add your newly - created diagnostic item simply open the module file and add the name (In - this case `Cat`) at the correct point in the list. +2. <!-- date-check: Aug 2022 --> + Diagnostic items in code are accessed via symbols in + [`rustc_span::symbol::sym`]. + To add your newly-created diagnostic item, + simply open the module file, + and add the name (In this case `Cat`) at the correct point in the list. -Now you can create a pull request with your changes. :tada: (Note that when -using diagnostic items in other projects like Clippy, it might take some time -until the repos get synchronized.) +Now you can create a pull request with your changes. :tada: + +> NOTE: +> When using diagnostic items in other projects like Clippy, +> it might take some time until the repos get synchronized. ## Naming conventions -Diagnostic items don't have a set in stone naming convention yet. These are -some guidelines that should be used for the future, but might differ from -existing names: - -* Types, traits and enums are named using UpperCamelCase (Examples: `Iterator`, -* `HashMap`, ...) -* For type names that are used multiple times like `Writer` it's good to choose - a more precise name, maybe by adding the module to it. (Example: `IoWriter`) -* Associated items should not get their own diagnostic items, but instead be - accessed indirectly by the diagnostic item of the type they're originating - from. + +Diagnostic items don't have a naming convention yet. +Following are some guidelines that should be used in future, +but might differ from existing names: + +* Types, traits, and enums are named using UpperCamelCase + (Examples: `Iterator` and `HashMap`) +* For type names that are used multiple times, + like `Writer`, + it's good to choose a more precise name, + maybe by adding the module to it + (Example: `IoWriter`) +* Associated items should not get their own diagnostic items, + but instead be accessed indirectly by the diagnostic item + of the type they're originating from. * Freestanding functions like `std::mem::swap()` should be named using - `snake_case` with one important (export) module as a prefix (Example: - `mem_swap`, `cmp_max`) + `snake_case` with one important (export) module as a prefix + (Examples: `mem_swap` and `cmp_max`) * Modules should usually not have a diagnostic item attached to them. - Diagnostic items were added to avoid the usage of paths, using them on - modules would therefore most likely to be counterproductive. + Diagnostic items were added to avoid the usage of paths, + and using them on modules would therefore most likely be counterproductive. ## Using diagnostic items + In rustc, diagnostic items are looked up via [`Symbol`]s from inside the [`rustc_span::symbol::sym`] module. These can then be mapped to [`DefId`]s using [`TyCtxt::get_diagnostic_item()`] or checked if they match a [`DefId`] using [`TyCtxt::is_diagnostic_item()`]. When mapping from a diagnostic item to a [`DefId`], the method will return a `Option<DefId>`. This can be `None` if either the symbol isn't a diagnostic item or the type is not registered, for -instance when compiling with `#[no_std]`. All following examples are based on -[`DefId`]s and their usage. +instance when compiling with `#[no_std]`. +All the following examples are based on [`DefId`]s and their usage. ### Example: Checking for a type + ```rust use rustc_span::symbol::sym; @@ -96,6 +111,7 @@ fn example_1(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { ``` ### Example: Checking for a trait implementation + ```rust /// This example checks if a given [`DefId`] from a method is part of a trait /// implementation defined by a diagnostic item. @@ -112,6 +128,7 @@ fn is_diag_trait_item( ``` ### Associated Types + Associated types of diagnostic items can be accessed indirectly by first getting the [`DefId`] of the trait and then calling [`TyCtxt::associated_items()`]. This returns an [`AssocItems`] object which can @@ -119,13 +136,15 @@ be used for further checks. Checkout [`clippy_utils::ty::get_iterator_item_ty()`] for an example usage of this. ### Usage in Clippy + Clippy tries to use diagnostic items where possible and has developed some wrapper and utility functions. Please also refer to its documentation when using diagnostic items in Clippy. (See [*Common tools for writing lints*][clippy-Common-tools-for-writing-lints].) ## Related issues -This lists some related issues. These are probably only interesting to people + +These are probably only interesting to people who really want to take a deep dive into the topic :) * [rust#60966]: The Rust PR that introduced diagnostic items diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md index f28350e03..f456474c7 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -17,45 +17,43 @@ shown below: ```rust,ignore #[derive(SessionDiagnostic)] -#[error(typeck::field_already_declared, code = "E0124")] +#[diag(typeck::field_already_declared, code = "E0124")] pub struct FieldAlreadyDeclared { pub field_name: Ident, #[primary_span] #[label] pub span: Span, - #[label = "previous-decl-label"] + #[label(typeck::previous_decl_label)] pub prev_span: Span, } ``` `SessionDiagnostic` can only be applied to structs. Every `SessionDiagnostic` -has to have one attribute applied to the struct itself: either `#[error(..)]` -for defining errors, or `#[warning(..)]` for defining warnings. +has to have one attribute, `#[diag(...)]`, applied to the struct itself. If an error has an error code (e.g. "E0624"), then that can be specified using the `code` sub-attribute. Specifying a `code` isn't mandatory, but if you are porting a diagnostic that uses `DiagnosticBuilder` to use `SessionDiagnostic` then you should keep the code if there was one. -Both `#[error(..)]` and `#[warning(..)]` must provide a slug as the first -positional argument (a path to an item in `rustc_errors::fluent::*`). A slug -uniquely identifies the diagnostic and is also how the compiler knows what -error message to emit (in the default locale of the compiler, or in the locale -requested by the user). See [translation documentation](./translation.md) to -learn more about how translatable error messages are written and how slug -items are generated. +`#[diag(..)]` must provide a slug as the first positional argument (a path to an +item in `rustc_errors::fluent::*`). A slug uniquely identifies the diagnostic +and is also how the compiler knows what error message to emit (in the default +locale of the compiler, or in the locale requested by the user). See +[translation documentation](./translation.md) to learn more about how +translatable error messages are written and how slug items are generated. In our example, the Fluent message for the "field already declared" diagnostic looks like this: ```fluent -typeck-field-already-declared = +typeck_field_already_declared = field `{$field_name}` is already declared .label = field already declared - .previous-decl-label = `{$field_name}` first declared here + .previous_decl_label = `{$field_name}` first declared here ``` -`typeck-field-already-declared` is the slug from our example and is followed +`typeck_field_already_declared` is the slug from our example and is followed by the diagnostic message. Every field of the `SessionDiagnostic` which does not have an annotation is @@ -75,10 +73,10 @@ type `Span`. Applying any of these attributes will create the corresponding subdiagnostic with that `Span`. These attributes will look for their diagnostic message in a Fluent attribute attached to the primary Fluent message. In our example, `#[label]` will look for -`typeck-field-already-declared.label` (which has the message "field already +`typeck_field_already_declared.label` (which has the message "field already declared"). If there is more than one subdiagnostic of the same type, then these attributes can also take a value that is the attribute name to look for -(e.g. `previous-decl-label` in our example). +(e.g. `previous_decl_label` in our example). Other types have special behavior when used in a `SessionDiagnostic` derive: @@ -95,38 +93,35 @@ represent optional `#[note]`/`#[help]` subdiagnostics. Suggestions can be emitted using one of four field attributes: -- `#[suggestion(message = "...", code = "...", applicability = "...")]` -- `#[suggestion_hidden(message = "...", code = "...", applicability = "...")]` -- `#[suggestion_short(message = "...", code = "...", applicability = "...")]` -- `#[suggestion_verbose(message = "...", code = "...", applicability = "...")]` +- `#[suggestion(slug, code = "...", applicability = "...")]` +- `#[suggestion_hidden(slug, code = "...", applicability = "...")]` +- `#[suggestion_short(slug, code = "...", applicability = "...")]` +- `#[suggestion_verbose(slug, code = "...", applicability = "...")]` Suggestions must be applied on either a `Span` field or a `(Span, -MachineApplicability)` field. Similarly to other field attributes, `message` -specifies the Fluent attribute with the message and defaults to `.suggestion`. -`code` specifies the code that should be suggested as a replacement and is a -format string (e.g. `{field_name}` would be replaced by the value of the -`field_name` field of the struct), not a Fluent identifier. `applicability` can -be used to specify the applicability in the attribute, it cannot be used when -the field's type contains an `Applicability`. +MachineApplicability)` field. Similarly to other field attributes, the slug +specifies the Fluent attribute with the message and defaults to the equivalent +of `.suggestion`. `code` specifies the code that should be suggested as a +replacement and is a format string (e.g. `{field_name}` would be replaced by +the value of the `field_name` field of the struct), not a Fluent identifier. +`applicability` can be used to specify the applicability in the attribute, it +cannot be used when the field's type contains an `Applicability`. In the end, the `SessionDiagnostic` derive will generate an implementation of `SessionDiagnostic` that looks like the following: ```rust,ignore -impl SessionDiagnostic for FieldAlreadyDeclared { +impl SessionDiagnostic<'_> for FieldAlreadyDeclared { fn into_diagnostic(self, sess: &'_ rustc_session::Session) -> DiagnosticBuilder<'_> { - let mut diag = sess.struct_err_with_code( - rustc_errors::DiagnosticMessage::fluent("typeck-field-already-declared"), - rustc_errors::DiagnosticId::Error("E0124") - ); + let mut diag = sess.struct_err(rustc_errors::fluent::typeck::field_already_declared); diag.set_span(self.span); diag.span_label( self.span, - rustc_errors::DiagnosticMessage::fluent_attr("typeck-field-already-declared", "label") + rustc_errors::fluent::typeck::label ); diag.span_label( self.prev_span, - rustc_errors::DiagnosticMessage::fluent_attr("typeck-field-already-declared", "previous-decl-label") + rustc_errors::fluent::typeck::previous_decl_label ); diag } @@ -146,12 +141,13 @@ tcx.sess.emit_err(FieldAlreadyDeclared { ``` ### Reference -`#[derive(SessionDiagnostic)]` supports the following attributes: +`#[derive(SessionDiagnostic)]` and `#[derive(LintDiagnostic)]` support the +following attributes: -- `#[error(slug, code = "...")]` or `#[warning(slug, code = "...")]` +- `#[diag(slug, code = "...")]` - _Applied to struct._ - _Mandatory_ - - Defines the struct to be representing an error or a warning. + - Defines the text and error code to be associated with the diagnostic. - Slug (_Mandatory_) - Uniquely identifies the diagnostic and corresponds to its Fluent message, mandatory. @@ -164,34 +160,48 @@ tcx.sess.emit_err(FieldAlreadyDeclared { - See [translation documentation](./translation.md). - `code = "..."` (_Optional_) - Specifies the error code. -- `#[note]` or `#[note = "..."]` (_Optional_) +- `#[note]` or `#[note(slug)]` (_Optional_) - _Applied to struct or `Span`/`()` fields._ - Adds a note subdiagnostic. - - Value is the Fluent attribute (relative to the Fluent message specified by - `slug`) for the note's message - - Defaults to `note`. + - Value is a path to an item in `rustc_errors::fluent` for the note's + message. + - Defaults to equivalent of `.note`. - If applied to a `Span` field, creates a spanned note. -- `#[help]` or `#[help = "..."]` (_Optional_) +- `#[help]` or `#[help(slug)]` (_Optional_) - _Applied to struct or `Span`/`()` fields._ - Adds a help subdiagnostic. - - Value is the Fluent attribute (relative to the Fluent message specified by - `slug`) for the help's message. - - Defaults to `help`. + - Value is a path to an item in `rustc_errors::fluent` for the note's + message. + - Defaults to equivalent of `.help`. - If applied to a `Span` field, creates a spanned help. -- `#[label]` or `#[label = "..."]` (_Optional_) +- `#[label]` or `#[label(slug)]` (_Optional_) - _Applied to `Span` fields._ - Adds a label subdiagnostic. - - Value is the Fluent attribute (relative to the Fluent message specified by - `slug`) for the label's message. - - Defaults to `label`. -- `#[suggestion{,_hidden,_short,_verbose}(message = "...", code = "...", applicability = "...")]` + - Value is a path to an item in `rustc_errors::fluent` for the note's + message. + - Defaults to equivalent of `.label`. +- `#[warn_]` or `#[warn_(slug)]` (_Optional_) + - _Applied to `Span` fields._ + - Adds a warning subdiagnostic. + - Value is a path to an item in `rustc_errors::fluent` for the note's + message. + - Defaults to equivalent of `.warn`. +- `#[suggestion{,_hidden,_short,_verbose}(slug, code = "...", applicability = "...")]` (_Optional_) - _Applied to `(Span, MachineApplicability)` or `Span` fields._ - Adds a suggestion subdiagnostic. - - `message = "..."` (_Mandatory_) - - Value is the Fluent attribute (relative to the Fluent message specified - by `slug`) for the suggestion's message. - - Defaults to `suggestion`. + - Slug (_Mandatory_) + - A path to an item in `rustc_errors::fluent`. Always in a module starting + with a Fluent resource name (which is typically the name of the crate + that the diagnostic is from), e.g. + `rustc_errors::fluent::typeck::field_already_declared` + (`rustc_errors::fluent` is implicit in the attribute, so just + `typeck::field_already_declared`). Fluent attributes for all messages + exist as top-level items in that module (so `typeck_message.attr` is just + `typeck::attr`). + - See [translation documentation](./translation.md). + - Defaults to `rustc_errors::fluent::_subdiag::suggestion` (or + - `.suggestion` in Fluent). - `code = "..."` (_Mandatory_) - Value is a format string indicating the code to be suggested as a replacement. @@ -203,7 +213,7 @@ tcx.sess.emit_err(FieldAlreadyDeclared { `#[derive(SessionSubdiagnostic)]`)._ - Adds the subdiagnostic represented by the subdiagnostic struct. - `#[primary_span]` (_Optional_) - - _Applied to `Span` fields._ + - _Applied to `Span` fields on `SessionSubdiagnostic`s. Not used for `LintDiagnostic`s._ - Indicates the primary span of the diagnostic. - `#[skip_arg]` (_Optional_) - _Applied to any field._ @@ -258,9 +268,9 @@ In our example, the Fluent message for the "expected return type" label looks like this: ```fluent -typeck-expected-default-return-type = expected `()` because of default return type +typeck_expected_default_return_type = expected `()` because of default return type -typeck-expected-return-type = expected `{$expected}` because of return type +typeck_expected_return_type = expected `{$expected}` because of return type ``` Using the `#[primary_span]` attribute on a field (with type `Span`) will denote @@ -276,16 +286,17 @@ Like `SessionDiagnostic`, `SessionSubdiagnostic` supports `Option<T>` and Suggestions can be emitted using one of four attributes on the type/variant: -- `#[suggestion(message = "...", code = "...", applicability = "...")]` -- `#[suggestion_hidden(message = "...", code = "...", applicability = "...")]` -- `#[suggestion_short(message = "...", code = "...", applicability = "...")]` -- `#[suggestion_verbose(message = "...", code = "...", applicability = "...")]` +- `#[suggestion(..., code = "...", applicability = "...")]` +- `#[suggestion_hidden(..., code = "...", applicability = "...")]` +- `#[suggestion_short(..., code = "...", applicability = "...")]` +- `#[suggestion_verbose(..., code = "...", applicability = "...")]` Suggestions require `#[primary_span]` be set on a field and can have the following sub-attributes: -- `message` specifies the Fluent attribute with the message and defaults to - `.suggestion`. +- The first positional argument specifies the path to a item in + `rustc_errors::fluent` corresponding to the Fluent attribute with the message + and defaults to the equivalent of `.suggestion`. - `code` specifies the code that should be suggested as a replacement and is a format string (e.g. `{field_name}` would be replaced by the value of the `field_name` field of the struct), not a Fluent identifier. @@ -304,11 +315,11 @@ impl<'tcx> AddToDiagnostic for ExpectedReturnTypeLabel<'tcx> { use rustc_errors::{Applicability, IntoDiagnosticArg}; match self { ExpectedReturnTypeLabel::Unit { span } => { - diag.span_label(span, DiagnosticMessage::fluent("typeck-expected-default-return-type")) + diag.span_label(span, rustc_errors::fluent::typeck::expected_default_return_type) } ExpectedReturnTypeLabel::Other { span, expected } => { diag.set_arg("expected", expected); - diag.span_label(span, DiagnosticMessage::fluent("typeck-expected-return-type")) + diag.span_label(span, rustc_errors::fluent::typeck::expected_return_type) } } @@ -338,14 +349,22 @@ diagnostic struct. (`rustc_errors::fluent` is implicit in the attribute, so just `typeck::field_already_declared`). - See [translation documentation](./translation.md). -- `#[suggestion{,_hidden,_short,_verbose}(message = "...", code = "...", applicability = "...")]` +- `#[suggestion{,_hidden,_short,_verbose}(slug, code = "...", applicability = "...")]` - _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._ - _Mandatory_ - Defines the type to be representing a suggestion. - - `message = "..."` (_Mandatory_) - - Value is the Fluent attribute (relative to the Fluent message specified - by `slug`) for the suggestion's message. - - Defaults to `suggestion`. + - Slug (_Mandatory_) + - A path to an item in `rustc_errors::fluent`. Always in a module starting + with a Fluent resource name (which is typically the name of the crate + that the diagnostic is from), e.g. + `rustc_errors::fluent::typeck::field_already_declared` + (`rustc_errors::fluent` is implicit in the attribute, so just + `typeck::field_already_declared`). Fluent attributes for all messages + exist as top-level items in that module (so `typeck_message.attr` is just + `typeck::attr`). + - See [translation documentation](./translation.md). + - Defaults to `rustc_errors::fluent::_subdiag::suggestion` (or + - `.suggestion` in Fluent). - `code = "..."` (_Mandatory_) - Value is a format string indicating the code to be suggested as a replacement. diff --git a/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md b/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md index 39007f8d1..33d9646f6 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md @@ -1,4 +1,5 @@ # Lints + This page documents some of the machinery around lint registration and how we run lints in the compiler. @@ -8,6 +9,7 @@ everything rotates. It's not available during the early parts of compilation lints, which can only happen after plugin registration. ## Lints vs. lint passes + There are two parts to the linting mechanism within the compiler: lints and lint passes. Unfortunately, a lot of the documentation we have refers to both of these as just "lints." @@ -15,11 +17,18 @@ of these as just "lints." First, we have the lint declarations themselves: this is where the name and default lint level and other metadata come from. These are normally defined by way of the [`declare_lint!`] macro, which boils down to a static with type -`&rustc_session::lint::Lint`. +[`&rustc_lint_defs::Lint`]. + +First, we have the lint declarations themselves, +and this is where the name and default lint level and other metadata come from. +These are normally defined by way of the [`declare_lint!`] macro, +which boils down to a static with type [`&rustc_lint_defs::Lint`] +(although this may change in the future, +as the macro is somewhat unwieldy to add new fields to, +like all macros). -As of <!-- date: 2022-02 --> February 2022, we lint against direct declarations -without the use of the macro today (although this may change in the future, as -the macro is somewhat unwieldy to add new fields to, like all macros). +As of <!-- date-check --> Aug 2022, +we lint against direct declarations without the use of the macro. Lint declarations don't carry any "state" - they are merely global identifiers and descriptions of lints. We assert at runtime that they are not registered @@ -34,8 +43,10 @@ lints are emitted as part of other work (e.g., type checking, etc.). ## Registration ### High-level overview -In [`rustc_interface::register_plugins`] the [`LintStore`] is created and all -lints are registered. + +In [`rustc_interface::register_plugins`], +the [`LintStore`] is created, +and all lints are registered. There are four 'sources' of lints: @@ -61,6 +72,7 @@ then invoke the lint pass methods. The lint pass methods take `&mut self` so they can keep track of state internally. #### Internal lints + These are lints used just by the compiler or plugins like `clippy`. They can be found in `rustc_lint::internal`. @@ -73,16 +85,20 @@ function which is called when constructing a new lint store inside [`rustc_lint::new_lint_store`]. ### Builtin Lints -These are primarily described in two places: `rustc_session::lint::builtin` and -`rustc_lint::builtin`. Often the first provides the definitions for the lints -themselves, and the latter provides the lint pass definitions (and -implementations), but this is not always true. -The builtin lint registration happens in the [`rustc_lint::register_builtins`] -function. Just like with internal lints, this happens inside of -[`rustc_lint::new_lint_store`]. +These are primarily described in two places, +`rustc_lint_defs::builtin` and `rustc_lint::builtin`. +Often the first provides the definitions for the lints themselves, +and the latter provides the lint pass definitions (and implementations), +but this is not always true. + +The builtin lint registration happens in +the [`rustc_lint::register_builtins`] function. +Just like with internal lints, +this happens inside of [`rustc_lint::new_lint_store`]. #### Plugin lints + This is one of the primary use cases remaining for plugins/drivers. Plugins are given access to the mutable `LintStore` during registration (which happens inside of [`rustc_interface::register_plugins`]) and they can call any @@ -94,6 +110,7 @@ diagnostics and help text; otherwise plugin lints are mostly just as first class as rustc builtin lints. #### Driver lints + These are the lints provided by drivers via the `rustc_interface::Config` [`register_lints`] field, which is a callback. Drivers should, if finding it already set, call the function currently set within the callback they add. The @@ -102,6 +119,7 @@ best way for drivers to get access to this is by overriding the structure. ## Compiler lint passes are combined into one pass + Within the compiler, for performance reasons, we usually do not register dozens of lint passes. Instead, we have a single lint pass of each variety (e.g., `BuiltinCombinedModuleLateLintPass`) which will internally call all of the @@ -121,3 +139,4 @@ approach, it is beneficial to do so for performance reasons. [`declare_lint!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.declare_lint.html [`declare_tool_lint!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.declare_tool_lint.html [`register_lints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Config.html#structfield.register_lints +[`&rustc_lint_defs::Lint`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/struct.Lint.html diff --git a/src/doc/rustc-dev-guide/src/diagnostics/translation.md b/src/doc/rustc-dev-guide/src/diagnostics/translation.md index 5c078ffb3..5bb37fbc2 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/translation.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/translation.md @@ -32,23 +32,23 @@ Diagnostic messages are defined in Fluent resources. A combined set of Fluent resources for a given locale (e.g. `en-US`) is known as Fluent bundle. ```fluent -typeck-address-of-temporary-taken = cannot take address of a temporary +typeck_address_of_temporary_taken = cannot take address of a temporary ``` -In the above example, `typeck-address-of-temporary-taken` is the identifier for +In the above example, `typeck_address_of_temporary_taken` is the identifier for a Fluent message and corresponds to the diagnostic message in English. Other Fluent resources can be written which would correspond to a message in another language. Each diagnostic therefore has at least one Fluent message. ```fluent -typeck-address-of-temporary-taken = cannot take address of a temporary +typeck_address_of_temporary_taken = cannot take address of a temporary .label = temporary value ``` By convention, diagnostic messages for subdiagnostics are specified as "attributes" on Fluent messages (additional related messages, denoted by the `.<attribute-name>` syntax). In the above example, `label` is an attribute of -`typeck-address-of-temporary-taken` which corresponds to the message for the +`typeck_address_of_temporary_taken` which corresponds to the message for the label added to this diagnostic. Diagnostic messages often interpolate additional context into the message shown @@ -56,7 +56,7 @@ to the user, such as the name of a type or of a variable. Additional context to Fluent messages is provided as an "argument" to the diagnostic. ```fluent -typeck-struct-expr-non-exhaustive = +typeck_struct_expr_non_exhaustive = cannot create non-exhaustive {$what} using struct expression ``` @@ -67,6 +67,13 @@ discussed in detail later). You can consult the [Fluent] documentation for other usage examples of Fluent and its syntax. +### Guideline for message naming +Usually, fluent uses `-` for separating words inside a message name. However, +`_` is accepted by fluent as well. As `_` fits Rust's use cases better, due to +the identifiers on the Rust side using `_` as well, inside rustc, `-` is not +allowed for separating words, and instead `_` is recommended. The only exception +is for leading `-`s, for message names like `-passes_see_issue`. + ### Guidelines for writing translatable messages For a message to be translatable into different languages, all of the information required by any language must be provided to the diagnostic as an @@ -106,10 +113,10 @@ fluent_messages! { For example, given the following Fluent... ```fluent -typeck-field-multiply-specified-in-initializer = +typeck_field_multiply_specified_in_initializer = field `{$ident}` specified more than once .label = used more than once - .label-previous-use = first use of `{$ident}` + .label_previous_use = first use of `{$ident}` ``` ...then the `fluent_messages` macro will generate: @@ -122,11 +129,11 @@ pub static DEFAULT_LOCALE_RESOURCES: &'static [&'static str] = &[ mod fluent_generated { mod typeck { pub const field_multiply_specified_in_initializer: DiagnosticMessage = - DiagnosticMessage::new("typeck-field-multiply-specified-in-initializer"); + DiagnosticMessage::new("typeck_field_multiply_specified_in_initializer"); pub const label: SubdiagnosticMessage = SubdiagnosticMessage::attr("label"); pub const label_previous_use: SubdiagnosticMessage = - SubdiagnosticMessage::attr("previous-use-label"); + SubdiagnosticMessage::attr("previous_use_label"); } } ``` @@ -217,7 +224,7 @@ returned by `Emitter::fluent_bundle`. This bundle is used preferentially when translating messages, the fallback bundle is only used if the primary bundle is missing a message or not provided. -As of <!-- date: 2022-06 --> June 2022, there are no locale bundles +As of <!-- date-check --> June 2022, there are no locale bundles distributed with the compiler, but mechanisms are implemented for loading bundles. diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index f16c22d93..5899753ba 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -157,9 +157,12 @@ no changes added to commit (use "git add" and/or "git commit -a") These changes are not changes to files: they are changes to submodules (more on this [later](#git-submodules)). To get rid of those, run `git submodule update` (or run any `x.py` command, which will automatically update the submodules). -Note that there is (as of <!-- date: 2022-02 --> February 2022) a [bug][#77620] if you use -worktrees, submodules, and `x.py` in a commit hook. If you run into an error -like: +Note that, +as of <!-- date-check --> Aug 2022, +there is a [bug][#77620] if you use worktrees, +submodules, and `x.py` in a commit hook. +If you run into an error like the following, +it's not anything you did wrong: ``` error: failed to read `/home/joshua/rustc-worktree/src/tools/miri/cargo-miri/Cargo.toml` @@ -167,7 +170,8 @@ error: failed to read `/home/joshua/rustc-worktree/src/tools/miri/cargo-miri/Car Caused by: No such file or directory (os error 2) ``` -it's not anything you did wrong. There is a workaround in [the issue][#77620-workaround]. + +There is a workaround in [the issue][#77620-workaround]. [#77620]: https://github.com/rust-lang/rust/issues/77620 [#77620-workaround]: https://github.com/rust-lang/rust/issues/77620#issuecomment-705228229 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 ea4bdfca6..b186f4820 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -222,9 +222,10 @@ properly-configured variables in LLVM IR, according to very specific 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: 2021-12 --> -December 2021) supports _LLVM Coverage Mapping Format_ Version 5 or 6. Version 5 -was introduced in _LLVM 12_, which is (as of this writing) the minimum LLVM +[^llvm-and-covmap-versions]: The Rust compiler (as of <!-- date-check --> December 2021) +supports _LLVM Coverage Mapping Format_ Version 5 or 6. Version 5 +was introduced in _LLVM 12_, +which is (as of <!-- date-check: December 2021--> this writing) the minimum LLVM version supported by the current version of Rust. Version 6 was introduced in _LLVM 13_, which is currently the default LLVM version for Rust. The Rust compiler will automatically use the most up-to-date coverage mapping format diff --git a/src/doc/rustc-dev-guide/src/opaque-types-type-alias-impl-trait.md b/src/doc/rustc-dev-guide/src/opaque-types-type-alias-impl-trait.md index 2be072dd2..956f56828 100644 --- a/src/doc/rustc-dev-guide/src/opaque-types-type-alias-impl-trait.md +++ b/src/doc/rustc-dev-guide/src/opaque-types-type-alias-impl-trait.md @@ -14,9 +14,9 @@ This declares an opaque type named `Foo`, of which the only information is that it implements `Bar`. Therefore, any of `Bar`'s interface can be used on a `Foo`, but nothing else (regardless of whether it implements any other traits). -Since there needs to be a concrete background type, you can (as of <!-- date: -2021-01 --> January 2021) express that type by using the opaque type in a -"defining use site". +Since there needs to be a concrete background type, +you can (as of <!-- date-check --> January 2021) express that type +by using the opaque type in a "defining use site". ```rust,ignore struct Struct; diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md index de6c88e7e..c7da92542 100644 --- a/src/doc/rustc-dev-guide/src/overview.md +++ b/src/doc/rustc-dev-guide/src/overview.md @@ -292,7 +292,7 @@ Moreover, the compiler wasn't originally built to use a query system; the query system has been retrofitted into the compiler, so parts of it are not query-fied yet. Also, LLVM isn't our code, so that isn't querified either. The plan is to eventually query-fy all of the steps listed in the previous section, -but as of <!-- date: 2021-11 --> November 2021, only the steps between HIR and +but as of <!-- date-check --> November 2021, only the steps between HIR and LLVM IR are query-fied. That is, lexing, parsing, name resolution, and macro expansion are done all at once for the whole program. diff --git a/src/doc/rustc-dev-guide/src/parallel-rustc.md b/src/doc/rustc-dev-guide/src/parallel-rustc.md index 4aa13d781..e93f51dbb 100644 --- a/src/doc/rustc-dev-guide/src/parallel-rustc.md +++ b/src/doc/rustc-dev-guide/src/parallel-rustc.md @@ -1,34 +1,116 @@ # Parallel Compilation -As of <!-- date: 2022-05 --> May 2022, The only stage of the compiler -that is already parallel is codegen. The nightly compiler implements query evaluation, -but there is still a lot of work to be done. The lack of parallelism at other stages -also represents an opportunity for improving compiler performance. One can try out the current -parallel compiler work by enabling it in the `config.toml`. +As of <!-- date-check --> August 2022, the only stage of the compiler that +is already parallel is codegen. Some parts of the compiler already have +parallel implementations, such as query evaluation, type check and +monomorphization, but the general version of the compiler does not include +these parallelization functions. **To try out the current parallel compiler**, +one can install rustc from source code with `parallel-compiler = true` in +the `config.toml`. + +The lack of parallelism at other stages (for example, macro expansion) also +represents an opportunity for improving compiler performance. These next few sections describe where and how parallelism is currently used, and the current status of making parallel compilation the default in `rustc`. -The underlying thread-safe data-structures used in the parallel compiler -can be found in the `rustc_data_structures::sync` module. Some of these data structures -use the `parking_lot` crate as well. - ## Codegen -There are two underlying thread safe data structures used in code generation: - -- `Lrc` - - Which is an [`Arc`][Arc] if `parallel_compiler` is true, and a [`Rc`][Rc] - if it is not. -- `MetadataRef` -> [`OwningRef<Box<dyn Erased + Send + Sync>, [u8]>`][OwningRef] - - This data structure is specific to `rustc`. - During [monomorphization][monomorphization] the compiler splits up all the code to be generated into smaller chunks called _codegen units_. These are then generated by independent instances of LLVM running in parallel. At the end, the linker is run to combine all the codegen units together into one binary. This process occurs in the `rustc_codegen_ssa::base` module. +## Data Structures + +The underlying thread-safe data-structures used in the parallel compiler +can be found in the `rustc_data_structures::sync` module. These data structures +are implemented diferently depending on whether `parallel-compiler` is true. + +| data structure | parallel | non-parallel | +| -------------------------------- | --------------------------------------------------- | ------------ | +| Lrc | std::sync::Arc | std::rc::Rc | +| Weak | std::sync::Weak | std::rc::Weak | +| Atomic{Bool}/{Usize}/{U32}/{U64} | std::sync::atomic::Atomic{Bool}/{Usize}/{U32}/{U64} | (std::cell::Cell<bool/usize/u32/u64>) | +| OnceCell | std::sync::OnceLock | std::cell::OnceCell | +| Lock\<T> | (parking_lot::Mutex\<T>) | (std::cell::RefCell) | +| RwLock\<T> | (parking_lot::RwLock\<T>) | (std::cell::RefCell) | +| MTRef<'a, T> | &'a T | &'a mut T | +| MTLock\<T> | (Lock\<T>) | (T) | +| ReadGuard | parking_lot::RwLockReadGuard | std::cell::Ref | +| MappedReadGuard | parking_lot::MappedRwLockReadGuard | std::cell::Ref | +| WriteGuard | parking_lot::RwLockWriteGuard | std::cell::RefMut | +| MappedWriteGuard | parking_lot::MappedRwLockWriteGuard | std::cell::RefMut | +| LockGuard | parking_lot::MutexGuard | std::cell::RefMut | +| MappedLockGuard | parking_lot::MappedMutexGuard | std::cell::RefMut | +| MetadataRef | [`OwningRef<Box<dyn Erased + Send + Sync>, [u8]>`][OwningRef] | [`OwningRef<Box<dyn Erased>, [u8]>`][OwningRef] | + +- These thread-safe data structures interspersed during compilation can + cause a lot of lock contention, which actually degrades performance as the + number of threads increases beyond 4. This inspires us to audit the use + of these data structures, leading to either refactoring to reduce use of + shared state, or persistent documentation covering invariants, atomicity, + and lock orderings. + +- On the other hand, we still need to figure out what other invariants + during compilation might not hold in parallel compilation. + +### WorkLocal + +`WorkLocal` is a special data structure implemented for parallel compiler. +It holds worker-locals values for each thread in a thread pool. You can only +access the worker local value through the Deref impl on the thread pool it +was constructed on. It will panic otherwise. + +`WorkLocal` is used to implement the `Arena` allocator in the parallel +environment, which is critical in parallel queries. Its implementation +is located in the `rustc-rayon-core::worker_local` module. However, in the +non-parallel compiler, it is implemented as `(OneThread<T>)`, whose `T` +can be accessed directly through `Deref::deref`. + +## Parallel Iterator + +The parallel iterators provided by the [`rayon`] crate are easy ways +to implement parallelism. In the current implementation of the parallel +compiler we use a custom [fork][rustc-rayon] of [`rayon`] to run tasks in parallel. + +Some iterator functions are implemented to run loops in parallel +when `parallel-compiler` is true. + +| Function(Omit `Send` and `Sync`) | Introduction | Owning Module | +| ------------------------------------------------------------ | ------------------------------------------------------------ | -------------------------- | +| **par_iter**<T: IntoParallelIterator>(t: T) -> T::Iter | generate a parallel iterator | rustc_data_structure::sync | +| **par_for_each_in**<T: IntoParallelIterator>(t: T, for_each: impl Fn(T::Item)) | generate a parallel iterator and run `for_each` on each element | rustc_data_structure::sync | +| **Map::par_body_owners**(self, f: impl Fn(LocalDefId)) | run `f` on all hir owners in the crate | rustc_middle::hir::map | +| **Map::par_for_each_module**(self, f: impl Fn(LocalDefId)) | run `f` on all modules and sub modules in the crate | rustc_middle::hir::map | +| **ModuleItems::par_items**(&self, f: impl Fn(ItemId)) | run `f` on all items in the module | rustc_middle::hir | +| **ModuleItems::par_trait_items**(&self, f: impl Fn(TraitItemId)) | run `f` on all trait items in the module | rustc_middle::hir | +| **ModuleItems::par_impl_items**(&self, f: impl Fn(ImplItemId)) | run `f` on all impl items in the module | rustc_middle::hir | +| **ModuleItems::par_foreign_items**(&self, f: impl Fn(ForeignItemId)) | run `f` on all foreign items in the module | rustc_middle::hir | + +There are a lot of loops in the compiler which can possibly be +parallelized using these functions. As of <!-- date-check--> August +2022, scenarios where the parallel iterator function has been used +are as follows: + +| caller | scenario | callee | +| ------------------------------------------------------- | ------------------------------------------------------------ | ------------------------ | +| rustc_metadata::rmeta::encoder::prefetch_mir | Prefetch queries which will be needed later by metadata encoding | par_iter | +| rustc_monomorphize::collector::collect_crate_mono_items | Collect monomorphized items reachable from non-generic items | par_for_each_in | +| rustc_interface::passes::analysis | Check the validity of the match statements | Map::par_body_owners | +| rustc_interface::passes::analysis | MIR borrow check | Map::par_body_owners | +| rustc_typeck::check::typeck_item_bodies | Type check | Map::par_body_owners | +| rustc_interface::passes::hir_id_validator::check_crate | Check the validity of hir | Map::par_for_each_module | +| rustc_interface::passes::analysis | Check the validity of loops body, attributes, naked functions, unstable abi, const bodys | Map::par_for_each_module | +| rustc_interface::passes::analysis | Liveness and intrinsic checking of MIR | Map::par_for_each_module | +| rustc_interface::passes::analysis | Deathness checking | Map::par_for_each_module | +| rustc_interface::passes::analysis | Privacy checking | Map::par_for_each_module | +| rustc_lint::late::check_crate | Run per-module lints | Map::par_for_each_module | +| rustc_typeck::check_crate | Well-formedness checking | Map::par_for_each_module | + +There are still many loops that have the potential to use parallel iterators. + ## Query System The query model has some properties that make it actually feasible to evaluate @@ -48,44 +130,22 @@ When a query `foo` is evaluated, the cache table for `foo` is locked. start evaluating. - If there *is* another query invocation for the same key in progress, we release the lock, and just block the thread until the other invocation has - computed the result we are waiting for. This cannot deadlock because, as - mentioned before, query invocations form a DAG. Some threads will always make - progress. + computed the result we are waiting for. **Cycle error detection** in the parallel + compiler requires more complex logic than in single-threaded mode. When + worker threads in parallel queries stop making progress due to interdependence, + the compiler uses an extra thread *(named deadlock handler)* to detect, remove and + report the cycle error. + +Parallel query still has a lot of work to do, most of which is related to +the previous `Data Structures` and `Parallel Iterators`. See [this tracking issue][tracking]. ## Rustdoc -As of <!-- date: 2022-05--> May 2022, there are still a number of steps +As of <!-- date-check--> May 2022, there are still a number of steps to complete before rustdoc rendering can be made parallel. More details on this issue can be found [here][parallel-rustdoc]. -## Current Status - -As of <!-- date: 2022-05 --> May 2022, work on explicitly parallelizing the -compiler has stalled. There is a lot of design and correctness work that needs -to be done. - -These are the basic ideas in the effort to make `rustc` parallel: - -- There are a lot of loops in the compiler that just iterate over all items in - a crate. These can possibly be parallelized. -- We can use (a custom fork of) [`rayon`] to run tasks in parallel. The custom - fork allows the execution of DAGs of tasks, not just trees. -- There are currently a lot of global data structures that need to be made - thread-safe. A key strategy here has been converting interior-mutable - data-structures (e.g. `Cell`) into their thread-safe siblings (e.g. `Mutex`). - -[`rayon`]: https://crates.io/crates/rayon - -As of <!-- date: 2022-05 --> May 2022, much of this effort is on hold due -to lack of manpower. We have a working prototype with promising performance -gains in many cases. However, there are two blockers: - -- It's not clear what invariants need to be upheld that might not hold in the - face of concurrency. An auditing effort was underway, but seems to have - stalled at some point. - -- There is a lot of lock contention, which actually degrades performance as the - number of threads increases beyond 4. +## Resources Here are some resources that can be used to learn more (note that some of them are a bit out of date): @@ -93,8 +153,9 @@ are a bit out of date): - [This IRLO thread by Zoxc, one of the pioneers of the effort][irlo0] - [This list of interior mutability in the compiler by nikomatsakis][imlist] - [This IRLO thread by alexchricton about performance][irlo1] -- [This tracking issue][tracking] +[`rayon`]: https://crates.io/crates/rayon +[rustc-rayon]: https://github.com/rust-lang/rustc-rayon [irlo0]: https://internals.rust-lang.org/t/parallelizing-rustc-using-rayon/6606 [imlist]: https://github.com/nikomatsakis/rustc-parallelization/blob/master/interior-mutability-list.md [irlo1]: https://internals.rust-lang.org/t/help-test-parallel-rustc/11503 diff --git a/src/doc/rustc-dev-guide/src/part-5-intro.md b/src/doc/rustc-dev-guide/src/part-5-intro.md index 4b7c25797..faa12f484 100644 --- a/src/doc/rustc-dev-guide/src/part-5-intro.md +++ b/src/doc/rustc-dev-guide/src/part-5-intro.md @@ -1,54 +1,57 @@ # From MIR to Binaries -All of the preceding chapters of this guide have one thing in common: we never -generated any executable machine code at all! With this chapter, all of that -changes. +All of the preceding chapters of this guide have one thing in common: +we never generated any executable machine code at all! +With this chapter, all of that changes. -So far, we've shown how the compiler can take raw source code in text format -and transform it into [MIR]. We have also shown how the compiler does various -analyses on the code to detect things like type or lifetime errors. Now, we -will finally take the MIR and produce some executable machine code. +So far, +we've shown how the compiler can take raw source code in text format +and transform it into [MIR]. +We have also shown how the compiler does various +analyses on the code to detect things like type or lifetime errors. +Now, we will finally take the MIR and produce some executable machine code. [MIR]: ./mir/index.md -> NOTE: This part of a compiler is often called the _backend_. The term is a bit -> overloaded because in the compiler source, it usually refers to the "codegen -> backend" (i.e. LLVM or Cranelift). Usually, when you see the word "backend" -> in this part, we are referring to the "codegen backend". +> NOTE: This part of a compiler is often called the _backend_. +> The term is a bit overloaded because in the compiler source, +> it usually refers to the "codegen backend" (i.e. LLVM, Cranelift, or GCC). +> Usually, when you see the word "backend" in this part, +> we are referring to the "codegen backend". So what do we need to do? -0. First, we need to collect the set of things to generate code for. In - particular, we need to find out which concrete types to substitute for - generic ones, since we need to generate code for the concrete types. - Generating code for the concrete types (i.e. emitting a copy of the code for - each concrete type) is called _monomorphization_, so the process of - collecting all the concrete types is called _monomorphization collection_. +0. First, we need to collect the set of things to generate code for. + In particular, + we need to find out which concrete types to substitute for generic ones, + since we need to generate code for the concrete types. + Generating code for the concrete types + (i.e. emitting a copy of the code for each concrete type) is called _monomorphization_, + so the process of collecting all the concrete types is called _monomorphization collection_. 1. Next, we need to actually lower the MIR to a codegen IR (usually LLVM IR) for each concrete type we collected. -2. Finally, we need to invoke LLVM or Cranelift, which runs a bunch of - optimization passes, generates executable code, and links together an - executable binary. +2. Finally, we need to invoke the codegen backend, + which runs a bunch of optimization passes, + generates executable code, + and links together an executable binary. [codegen1]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/base/fn.codegen_crate.html The code for codegen is actually a bit complex due to a few factors: -- Support for multiple codegen backends (LLVM and Cranelift). We try to share as much - backend code between them as possible, so a lot of it is generic over the - codegen implementation. This means that there are often a lot of layers of - abstraction. +- Support for multiple codegen backends (LLVM, Cranelift, and GCC). + We try to share as much backend code between them as possible, + so a lot of it is generic over the codegen implementation. + This means that there are often a lot of layers of abstraction. - Codegen happens asynchronously in another thread for performance. -- The actual codegen is done by a third-party library (either LLVM or Cranelift). +- The actual codegen is done by a third-party library (either of the 3 backends). -Generally, the [`rustc_codegen_ssa`][ssa] crate contains backend-agnostic code -(i.e. independent of LLVM or Cranelift), while the [`rustc_codegen_llvm`][llvm] -crate contains code specific to LLVM codegen. +Generally, the [`rustc_codegen_ssa`][ssa] crate contains backend-agnostic code, +while the [`rustc_codegen_llvm`][llvm] crate contains code specific to LLVM codegen. [ssa]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html [llvm]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/index.html At a very high level, the entry point is -[`rustc_codegen_ssa::base::codegen_crate`][codegen1]. This function starts the -process discussed in the rest of this chapter. - +[`rustc_codegen_ssa::base::codegen_crate`][codegen1]. +This function starts the process discussed in the rest of this chapter. diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index ada497d88..e1666e237 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -108,6 +108,6 @@ The llvm-lines output is affected by several options. MIR optimizations have little impact. Compared to the default `RUSTFLAGS="-Z mir-opt-level=1"`, level 0 adds 0.3GB and level 2 removes 0.2GB. -As of <!-- date: 2022-07 --> July 2022, +As of <!-- date-check --> July 2022, inlining happens in LLVM and GCC codegen backends, missing only in the Cranelift one. diff --git a/src/doc/rustc-dev-guide/src/queries/query-evaluation-model-in-detail.md b/src/doc/rustc-dev-guide/src/queries/query-evaluation-model-in-detail.md index b84a5dac4..8a08f1e04 100644 --- a/src/doc/rustc-dev-guide/src/queries/query-evaluation-model-in-detail.md +++ b/src/doc/rustc-dev-guide/src/queries/query-evaluation-model-in-detail.md @@ -76,7 +76,7 @@ executed, no results are cached. But the context already provides access to "input" data, i.e. pieces of immutable data that were computed before the context was created and that queries can access to do their computations. -As of <!-- date: 2021-01 --> January 2021, this input data consists mainly of +As of <!-- date-check --> January 2021, this input data consists mainly of the HIR map, upstream crate metadata, and the command-line options the compiler was invoked with; but in the future inputs will just consist of command-line options and a list of source files -- the HIR map will itself be provided by a diff --git a/src/doc/rustc-dev-guide/src/query.md b/src/doc/rustc-dev-guide/src/query.md index 95e570dfc..3d60059bd 100644 --- a/src/doc/rustc-dev-guide/src/query.md +++ b/src/doc/rustc-dev-guide/src/query.md @@ -3,7 +3,7 @@ <!-- toc --> As described in [the high-level overview of the compiler][hl], the Rust compiler -is still (as of <!-- date: 2021-07 --> July 2021) transitioning from a +is still (as of <!-- date-check --> July 2021) transitioning from a traditional "pass-based" setup to a "demand-driven" system. The compiler query system is the key to rustc's demand-driven organization. The idea is pretty simple. Instead of entirely independent passes diff --git a/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md b/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md index 327415e5a..5ce93c3df 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver-getting-diagnostics.md @@ -7,7 +7,7 @@ To get diagnostics from the compiler, configure `rustc_interface::Config` to output diagnostic to a buffer, and run `TyCtxt.analysis`. The following was tested -with <!-- date: 2022-06 --> `nightly-2022-06-05` (See [here][example] +with <!-- date-check: June 2022 --> `nightly-2022-06-05` (See [here][example] for the complete example): [example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-getting-diagnostics.rs diff --git a/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md b/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md index d70264fe4..ce53f3861 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md @@ -5,7 +5,7 @@ ## Getting the type of an expression To get the type of an expression, use the `global_ctxt` to get a `TyCtxt`. -The following was tested with <!-- date: 2022-06 --> `nightly-2022-06-05` +The following was tested with <!-- date-check: June 2022 --> `nightly-2022-06-05` (see [here][example] for the complete example): [example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-interacting-with-the-ast.rs diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index 91bb0c358..f21c8725c 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -66,7 +66,7 @@ these passes, please let us know!) [44136]: https://github.com/rust-lang/rust/issues/44136 -Here is the list of passes as of <!-- date: 2022-05 --> May 2022: +Here is the list of passes as of <!-- date-check --> May 2022: - `calculate-doc-coverage` calculates information used for the `--show-coverage` flag. diff --git a/src/doc/rustc-dev-guide/src/salsa.md b/src/doc/rustc-dev-guide/src/salsa.md index afa01eda2..872308e78 100644 --- a/src/doc/rustc-dev-guide/src/salsa.md +++ b/src/doc/rustc-dev-guide/src/salsa.md @@ -9,7 +9,7 @@ want to watch [Salsa In More Depth](https://www.youtube.com/watch?v=i_IhACacPRY), also by Niko Matsakis. -> As of <!-- date: 2022-04 --> April 2022, although Salsa is inspired by +> As of <!-- date-check --> April 2022, although Salsa is inspired by > (among other things) rustc's query system, it is not used directly in rustc. > It _is_ used in chalk and extensively in `rust-analyzer`, but there are no > medium or long-term concrete plans to integrate it into the compiler. diff --git a/src/doc/rustc-dev-guide/src/stabilization_guide.md b/src/doc/rustc-dev-guide/src/stabilization_guide.md index 454cd0f27..0ac19293b 100644 --- a/src/doc/rustc-dev-guide/src/stabilization_guide.md +++ b/src/doc/rustc-dev-guide/src/stabilization_guide.md @@ -99,24 +99,6 @@ require steps beyond what this guide talks about. Note: Before we stabilize any feature, it's the rule that it should appear in the documentation. -### Determining the stabilization version - -The version in which the feature will be stabilized *must* match -the value of [the `src/version` file in `master`][src-version] when the PR is merged. - -It's worth checking [the version schedule on the Forge][forge-versions] to see whether -changes are coming soon. You'll usually use the version labelled "Nightly". -"Nightly" is two versions higher than the current stable release, -since what's currently in beta will be the next stable release, -and any changes you're making now will be in the one after that. - -No PR is merged instantly, so you'll want to be careful around release time. -The version bump happens [the Friday before][forge-release-process] the stable release, -not the same time as the release. So if you're opening a PR shortly before then, -be prepared to update the version, or consider just opening it for one version -higher than the current nightly, with a note saying not to merge until -after the upcoming version bump. - ### Updating the feature-gate listing There is a central listing of feature-gates in @@ -127,7 +109,7 @@ to stabilize, something like (this example is taken from ```rust,ignore // pub(restricted) visibilities (RFC 1422) -(active, pub_restricted, "1.9.0", Some(32409)), +(active, pub_restricted, "CURRENT_RUSTC_VERSION", Some(32409)), ``` The above line should be moved down to the area for "accepted" @@ -136,11 +118,13 @@ When it is done, it should look like: ```rust,ignore // pub(restricted) visibilities (RFC 1422) -(accepted, pub_restricted, "1.31.0", Some(32409)), +(accepted, pub_restricted, "CURRENT_RUSTC_VERSION", Some(32409)), // note that we changed this ``` -(The version here is the one discussed in the previous section.) +(Even though you will encounter version numbers in the file of past changes, +you should not put the rustc version you expect your stabilization to happen in, +but instead `CURRENT_RUSTC_VERSION`) ### Removing existing uses of the feature-gate diff --git a/src/doc/rustc-dev-guide/src/test-implementation.md b/src/doc/rustc-dev-guide/src/test-implementation.md index 09a66cdc9..1b8247005 100644 --- a/src/doc/rustc-dev-guide/src/test-implementation.md +++ b/src/doc/rustc-dev-guide/src/test-implementation.md @@ -155,5 +155,4 @@ $ rustc my_mod.rs -Z unpretty=hir [TestDesc]: https://doc.rust-lang.org/test/struct.TestDesc.html [Symbol]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html [Ident]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Ident.html -[eRFC]: https://github.com/rust-lang/rfcs/blob/master/text/2318-custom-test-frameworks.md [rustc_ast]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_ast diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 5c3dcf54b..70cef2ad3 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -452,7 +452,7 @@ fn main() { ## Revisions -Certain classes of tests support "revisions" (as of <!-- date: 2022-07 --> July 2022, +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. diff --git a/src/doc/rustc-dev-guide/src/the-parser.md b/src/doc/rustc-dev-guide/src/the-parser.md index ff43220c1..0d37704e8 100644 --- a/src/doc/rustc-dev-guide/src/the-parser.md +++ b/src/doc/rustc-dev-guide/src/the-parser.md @@ -1,6 +1,6 @@ # Lexing and Parsing -As of <!-- date: 2021-01 --> January 2021, the lexer and parser are undergoing +As of <!-- date-check --> January 2021, the lexer and parser are undergoing refactoring to allow extracting them into libraries. The very first thing the compiler does is take the program (in Unicode @@ -35,9 +35,10 @@ The main entrypoint to the parser is via the various `parse_*` functions and oth the token stream, and then execute the parser to get a `Crate` (the root AST node). -To minimise the amount of copying that is done, both the `StringReader` and -`Parser` have lifetimes which bind them to the parent `ParseSess`. This contains -all the information needed while parsing, as well as the `SourceMap` itself. +To minimize the amount of copying that is done, +both [`StringReader`] and [`Parser`] have lifetimes which bind them to the parent `ParseSess`. +This contains all the information needed while parsing, +as well as the [`SourceMap`] itself. Note that while parsing, we may encounter macro definitions or invocations. We set these aside to be expanded (see [this chapter](./macro-expansion.md)). @@ -52,9 +53,9 @@ Code for lexical analysis is split between two crates: constituting tokens. Although it is popular to implement lexers as generated finite state machines, the lexer in `rustc_lexer` is hand-written. -- [`StringReader`] from [`rustc_ast`][rustc_ast] integrates `rustc_lexer` with `rustc` - specific data structures. Specifically, it adds `Span` information to tokens - returned by `rustc_lexer` and interns identifiers. +- [`StringReader`] integrates `rustc_lexer` with data structures specific to `rustc`. + Specifically, + it adds `Span` information to tokens returned by `rustc_lexer` and interns identifiers. [rustc_ast]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/index.html [rustc_errors]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html @@ -64,7 +65,7 @@ Code for lexical analysis is split between two crates: [rustc_parse]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html [parser_lib]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html [parser]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/index.html -[`Parser`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/parse/parser/struct.Parser.html +[`Parser`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html [`StringReader`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/lexer/struct.StringReader.html [visit module]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/index.html [sourcefile]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.SourceFile.html diff --git a/src/doc/rustc-dev-guide/src/thir.md b/src/doc/rustc-dev-guide/src/thir.md index 4f8e6512c..2a811be3d 100644 --- a/src/doc/rustc-dev-guide/src/thir.md +++ b/src/doc/rustc-dev-guide/src/thir.md @@ -4,7 +4,7 @@ The THIR ("Typed High-Level Intermediate Representation"), previously called HAIR for "High-Level Abstract IR", is another IR used by rustc that is generated after -[type checking]. It is (as of <!-- date: 2022-04 --> April 2022) only used for +[type checking]. It is (as of <!-- date-check --> April 2022) only used for [MIR construction] and [exhaustiveness checking]. There is also [an experimental unsafety checker][thir-unsafeck] that operates on the THIR as a replacement for the current MIR unsafety checker, and can be used instead of the MIR unsafety checker by passing @@ -47,9 +47,19 @@ which is useful to keep peak memory in check. Having a THIR representation of all bodies of a crate in memory at the same time would be very heavy. You can get a debug representation of the THIR by passing the `-Zunpretty=thir-tree` flag -to `rustc`. Here is how a function with just the statement `let x = 1 + 2;` gets represented in -THIR: +to `rustc`. + +To demonstrate, let's use the following example: + ```rust +fn main() { + let x = 1 + 2; +} +``` + +Here is how that gets represented in THIR (as of <!-- date-check --> Aug 2022): + +```rust,no_run Thir { // no match arms arms: [], @@ -57,57 +67,73 @@ Thir { // expression 0, a literal with a value of 1 Expr { ty: i32, - temp_lifetime: Some(Node(6)), + temp_lifetime: Some( + Node(1), + ), span: oneplustwo.rs:2:13: 2:14 (#0), kind: Literal { - literal: Const { - ty: i32, - val: Value(Scalar(0x00000001)), + lit: Spanned { + node: Int( + 1, + Unsuffixed, + ), + span: oneplustwo.rs:2:13: 2:14 (#0), }, - user_ty: None, - const_id: None, + neg: false, }, }, // expression 1, scope surronding literal 1 Expr { ty: i32, - temp_lifetime: Some(Node(6)), + temp_lifetime: Some( + Node(1), + ), span: oneplustwo.rs:2:13: 2:14 (#0), kind: Scope { - region_scope: Node(1), - lint_level: Explicit(HirId { - owner: DefId(0:3 ~ oneplustwo[6ccc]::main), - local_id: 1, - }), // reference to expression 0 above + region_scope: Node(3), + lint_level: Explicit( + HirId { + owner: DefId(0:3 ~ oneplustwo[6932]::main), + local_id: 3, + }, + ), value: e0, }, }, // expression 2, literal 2 Expr { ty: i32, - temp_lifetime: Some(Node(6)), + temp_lifetime: Some( + Node(1), + ), span: oneplustwo.rs:2:17: 2:18 (#0), kind: Literal { - literal: Const { - ty: i32, - val: Value(Scalar(0x00000002)), + lit: Spanned { + node: Int( + 2, + Unsuffixed, + ), + span: oneplustwo.rs:2:17: 2:18 (#0), }, - user_ty: None, - const_id: None, + neg: false, }, }, // expression 3, scope surrounding literal 2 Expr { ty: i32, - temp_lifetime: Some(Node(6)), + temp_lifetime: Some( + Node(1), + ), span: oneplustwo.rs:2:17: 2:18 (#0), kind: Scope { - region_scope: Node(2), - lint_level: Explicit(HirId { - owner: DefId(0:3 ~ oneplustwo[6ccc]::main), - local_id: 2, - }), + region_scope: Node(4), + lint_level: Explicit( + HirId { + owner: DefId(0:3 ~ oneplustwo[6932]::main), + local_id: 4, + }, + ), // reference to expression 2 above value: e2, }, @@ -115,7 +141,9 @@ Thir { // expression 4, represents 1 + 2 Expr { ty: i32, - temp_lifetime: Some(Node(6)), + temp_lifetime: Some( + Node(1), + ), span: oneplustwo.rs:2:13: 2:18 (#0), kind: Binary { op: Add, @@ -127,30 +155,38 @@ Thir { // expression 5, scope surronding expression 4 Expr { ty: i32, - temp_lifetime: Some(Node(6)), + temp_lifetime: Some( + Node(1), + ), span: oneplustwo.rs:2:13: 2:18 (#0), kind: Scope { - region_scope: Node(3), - lint_level: Explicit(HirId { - owner: DefId(0:3 ~ oneplustwo[6ccc]::main), - local_id: 3, - }), + region_scope: Node(5), + lint_level: Explicit( + HirId { + owner: DefId(0:3 ~ oneplustwo[6932]::main), + local_id: 5, + }, + ), value: e4, }, }, // expression 6, block around statement Expr { ty: (), - temp_lifetime: Some(Node(8)), + temp_lifetime: Some( + Node(9), + ), span: oneplustwo.rs:1:11: 3:2 (#0), kind: Block { body: Block { targeted_by_break: false, - region_scope: Node(7), + region_scope: Node(8), opt_destruction_scope: None, span: oneplustwo.rs:1:11: 3:2 (#0), // reference to statement 0 below - stmts: [ s0 ], + stmts: [ + s0, + ], expr: None, safety_mode: Safe, }, @@ -160,25 +196,29 @@ Thir { Expr { ty: (), temp_lifetime: Some( - Node(8), + Node(9), ), span: oneplustwo.rs:1:11: 3:2 (#0), kind: Scope { - region_scope: Node(8), - lint_level: Explicit(HirId { - owner: DefId(0:3 ~ oneplustwo[6ccc]::main), - local_id: 8, - }), + region_scope: Node(9), + lint_level: Explicit( + HirId { + owner: DefId(0:3 ~ oneplustwo[6932]::main), + local_id: 9, + }, + ), value: e6, }, }, // destruction scope around expression 7 Expr { ty: (), - temp_lifetime: Some(Node(8)), + temp_lifetime: Some( + Node(9), + ), span: oneplustwo.rs:1:11: 3:2 (#0), kind: Scope { - region_scope: Destruction(8), + region_scope: Destruction(9), lint_level: Inherited, value: e7, }, @@ -188,8 +228,8 @@ Thir { // let statement Stmt { kind: Let { - remainder_scope: Remainder { block: 7, first_statement_index: 0}, - init_scope: Node(6), + remainder_scope: Remainder { block: 8, first_statement_index: 0}, + init_scope: Node(1), pattern: Pat { ty: i32, span: oneplustwo.rs:2:9: 2:10 (#0), @@ -197,22 +237,31 @@ Thir { mutability: Not, name: "x", mode: ByValue, - var: HirId { - owner: DefId(0:3 ~ oneplustwo[6ccc]::main), - local_id: 5, - }, + var: LocalVarId( + HirId { + owner: DefId(0:3 ~ oneplustwo[6932]::main), + local_id: 7, + }, + ), ty: i32, subpattern: None, is_primary: true, }, }, - initializer: Some(e5), - lint_level: Explicit(HirId { - owner: DefId(0:3 ~ oneplustwo[6ccc]::main), - local_id: 4, - }), + initializer: Some( + e5, + ), + else_block: None, + lint_level: Explicit( + HirId { + owner: DefId(0:3 ~ oneplustwo[6932]::main), + local_id: 6, + }, + ), }, - opt_destruction_scope: Some(Destruction(6)), + opt_destruction_scope: Some( + Destruction(1), + ), }, ], } diff --git a/src/doc/rustc-dev-guide/src/traits/chalk.md b/src/doc/rustc-dev-guide/src/traits/chalk.md index d4045c460..78deb3675 100644 --- a/src/doc/rustc-dev-guide/src/traits/chalk.md +++ b/src/doc/rustc-dev-guide/src/traits/chalk.md @@ -1,7 +1,7 @@ # Chalk-based trait solving -[Chalk][chalk] is an experimental trait solver for Rust that is (as of <!-- -date: 2022-05 --> May 2022) under development by the [Types team]. +[Chalk][chalk] is an experimental trait solver for Rust that is +(as of <!-- date-check --> May 2022) under development by the [Types team]. Its goal is to enable a lot of trait system features and bug fixes that are hard to implement (e.g. GATs or specialization). If you would like to help in hacking on the new solver, drop by on the rust-lang Zulip in the [`#t-types`] diff --git a/src/doc/rustc-dev-guide/src/traits/resolution.md b/src/doc/rustc-dev-guide/src/traits/resolution.md index c22ee6de6..195fe6050 100644 --- a/src/doc/rustc-dev-guide/src/traits/resolution.md +++ b/src/doc/rustc-dev-guide/src/traits/resolution.md @@ -120,7 +120,7 @@ the obligation contains unbound inference variables. The subroutines that decide whether a particular impl/where-clause/etc applies to a particular obligation are collectively referred to as the process of -_matching_. As of <!-- date: 2022-05 --> May 2022, this amounts to unifying +_matching_. As of <!-- date-check --> May 2022, this amounts to unifying the `Self` types, but in the future we may also recursively consider some of the nested obligations, in the case of an impl. diff --git a/src/doc/rustc-dev-guide/src/type-inference.md b/src/doc/rustc-dev-guide/src/type-inference.md index 4be9211ee..10f1dd5ef 100644 --- a/src/doc/rustc-dev-guide/src/type-inference.md +++ b/src/doc/rustc-dev-guide/src/type-inference.md @@ -45,11 +45,9 @@ tcx.infer_ctxt().enter(|infcx| { }) ``` -Within the closure, `infcx` has the type `InferCtxt<'cx, 'tcx>` for some -fresh `'cx`, while `'tcx` is the same as outside the inference context. -(Again, see the [`ty` chapter][ty-ch] for more details on this setup.) - -[ty-ch]: ty.html +Within the closure, +`infcx` has the type `InferCtxt<'a, 'tcx>` for some fresh `'a`, +while `'tcx` is the same as outside the inference context. The `tcx.infer_ctxt` method actually returns a builder, which means there are some kinds of configuration you can do before the `infcx` is @@ -72,7 +70,7 @@ inference works, or perhaps this blog post on [Unification in the Chalk project]: http://smallcultfollowing.com/babysteps/blog/2017/03/25/unification-in-chalk-part-1/ All told, the inference context stores five kinds of inference variables -(as of <!-- date: 2021-06 --> June 2021): +(as of <!-- date-check --> June 2021): - Type variables, which come in three varieties: - General type variables (the most common). These can be unified with any diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index d168af60c..d9d430c20 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -18,6 +18,8 @@ - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) - [\*-apple-watchos\*](platform-support/apple-watchos.md) - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md) + - [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md) + - [armv4t-none-eabi](platform-support/armv4t-none-eabi.md) - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md index 0ae9e53af..38fd5c969 100644 --- a/src/doc/rustc/src/instrument-coverage.md +++ b/src/doc/rustc/src/instrument-coverage.md @@ -97,7 +97,17 @@ $ echo "{some: 'thing'}" | target/debug/examples/formatjson5 - } ``` -After running this program, a new file, `default.profraw`, should be in the current working directory. It's often preferable to set a specific file name or path. You can change the output file using the environment variable `LLVM_PROFILE_FILE`: +After running this program, a new file named like `default_11699812450447639123_0_20944` should be in the current working directory. +A new, unique file name will be generated each time the program is run to avoid overwriting previous data. + +```shell +$ echo "{some: 'thing'}" | target/debug/examples/formatjson5 - +... +$ ls default_*.profraw +default_11699812450447639123_0_20944.profraw +``` + +You can also set a specific file name or path for the generated `.profraw` files by using the environment variable `LLVM_PROFILE_FILE`: ```shell $ echo "{some: 'thing'}" \ @@ -115,6 +125,9 @@ If `LLVM_PROFILE_FILE` contains a path to a non-existent directory, the missing - `%Nm` - the instrumented binary’s signature: The runtime creates a pool of N raw profiles, used for on-line profile merging. The runtime takes care of selecting a raw profile from the pool, locking it, and updating it before the program exits. `N` must be between `1` and `9`, and defaults to `1` if omitted (with simply `%m`). - `%c` - Does not add anything to the filename, but enables a mode (on some platforms, including Darwin) in which profile counter updates are continuously synced to a file. This means that if the instrumented program crashes, or is killed by a signal, perfect coverage information can still be recovered. +In the first example above, the value `11699812450447639123_0` in the generated filename is the instrumented binary's signature, +which replaced the `%m` pattern and the value `20944` is the process ID of the binary being executed. + ## Installing LLVM coverage tools LLVM's supplies two tools—`llvm-profdata` and `llvm-cov`—that process coverage data and generate reports. There are several ways to find and/or install these tools, but note that the coverage mapping data generated by the Rust compiler requires LLVM version 12 or higher, and processing the *raw* data may require exactly the LLVM version used by the compiler. (`llvm-cov --version` typically shows the tool's LLVM version number, and `rustc --verbose --version` shows the version of LLVM used by the Rust compiler.) @@ -181,11 +194,10 @@ A typical use case for coverage analysis is test coverage. Rust's source-based c The following example (using the [`json5format`] crate, for demonstration purposes) show how to generate and analyze coverage results for all tests in a crate. -Since `cargo test` both builds and runs the tests, we set both the additional `RUSTFLAGS`, to add the `-C instrument-coverage` flag, and `LLVM_PROFILE_FILE`, to set a custom filename for the raw profiling data generated during the test runs. Since there may be more than one test binary, apply `%m` in the filename pattern. This generates unique names for each test binary. (Otherwise, each executed test binary would overwrite the coverage results from the previous binary.) +Since `cargo test` both builds and runs the tests, we set the additional `RUSTFLAGS`, to add the `-C instrument-coverage` flag. ```shell $ RUSTFLAGS="-C instrument-coverage" \ - LLVM_PROFILE_FILE="json5format-%m.profraw" \ cargo test --tests ``` @@ -210,7 +222,7 @@ test result: ok. 31 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out You should have one or more `.profraw` files now, one for each test binary. Run the `profdata` tool to merge them: ```shell -$ llvm-profdata merge -sparse json5format-*.profraw -o json5format.profdata +$ llvm-profdata merge -sparse default_*.profraw -o json5format.profdata ``` Then run the `cov` tool, with the `profdata` file and all test binaries: @@ -230,6 +242,8 @@ $ llvm-cov show \ --Xdemangler=rustfilt | less -R ``` +> **Note**: If overriding the default `profraw` file name via the `LLVM_PROFILE_FILE` environment variable, it's highly recommended to use the `%m` and `%p` special pattern strings to generate unique file names in the case of more than a single test binary being executed. + > **Note**: The command line option `--ignore-filename-regex=/.cargo/registry`, which excludes the sources for dependencies from the coverage results.\_ ### Tips for listing the binaries automatically @@ -271,9 +285,8 @@ To include doc tests in the coverage results, drop the `--tests` flag, and apply ```bash $ RUSTFLAGS="-C instrument-coverage" \ RUSTDOCFLAGS="-C instrument-coverage -Z unstable-options --persist-doctests target/debug/doctestbins" \ - LLVM_PROFILE_FILE="json5format-%m.profraw" \ cargo test -$ llvm-profdata merge -sparse json5format-*.profraw -o json5format.profdata +$ llvm-profdata merge -sparse default_*.profraw -o json5format.profdata ``` The `-Z unstable-options --persist-doctests` flag is required, to save the test binaries @@ -302,8 +315,7 @@ $ llvm-cov report \ > version without doc tests, include: - The `cargo test ... --no-run` command is updated with the same environment variables - and flags used to _build_ the tests, _including_ the doc tests. (`LLVM_PROFILE_FILE` - is only used when _running_ the tests.) + and flags used to _build_ the tests, _including_ the doc tests. - The file glob pattern `target/debug/doctestbins/*/rust_out` adds the `rust_out` binaries generated for doc tests (note, however, that some `rust_out` files may not be executable binaries). diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index 9c644dd40..b1854b22a 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -30,7 +30,7 @@ Using `rustc` directly: # Compile the Rust staticlib rustc --crate-type=staticlib -Clinker-plugin-lto -Copt-level=2 ./lib.rs # Compile the C code with `-flto=thin` -clang -c -O2 -flto=thin -o main.o ./main.c +clang -c -O2 -flto=thin -o cmain.o ./cmain.c # Link everything, making sure that we use an appropriate linker clang -flto=thin -fuse-ld=lld -L . -l"name-of-your-rust-lib" -o main -O2 ./cmain.o ``` @@ -41,7 +41,7 @@ Using `cargo`: # Compile the Rust staticlib RUSTFLAGS="-Clinker-plugin-lto" cargo build --release # Compile the C code with `-flto=thin` -clang -c -O2 -flto=thin -o main.o ./main.c +clang -c -O2 -flto=thin -o cmain.o ./cmain.c # Link everything, making sure that we use an appropriate linker clang -flto=thin -fuse-ld=lld -L . -l"name-of-your-rust-lib" -o main -O2 ./cmain.o ``` diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 01489e9aa..3a6963ebc 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -213,7 +213,7 @@ target | std | host | notes [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD `aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore -`aarch64-unknown-uefi` | * | | ARM64 UEFI +[`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | * | | ARM64 UEFI `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) `aarch64-unknown-netbsd` | ✓ | ✓ | [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD @@ -223,6 +223,8 @@ target | std | host | notes `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI) `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian) [`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS 64-bit with 32-bit pointers +[`armeb-unknown-linux-gnueabi`](platform-support/armeb-unknown-linux-gnueabi.md) | ✓ | ? | ARM BE8 the default ARM big-endian architecture since [ARMv6](https://developer.arm.com/documentation/101754/0616/armlink-Reference/armlink-Command-line-Options/--be8?lang=en). +`armv4t-none-eabi` | * | | ARMv4T A32 `armv4t-unknown-linux-gnueabi` | ? | | `armv5te-unknown-linux-uclibceabi` | ? | | ARMv5TE Linux with uClibc `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD @@ -249,7 +251,7 @@ target | std | host | notes `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku `i686-unknown-netbsd` | ✓ | ✓ | NetBSD/i386 with SSE2 [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD -`i686-unknown-uefi` | * | | 32-bit UEFI +[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | | 32-bit UEFI `i686-uwp-windows-gnu` | ? | | `i686-uwp-windows-msvc` | ? | | `i686-wrs-vxworks` | ? | | @@ -276,6 +278,7 @@ target | std | host | notes `powerpc64-unknown-linux-musl` | ? | | `powerpc64-wrs-vxworks` | ? | | `powerpc64le-unknown-linux-musl` | ? | | +[`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64 `riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33) `riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches) `riscv32im-unknown-none-elf` | * | | Bare RISC-V (RV32IM ISA) @@ -283,6 +286,7 @@ target | std | host | notes `riscv32imc-esp-espidf` | ✓ | | RISC-V ESP-IDF `riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD `riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0) +[`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 `s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux `sparc64-unknown-netbsd` | ✓ | ✓ | NetBSD/sparc64 @@ -304,7 +308,7 @@ target | std | host | notes `x86_64-unknown-l4re-uclibc` | ? | | `x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD -`x86_64-unknown-uefi` | * | | 64-bit UEFI +[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | | 64-bit UEFI `x86_64-uwp-windows-gnu` | ✓ | | `x86_64-uwp-windows-msvc` | ✓ | | `x86_64-wrs-vxworks` | ? | | diff --git a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md new file mode 100644 index 000000000..507631cdc --- /dev/null +++ b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md @@ -0,0 +1,74 @@ +# armeb-unknown-linux-gnueabi +**Tier: 3** + +Target for cross-compiling Linux user-mode applications targetting the ARM BE8 architecture. + +## Overview +BE8 architecture retains the same little-endian ordered code-stream used by conventional little endian ARM systems, however the data accesses are in big-endian. BE8 is used primarily in high-performance networking applications where the ability to read packets in their native "Network Byte Order" is important (many network protocols transmit data in big-endian byte order for their wire formats). + +## History +BE8 architecture is the default big-endian architecture for ARM since [ARMv6](https://developer.arm.com/documentation/101754/0616/armlink-Reference/armlink-Command-line-Options/--be8?lang=en). It's predecessor, used for ARMv4 and ARMv5 devices was [BE32](https://developer.arm.com/documentation/dui0474/j/linker-command-line-options/--be32). On ARMv6 architecture, endianness can be configured via [system registers](https://developer.arm.com/documentation/ddi0290/g/unaligned-and-mixed-endian-data-access-support/mixed-endian-access-support/interaction-between-the-bus-protocol-and-the-core-endianness). However, BE32 was withdrawn for [ARMv7](https://developer.arm.com/documentation/ddi0406/cb/Appendixes/Deprecated-and-Obsolete-Features/Obsolete-features/Support-for-BE-32-endianness-model) onwards. + +## Target Maintainers +* [@WorksButNotTested](https://github.com/WorksButNotTested) + +## Requirements +The target is cross-compiled. This target supports `std` in the normal way (indeed only nominal changes are required from the standard ARM configuration). + +## Target definition +The target definition can be seen [here](https://github.com/rust-lang/rust/tree/master/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs). In particular, it should be noted that the `features` specify that this target is built for the ARMv8 core. Though this can likely be modified as required. + +## Building the target +Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target. + +Therefore, you can build Rust with support for the target by adding it to the target list in config.toml, a sample configuration is shown below. It is expected that the user already have a working GNU compiler toolchain and update the paths accordingly. + +```toml +[llvm] +download-ci-llvm = false +skip-rebuild = true +optimize = true +ninja = true +targets = "ARM;X86" +clang = false + +[build] +target = ["x86_64-unknown-linux-gnu", "armeb-unknown-linux-gnueabi"] +docs = false +docs-minification = false +compiler-docs = false +[install] +prefix = "/home/user/x-tools/rust/" + +[rust] +debug-logging=true +backtrace = true +incremental = true + +[target.x86_64-unknown-linux-gnu] + +[dist] + +[target.armeb-unknown-linux-gnueabi] +cc = "/home/user/x-tools/armeb-unknown-linux-gnueabi/bin/armeb-unknown-linux-gnueabi-gcc" +cxx = "/home/user/x-tools/armeb-unknown-linux-gnueabi/bin/armeb-unknown-linux-gnueabi-g++" +ar = "/home/user/x-tools/armeb-unknown-linux-gnueabi/bin/armeb-unknown-linux-gnueabi-ar" +ranlib = "/home/user/x-tools/armeb-unknown-linux-gnueabi/bin/armeb-unknown-linux-gnueabi-ranlib" +linker = "/home/user/x-tools/armeb-unknown-linux-gnueabi/bin/armeb-unknown-linux-gnueabi-gcc" +llvm-config = "/home/user/x-tools/clang/bin/llvm-config" +llvm-filecheck = "/home/user/x-tools/clang/bin/FileCheck" +``` + +## Building Rust programs + +The following `.cargo/config` is needed inside any project directory to build for the BE8 target: + +```toml +[build] +target = "armeb-unknown-linux-gnueabi" + +[target.armeb-unknown-linux-gnueabi] +linker = "armeb-unknown-linux-gnueabi-gcc" +``` + +Note that it is expected that the user has a suitable linker from the GNU toolchain. diff --git a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md new file mode 100644 index 000000000..cf831e159 --- /dev/null +++ b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md @@ -0,0 +1,70 @@ +# armv4t-none-eabi + +Tier 3 + +Bare-metal target for any cpu in the ARMv4T architecture family, supporting +ARM/Thumb code interworking (aka `a32`/`t32`), with ARM code as the default code +generation. + +In particular this supports the Gameboy Advance (GBA), but there's nothing GBA +specific with this target, so any ARMv4T device should work fine. + +## Target Maintainers + +* [@Lokathor](https://github.com/lokathor) + +## Requirements + +The target is cross-compiled, and uses static linking. + +The linker that comes with rustc cannot link for this platform (the platform is +too old). You will need the `arm-none-eabi-ld` linker from a GNU Binutils +targeting ARM. This can be obtained for Windows/Mac/Linux from the [ARM +Developer Website][arm-dev], or possibly from your OS's package manager. + +[arm-dev]: https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain + +This target doesn't provide a linker script, you'll need to bring your own +according to the specific device you want to target. Pass +`-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use +`your_script.ld` during linking. + +## Building Rust Programs + +Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target. + +Just use the `build-std` nightly cargo feature to build the `core` library. You +can pass this as a command line argument to cargo, or your `.cargo/config.toml` +file might include the following lines: + +```toml +[unstable] +build-std = ["core"] +``` + +Most of `core` should work as expected, with the following notes: +* the target is "soft float", so `f32` and `f64` operations are emulated in + software. +* integer division is also emulated in software. +* the target is old enough that it doesn't have atomic instructions. + +Rust programs are output as ELF files. + +For running on hardware, you'll generally need to extract the "raw" program code +out of the ELF and into a file of its own. The `objcopy` program provided as +part of the GNU Binutils can do this: + +```shell +arm-none-eabi-objcopy --output-target binary [in_file] [out_file] +``` + +## Testing + +This is a cross-compiled target that you will need to emulate during testing. + +Because this is a device-agnostic target, and the exact emulator that you'll +need depends on the specific device you want to run your code on. + +For example, when programming for the Gameboy Advance, the +[mgba-test-runner](https://github.com/agbrs/agb) program could be used to make a +normal set of rust tests be run within the `mgba` emulator. diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index 61bd1b425..1ff6003c1 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -5,14 +5,10 @@ [Fuchsia] is a modern open source operating system that's simple, secure, updatable, and performant. -[Fuchsia]: https://fuchsia.dev/ - ## Target maintainers The [Fuchsia team]: -[Fuchsia team]: https://team-api.infra.rust-lang.org/v1/teams/fuchsia.json - - Tyler Mandry ([@tmandry](https://github.com/tmandry)) - Dan Johnson ([@computerdruid](https://github.com/computerdruid)) - David Koloski ([@djkoloski](https://github.com/djkoloski)) @@ -24,27 +20,174 @@ the members reported by the API. The API should be considered to be authoritative if this occurs. Instead of pinging individual members, use `@rustbot ping fuchsia` to contact the team on GitHub. +## Table of contents + +1. [Requirements](#requirements) +1. [Walkthrough structure](#walkthrough-structure) +1. [Compiling a Rust binary targeting Fuchsia](#compiling-a-rust-binary-targeting-fuchsia) + 1. [Targeting Fuchsia with rustup and cargo](#targeting-fuchsia-with-rustup-and-cargo) + 1. [Targeting Fuchsia with a compiler built from source](#targeting-fuchsia-with-a-compiler-built-from-source) +1. [Creating a Fuchsia package](#creating-a-fuchsia-package) + 1. [Creating a Fuchsia component](#creating-a-fuchsia-component) + 1. [Building a Fuchsia package](#building-a-fuchsia-package) +1. [Publishing a Fuchsia package](#publishing-a-fuchsia-package) + 1. [Creating a Fuchsia package repository](#creating-a-fuchsia-package-repository) + 1. [Publishing Fuchsia package to repository](#publishing-fuchsia-package-to-repository) +1. [Running a Fuchsia component on an emulator](#running-a-fuchsia-component-on-an-emulator) + 1. [Starting the Fuchsia emulator](#starting-the-fuchsia-emulator) + 1. [Watching emulator logs](#watching-emulator-logs) + 1. [Serving a Fuchsia package](#serving-a-fuchsia-package) + 1. [Running a Fuchsia component](#running-a-fuchsia-component) +1. [`.gitignore` extensions](#gitignore-extensions) +1. [Testing](#testing) + 1. [Running unit tests](#running-unit-tests) + 1. [Running the compiler test suite](#running-the-compiler-test-suite) +1. [Debugging](#debugging) + 1. [`zxdb`](#zxdb) + 1. [Attaching `zxdb`](#attaching-zxdb) + 1. [Using `zxdb`](#using-zxdb) + 1. [Displaying source code in `zxdb`](#displaying-source-code-in-zxdb) + ## Requirements -This target is cross-compiled from a host environment. Development may be done -from the [source tree] or using the Fuchsia SDK. +This target is cross-compiled from a host environment. You will need a recent +copy of the [Fuchsia SDK], which provides the tools, libraries, and binaries +required to build and link programs for Fuchsia. -[source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build +Development may also be done from the [source tree]. -Fuchsia targets support std and follow the `sysv64` calling convention on +Fuchsia targets support `std` and follow the `sysv64` calling convention on x86_64. Fuchsia binaries use the ELF file format. -## Building the target +## Walkthrough structure + +This walkthrough will cover: + +1. Compiling a Rust binary targeting Fuchsia. +1. Building a Fuchsia package. +1. Publishing and running a Fuchsia package to a Fuchsia emulator. + +For the purposes of this walkthrough, we will only target `x86_64-fuchsia`. + +## Compiling a Rust binary targeting Fuchsia + +Today, there are two main ways to build a Rust binary targeting Fuchsia +using the Fuchsia SDK: +1. Allow [rustup] to handle the installation of Fuchsia targets for you. +1. Build a toolchain locally that can target Fuchsia. + +### Targeting Fuchsia with rustup and cargo + +The easiest way to build a Rust binary targeting Fuchsia is by allowing [rustup] +to handle the installation of Fuchsia targets for you. This can be done by issuing +the following commands: + +```sh +rustup target add x86_64-fuchsia +rustup target add aarch64-fuchsia +``` + +After installing our Fuchsia targets, we can now compile a Rust binary that targets +Fuchsia. + +To create our Rust project, we can issue a standard `cargo` command as follows: + +**From base working directory** +```sh +cargo new hello_fuchsia +``` + +The rest of this walkthrough will take place from `hello_fuchsia`, so we can +change into that directory now: + +```sh +cd hello_fuchsia +``` + +*Note: From this point onwards, all commands will be issued from the `hello_fuchsia/` +directory, and all `hello_fuchsia/` prefixes will be removed from references for sake of brevity.* + +We can edit our `src/main.rs` to include a test as follows: + +**`src/main.rs`** +```rust +fn main() { + println!("Hello Fuchsia!"); +} + +#[test] +fn it_works() { + assert_eq!(2 + 2, 4); +} +``` + +In addition to the standard workspace created, we will want to create a +`.cargo/config.toml` file to link necessary libraries +during compilation: + +**`.cargo/config.toml`** +```txt +[target.x86_64-fuchsia] + +rustflags = [ + "-Lnative=<SDK_PATH>/arch/x64/lib", + "-Lnative=<SDK_PATH>/arch/x64/sysroot/lib" +] +``` + +*Note: Make sure to fill out `<SDK_PATH>` with the path to the downloaded [Fuchsia SDK].* + +These options configure the following: + +* `-Lnative=${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from + the SDK +* `-Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia sysroot + libraries from the SDK + +In total, our new project will look like: + +**Current directory structure** +```txt +hello_fuchsia/ +┣━ src/ +┃ ┗━ main.rs +┣━ Cargo.toml +┗━ .cargo/ + ┗━ config.toml +``` + +Finally, we can build our rust binary as: + +```sh +cargo build --target x86_64-fuchsia +``` + +Now we have a Rust binary at `target/x86_64-fuchsia/debug/hello_fuchsia`, +targeting our desired Fuchsia target. + +**Current directory structure** +```txt +hello_fuchsia/ +┣━ src/ +┃ ┗━ main.rs +┣━ target/ +┃ ┗━ x86_64-fuchsia/ +┃ ┗━ debug/ +┃ ┗━ hello_fuchsia +┣━ Cargo.toml +┗━ .cargo/ + ┗━ config.toml +``` + +### Targeting Fuchsia with a compiler built from source + +An alternative to the first workflow is to target Fuchsia by using +`rustc` built from source. Before building Rust for Fuchsia, you'll need a clang toolchain that supports Fuchsia as well. A recent version (14+) of clang should be sufficient to compile Rust for Fuchsia. -You'll also need a recent copy of the [Fuchsia SDK], which provides the tools -and binaries required to build and link programs for Fuchsia. - -[Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core - x86-64 and AArch64 Fuchsia targets can be enabled using the following configuration. @@ -53,12 +196,6 @@ In `config.toml`, add: ```toml [build] target = ["<host_platform>", "aarch64-fuchsia", "x86_64-fuchsia"] - -[target.x86_64-fuchsia] -llvm-libunwind = "in-tree" - -[target.aarch64-fuchsia] -llvm-libunwind = "in-tree" ``` Additionally, the following environment variables must be configured (for @@ -81,15 +218,21 @@ export CARGO_TARGET_X86_64_FUCHSIA_RUSTFLAGS="-C link-arg=--sysroot=${SDK_PATH}/ These can be run together in a shell environment by executing `(source config-env.sh && ./x.py install)`. -## Building Rust programs +Once `rustc` is installed, we can create a new working directory to work from, +`hello_fuchsia` along with `hello_fuchsia/src`: -After compiling Rust binaries, you'll need to build a component, package it, and -serve it to a Fuchsia device or emulator. All of this can be done using the -Fuchsia SDK. +```sh +mkdir hello_fuchsia +cd hello_fuchsia +mkdir src +``` + +*Note: From this point onwards, all commands will be issued from the `hello_fuchsia/` +directory, and all `hello_fuchsia/` prefixes will be removed from references for sake of brevity.* -As an example, we'll compile and run this simple program on a Fuchsia emulator: +There, we can create a new file named `src/hello_fuchsia.rs`: -**`hello_fuchsia.rs`** +**`src/hello_fuchsia.rs`** ```rust fn main() { println!("Hello Fuchsia!"); @@ -101,45 +244,113 @@ fn it_works() { } ``` -Create a new file named `hello_fuchsia.rs` and fill out its contents with that -code. +**Current directory structure** +```txt +hello_fuchsia/ +┗━ src/ + ┗━ hello_fuchsia.rs +``` + +Using your freshly installed `rustc`, you can compile a binary for Fuchsia using +the following options: + +* `--target x86_64-fuchsia`/`--target aarch64-fuchsia`: Targets the Fuchsia + platform of your choice +* `-Lnative ${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from + the SDK +* `-Lnative ${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia sysroot + libraries from the SDK -### Create a package +Putting it all together: +```sh +# Configure these for the Fuchsia target of your choice +TARGET_ARCH="<x86_64-fuchsia|aarch64-fuchsia>" +ARCH="<x64|aarch64>" + +rustc \ + --target ${TARGET_ARCH} \ + -Lnative=${SDK_PATH}/arch/${ARCH}/lib \ + -Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib \ + --out-dir bin src/hello_fuchsia.rs +``` + +**Current directory structure** +```txt +hello_fuchsia/ +┣━ src/ +┃ ┗━ hello_fuchsia.rs +┗━ bin/ + ┗━ hello_fuchsia +``` + +## Creating a Fuchsia package + +Before moving on, double check your directory structure: + +**Current directory structure** +```txt +hello_fuchsia/ +┣━ src/ (if using rustc) +┃ ┗━ hello_fuchsia.rs ... +┣━ bin/ ... +┃ ┗━ hello_fuchsia ... +┣━ src/ (if using cargo) +┃ ┗━ main.rs ... +┗━ target/ ... + ┗━ x86_64-fuchsia/ ... + ┗━ debug/ ... + ┗━ hello_fuchsia ... +``` + +With our Rust binary built, we can move to creating a Fuchsia package. On Fuchsia, a package is the unit of distribution for software. We'll need to create a new package directory where we will place files like our finished -binary and any data it may need. The working directory will have this layout: +binary and any data it may need. + +To start, make the `pkg`, and `pkg/meta` directories: + +```sh +mkdir pkg +mkdir pkg/meta +``` +**Current directory structure** ```txt -hello_fuchsia.rs -hello_fuchsia.cml -package -┣━ bin -┃ ┗━ hello_fuchsia -┣━ meta -┃ ┣━ package -┃ ┗━ hello_fuchsia.cm -┗━ hello_fuchsia.manifest +hello_fuchsia/ +┗━ pkg/ + ┗━ meta/ ``` -Make the `package`, `package/bin`, and `package/meta` directories and create the -following files inside: +Now, create the following files inside: -**`package/meta/package`** +**`pkg/meta/package`** ```json -{"name":"hello_fuchsia","version":0} +{ + "name": "hello_fuchsia", + "version": "0" +} ``` The `package` file describes our package's name and version number. Every package must contain one. -**`package/hello_fuchsia.manifest`** +**`pkg/hello_fuchsia.manifest` if using cargo** +```txt +bin/hello_fuchsia=target/x86_64-fuchsia/debug/hello_fuchsia +lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1 +lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so +meta/package=pkg/meta/package +meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm +``` + +**`pkg/hello_fuchsia.manifest` if using rustc** ```txt -bin/hello_fuchsia=package/bin/hello_fuchsia +bin/hello_fuchsia=bin/hello_fuchsia lib/ld.so.1=<SDK_PATH>/arch/x64/sysroot/dist/lib/ld.so.1 lib/libfdio.so=<SDK_PATH>/arch/x64/dist/libfdio.so -meta/package=package/meta/package -meta/hello_fuchsia.cm=package/meta/hello_fuchsia.cm +meta/package=pkg/meta/package +meta/hello_fuchsia.cm=pkg/meta/hello_fuchsia.cm ``` *Note: Relative manifest paths are resolved starting from the working directory @@ -147,42 +358,26 @@ of `pm`. Make sure to fill out `<SDK_PATH>` with the path to the downloaded SDK.* The `.manifest` file will be used to describe the contents of the package by -relating their location when installed to their location on the file system. You -can use this to make a package pull files from other places, but for this -example we'll just be placing everything in the `package` directory. - -### Compiling a binary - -Using your freshly compiled `rustc`, you can compile a binary for Fuchsia using -the following options: +relating their location when installed to their location on the file system. The +`bin/hello_fuchsia=` entry will be different depending on how your Rust binary +was built, so choose accordingly. -* `--target x86_64-fuchsia`/`--target aarch64-fuchsia`: Targets the Fuchsia - platform of your choice -* `-Lnative ${SDK_PATH}/arch/${ARCH}/lib`: Link against Fuchsia libraries from - the SDK -* `-Lnative ${SDK_PATH}/arch/${ARCH}/sysroot/lib`: Link against Fuchsia kernel - libraries from the SDK - -Putting it all together: - -```sh -# Configure these for the Fuchsia target of your choice -TARGET_ARCH="<x86_64-fuchsia|aarch64-fuchsia>" -ARCH="<x64|aarch64>" - -rustc --target ${TARGET_ARCH} -Lnative=${SDK_PATH}/arch/${ARCH}/lib -Lnative=${SDK_PATH}/arch/${ARCH}/sysroot/lib -o package/bin/hello_fuchsia hello_fuchsia.rs +**Current directory structure** +```txt +hello_fuchsia/ +┗━ pkg/ + ┣━ meta/ + ┃ ┗━ package + ┗━ hello_fuchsia.manifest ``` -### Bulding a component +### Creating a Fuchsia component -On Fuchsia, components require a component manifest written in Fuchia's markup +On Fuchsia, components require a component manifest written in Fuchsia's markup language called CML. The Fuchsia devsite contains an [overview of CML] and a [reference for the file format]. Here's a basic one that can run our single binary: -[overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests -[reference for the file format]: https://fuchsia.dev/reference/cml - -**`hello_fuchsia.cml`** +**`pkg/hello_fuchsia.cml`** ```txt { include: [ "syslog/client.shard.cml" ], @@ -193,43 +388,154 @@ language called CML. The Fuchsia devsite contains an [overview of CML] and a } ``` +**Current directory structure** +```txt +hello_fuchsia/ +┗━ pkg/ + ┣━ meta/ + ┃ ┗━ package + ┣━ hello_fuchsia.manifest + ┗━ hello_fuchsia.cml +``` + Now we can compile that CML into a component manifest: ```sh -${SDK_PATH}/tools/${ARCH}/cmc compile hello_fuchsia.cml --includepath ${SDK_PATH}/pkg -o package/meta/hello_fuchsia.cm +${SDK_PATH}/tools/${ARCH}/cmc compile \ + pkg/hello_fuchsia.cml \ + --includepath ${SDK_PATH}/pkg \ + -o pkg/meta/hello_fuchsia.cm ``` -`--includepath` tells the compiler where to look for `include`s from our CML. -In our case, we're only using `syslog/client.shard.cml`. +*Note: `--includepath` tells the compiler where to look for `include`s from our CML. +In our case, we're only using `syslog/client.shard.cml`.* -### Building and publishing a package +**Current directory structure** +```txt +hello_fuchsia/ +┗━ pkg/ + ┣━ meta/ + ┃ ┣━ package + ┃ ┗━ hello_fuchsia.cm + ┣━ hello_fuchsia.manifest + ┗━ hello_fuchsia.cml +``` -Next, we'll build our package as defined by our manifest: +### Building a Fuchsia package + +Next, we'll build a package manifest as defined by our manifest: ```sh -${SDK_PATH}/tools/${ARCH}/pm -o hello_fuchsia -m package/hello_fuchsia.manifest build -output-package-manifest hello_fuchsia_manifest +${SDK_PATH}/tools/${ARCH}/pm \ + -api-level $(${SDK_PATH}/tools/${ARCH}/ffx version -v | grep "api-level" | head -1 | awk -F ' ' '{print $2}') \ + -o pkg/hello_fuchsia_manifest \ + -m pkg/hello_fuchsia.manifest \ + build \ + -output-package-manifest pkg/hello_fuchsia_package_manifest +``` + +This will produce `pkg/hello_fuchsia_manifest/` which is a package manifest we can +publish directly to a repository. + +**Current directory structure** +```txt +hello_fuchsia/ +┗━ pkg/ + ┣━ meta/ + ┃ ┣━ package + ┃ ┗━ hello_fuchsia.cm + ┣━ hello_fuchsia_manifest/ + ┃ ┗━ ... + ┣━ hello_fuchsia.manifest + ┣━ hello_fuchsia.cml + ┗━ hello_fuchsia_package_manifest ``` -This will produce `hello_fuchsia_manifest` which is a package manifest we can -publish directly to a repository. We can set up that repository with: +We are now ready to publish the package. + +## Publishing a Fuchsia package + +With our package and component manifests setup, +we can now publish our package. The first step will +be to create a Fuchsia package repository to publish +to. + +### Creating a Fuchsia package repository + +We can set up our repository with: ```sh -${SDK_PATH}/tools/${ARCH}/pm newrepo -repo repo +${SDK_PATH}/tools/${ARCH}/pm newrepo \ + -repo pkg/repo ``` -And then publish our new package to that repository with: +**Current directory structure** +```txt +hello_fuchsia/ +┗━ pkg/ + ┣━ meta/ + ┃ ┣━ package + ┃ ┗━ hello_fuchsia.cm + ┣━ hello_fuchsia_manifest/ + ┃ ┗━ ... + ┣━ repo/ + ┃ ┗━ ... + ┣━ hello_fuchsia.manifest + ┣━ hello_fuchsia.cml + ┗━ hello_fuchsia_package_manifest +``` + +## Publishing Fuchsia package to repository + +We can publish our new package to that repository with: ```sh -${SDK_PATH}/tools/${ARCH}/pm publish -repo repo -lp -f <(echo "hello_fuchsia_manifest") +${SDK_PATH}/tools/${ARCH}/pm publish \ + -repo pkg/repo \ + -lp -f <(echo "pkg/hello_fuchsia_package_manifest") ``` -Then we can add it to `ffx`'s package server as `hello-fuchsia` using: +Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using: ```sh -${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm repo -r hello-fuchsia +${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \ + pkg/repo \ + -r hello-fuchsia +``` + +## Running a Fuchsia component on an emulator + +At this point, we are ready to run our Fuchsia +component. For reference, our final directory +structure will look like: + +**Final directory structure** +```txt +hello_fuchsia/ +┣━ src/ (if using rustc) +┃ ┗━ hello_fuchsia.rs ... +┣━ bin/ ... +┃ ┗━ hello_fuchsia ... +┣━ src/ (if using cargo) +┃ ┗━ main.rs ... +┣━ target/ ... +┃ ┗━ x86_64-fuchsia/ ... +┃ ┗━ debug/ ... +┃ ┗━ hello_fuchsia ... +┗━ pkg/ + ┣━ meta/ + ┃ ┣━ package + ┃ ┗━ hello_fuchsia.cm + ┣━ hello_fuchsia_manifest/ + ┃ ┗━ ... + ┣━ repo/ + ┃ ┗━ ... + ┣━ hello_fuchsia.manifest + ┣━ hello_fuchsia.cml + ┗━ hello_fuchsia_package_manifest ``` -### Starting the emulator +### Starting the Fuchsia emulator Start a Fuchsia emulator in a new terminal using: @@ -238,39 +544,85 @@ ${SDK_PATH}/tools/${ARCH}/ffx product-bundle get workstation_eng.qemu-${ARCH} ${SDK_PATH}/tools/${ARCH}/ffx emu start workstation_eng.qemu-${ARCH} --headless ``` -Then, once the emulator has been started: +### Watching emulator logs + +Once the emulator is running, open a separate terminal to watch the emulator logs: + +**In separate terminal** +```sh +${SDK_PATH}/tools/${ARCH}/ffx log \ + --since now +``` + +### Serving a Fuchsia package + +Now, start a package repository server to serve our +package to the emulator: ```sh -${SDK_PATH}/tools/${ARCH}/ffx target repository register +${SDK_PATH}/tools/${ARCH}/ffx repository server start ``` -And watch the logs from the emulator in a separate terminal: +Once the repository server is up and running, register it with the target Fuchsia system running in the emulator: ```sh -${SDK_PATH}/tools/${ARCH}/ffx log --since now +${SDK_PATH}/tools/${ARCH}/ffx target repository register \ + --repository hello-fuchsia ``` +### Running a Fuchsia component + Finally, run the component: ```sh -${SDK_PATH}/tools/${ARCH}/ffx component run fuchsia-pkg://hello-fuchsia/hello_fuchsia#meta/hello_fuchsia.cm +${SDK_PATH}/tools/${ARCH}/ffx component run \ + /core/ffx-laboratory:hello_fuchsia \ + fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm ``` On reruns of the component, the `--recreate` argument may also need to be passed. +```sh +${SDK_PATH}/tools/${ARCH}/ffx component run \ + --recreate \ + /core/ffx-laboratory:hello_fuchsia \ + fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm +``` + +## `.gitignore` extensions + +Optionally, we can create/extend our `.gitignore` file to ignore files and +directories that are not helpful to track: + +```txt +pkg/repo +pkg/meta/hello_fuchsia.cm +pkg/hello_fuchsia_manifest +pkg/hello_fuchsia_package_manifest +``` + ## Testing ### Running unit tests -Tests can be run in the same way as a regular binary, simply by passing `--test` -to the `rustc` invocation and then repackaging and rerunning. The test harness -will run the applicable unit tests. +Tests can be run in the same way as a regular binary. + +* If using `cargo`, you can simply pass `test --no-run` +to the `cargo` invocation and then repackage and rerun the Fuchsia package. From our previous example, +this would look like `cargo test --target x86_64-fuchsia --no-run`, and moving the executable +binary path found from the line `Executable unittests src/main.rs (target/x86_64-fuchsia/debug/deps/hello_fuchsia-<HASH>)` +into `pkg/hello_fuchsia.manifest`. + +* If using the compiled `rustc`, you can simply pass `--test` +to the `rustc` invocation and then repackage and rerun the Fuchsia package. + +The test harness will run the applicable unit tests. Often when testing, you may want to pass additional command line arguments to your binary. Additional arguments can be set in the component manifest: -**`hello_fuchsia.cml`** +**`pkg/hello_fuchsia.cml`** ```txt { include: [ "syslog/client.shard.cml" ], @@ -285,11 +637,148 @@ your binary. Additional arguments can be set in the component manifest: This will pass the argument `it_works` to the binary, filtering the tests to only those tests that match the pattern. There are many more configuration options available in CML including environment variables. More documentation is -available on the [Fuchsia devsite](https://fuchsia.dev/reference/cml). +available on the [Fuchsia devsite]. ### Running the compiler test suite Running the Rust test suite on Fuchsia is [not currently supported], but work is underway to enable it. +## Debugging + +### `zxdb` + +Debugging components running on a Fuchsia emulator can be done using the +console-mode debugger: [zxdb]. We will demonstrate attaching necessary symbol +paths to debug our `hello-fuchsia` component. + +### Attaching `zxdb` + +In a separate terminal, issue the following command from our `hello_fuchsia` +directory to launch `zxdb`: + +**In separate terminal** +```sh +${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \ + --symbol-path target/x86_64-fuchsia/debug +``` + +* `--symbol-path` gets required symbol paths, which are +necessary for stepping through your program. + +The "[displaying source code in `zxdb`](#displaying-source-code-in-zxdb)" section describes how you can +display Rust and/or Fuchsia source code in your debugging session. + +### Using `zxdb` + +Once launched, you will be presented with the window: + +```sh +Connecting (use "disconnect" to cancel)... +Connected successfully. +👉 To get started, try "status" or "help". +[zxdb] +``` + +To attach to our program, we can run: + +```sh +[zxdb] attach hello_fuchsia +``` + +**Expected output** +```sh +Waiting for process matching "hello_fuchsia". +Type "filter" to see the current filters. +``` + +Next, we can create a breakpoint at main using "b main": + +```sh +[zxdb] b main +``` + +**Expected output** +```sh +Created Breakpoint 1 @ main +``` + +Finally, we can re-run the "hello_fuchsia" component from our original +terminal: + +```sh +${SDK_PATH}/tools/${ARCH}/ffx component run \ + --recreate \ + fuchsia-pkg://hello-fuchsia/hello_fuchsia_manifest#meta/hello_fuchsia.cm +``` + +Once our component is running, our `zxdb` window will stop execution +in our main as desired: + +**Expected output** +```txt +Breakpoint 1 now matching 1 addrs for main +🛑 on bp 1 hello_fuchsia::main() • main.rs:2 + 1 fn main() { + ▶ 2 println!("Hello Fuchsia!"); + 3 } + 4 +[zxdb] +``` + +`zxdb` has similar commands to other debuggers like [gdb]. +To list the available commands, run "help" in the +`zxdb` window or visit [the zxdb documentation]. + +```sh +[zxdb] help +``` + +**Expected output** +```sh +Help! + + Type "help <command>" for command-specific help. + +Other help topics (see "help <topic>") +... +``` + +### Displaying source code in `zxdb` + +By default, the debugger will not be able to display +source code while debugging. For our user code, we displayed +source code by pointing our debugger to our debug binary via +the `--symbol-path` arg. To display library source code in +the debugger, you must provide paths to the source using +`--build-dir`. For example, to display the Rust and Fuchsia +source code: + +```sh +${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \ + --symbol-path target/x86_64-fuchsia/debug \ + --build-dir ${RUST_SRC_PATH}/rust \ + --build-dir ${FUCHSIA_SRC_PATH}/fuchsia/out/default +``` + + * `--build-dir` links against source code paths, which + are not strictly necessary for debugging, but is a nice-to-have + for displaying source code in `zxdb`. + + Linking to a Fuchsia checkout can help with debugging Fuchsia libraries, + such as [fdio]. + +[Fuchsia team]: https://team-api.infra.rust-lang.org/v1/teams/fuchsia.json +[Fuchsia]: https://fuchsia.dev/ +[source tree]: https://fuchsia.dev/fuchsia-src/get-started/learn/build +[rustup]: https://rustup.rs/ +[cargo]: https://doc.rust-lang.org/cargo/ +[Fuchsia SDK]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core +[overview of CML]: https://fuchsia.dev/fuchsia-src/concepts/components/v2/component_manifests +[reference for the file format]: https://fuchsia.dev/reference/cml +[Fuchsia devsite]: https://fuchsia.dev/reference/cml [not currently supported]: https://fxbug.dev/105393 +[zxdb]: https://fuchsia.dev/fuchsia-src/development/debugger +[gdb]: https://www.sourceware.org/gdb/ +[the zxdb documentation]: https://fuchsia.dev/fuchsia-src/development/debugger +[fdio]: https://cs.opensource.google/fuchsia/fuchsia/+/main:sdk/lib/fdio/ diff --git a/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md index d325ba334..b18a125f3 100644 --- a/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md +++ b/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md @@ -87,7 +87,7 @@ Rust programs can be built for that target: rustc --target m68k-unknown-linux-gnu your-code.rs ``` -Very simple progams can be run using the `qemu-m68k-static` program: +Very simple programs can be run using the `qemu-m68k-static` program: ```text $ qemu-m68k-static your-code diff --git a/src/doc/rustc/src/platform-support/openbsd.md b/src/doc/rustc/src/platform-support/openbsd.md index b2ac776ea..4ce80157d 100644 --- a/src/doc/rustc/src/platform-support/openbsd.md +++ b/src/doc/rustc/src/platform-support/openbsd.md @@ -12,6 +12,8 @@ The target names follow this format: `$ARCH-unknown-openbsd`, where `$ARCH` spec |--------------------------------|-------------|------------------| | `aarch64-unknown-openbsd` | libc++ | [64-bit ARM systems](https://www.openbsd.org/arm64.html) | | `i686-unknown-openbsd` | libc++ | [Standard PC and clones based on the Intel i386 architecture and compatible processors](https://www.openbsd.org/i386.html) | +| `powerpc64-unknown-openbsd` | libc++ | [IBM POWER-based PowerNV systems](https://www.openbsd.org/powerpc64.html) | +| `riscv64gc-unknown-openbsd` | libc++ | [64-bit RISC-V systems](https://www.openbsd.org/riscv64.html) | | `sparc64-unknown-openbsd` | estdc++ | [Sun UltraSPARC and Fujitsu SPARC64 systems](https://www.openbsd.org/sparc64.html) | | `x86_64-unknown-openbsd` | libc++ | [AMD64-based systems](https://www.openbsd.org/amd64.html) | 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 721c234c6..fb0cea05d 100644 --- a/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md +++ b/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md @@ -25,7 +25,7 @@ Like with any other Windows target created binaries are in PE format. ## Building the target -For cross-compilation I recommend using [llvm-mingw](https://github.com/mstorsjo/llvm-mingw) toolchain, one change that seems necessary beside configuring corss compilers is disabling experimental `m86k` target. Otherwise LLVM build fails with `multiple definition ...` errors. +For cross-compilation I recommend using [llvm-mingw](https://github.com/mstorsjo/llvm-mingw) toolchain, one change that seems necessary beside configuring cross compilers is disabling experimental `m86k` target. Otherwise LLVM build fails with `multiple definition ...` errors. Native bootstrapping builds require rather fragile hacks until host artifacts are available so I won't describe them here. ## Building Rust programs diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md index 8f90d9c74..295dec0f0 100644 --- a/src/doc/rustc/src/platform-support/unknown-uefi.md +++ b/src/doc/rustc/src/platform-support/unknown-uefi.md @@ -133,7 +133,7 @@ There are 3 common ways to compile native C code for UEFI targets: - Use native Windows targets. This means compiling your C code for the Windows platform as if it was the UEFI platform. This works for static libraries, but needs adjustments when linking into an UEFI executable. You can, however, - link such static libraries seemlessly into rust code compiled for UEFI + link such static libraries seamlessly into rust code compiled for UEFI targets. Be wary of any includes that are not specifically suitable for UEFI targets (especially the C standard library includes are not always compatible). Freestanding compilations are recommended to avoid diff --git a/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md index 021b904de..6932e6a57 100644 --- a/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md @@ -30,7 +30,7 @@ is 8-bytes large as well as pointers. The tradeoff, though, is that the maximum memory size is now the full 64-bit address space instead of the 4GB as limited by the 32-bit address space for `wasm32-unknown-unknown`. -This target is not a stable target. The [memory64] WebAssembly proposal is stil +This target is not a stable target. The [memory64] WebAssembly proposal is still in-progress and not standardized. This means that there are not many engines which implement the `memory64` feature and if they do they're likely behind a flag, for example: diff --git a/src/doc/rustdoc/book.toml b/src/doc/rustdoc/book.toml index 45405a117..dfa685785 100644 --- a/src/doc/rustdoc/book.toml +++ b/src/doc/rustdoc/book.toml @@ -6,5 +6,9 @@ title = "The rustdoc book" git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustdoc" [output.html.redirect] +"/what-to-include.html" = "write-documentation/what-to-include.html" "/the-doc-attribute.html" = "write-documentation/the-doc-attribute.html" +"/linking-to-items-by-name.html" = "write-documentation/linking-to-items-by-name.html" "/documentation-tests.html" = "write-documentation/documentation-tests.html" +"/website-features.html" = "advanced-features.html#custom-search-engines" +"/passes.html" = "deprecated-features.html#passes" diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md index bfa92e7d3..321992f7b 100644 --- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md @@ -143,7 +143,7 @@ fn do_features() {} #[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in names() // and because no value checking was enable for "has_feathers" - // no warning is emited for the value "zapping" + // no warning is emitted for the value "zapping" fn do_zapping() {} #[cfg(has_mumble_frotz)] // This is UNEXPECTED because names checking is enable and diff --git a/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md b/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md index 977d25852..3890a12b7 100644 --- a/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md +++ b/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md @@ -8,7 +8,7 @@ This flag will rewrite absolute paths under the current working directory, replacing the current working directory prefix with a specified value. The given value may be absolute or relative, or empty. This switch takes -precidence over `--remap-path-prefix` in case they would both match a given +precedence over `--remap-path-prefix` in case they would both match a given path. This flag helps to produce deterministic output, by removing the current working diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 7f7549aaf..b33405f18 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -9,17 +9,17 @@ The tracking issues for this feature are: This feature allows for use of one of following sanitizers: -* [AddressSanitizer][clang-asan] a fast memory error detector. -* [ControlFlowIntegrity][clang-cfi] LLVM Control Flow Integrity (CFI) provides +* [AddressSanitizer](#addresssanitizer) a fast memory error detector. +* [ControlFlowIntegrity](#controlflowintegrity) LLVM Control Flow Integrity (CFI) provides forward-edge control flow protection. -* [HWAddressSanitizer][clang-hwasan] a memory error detector similar to +* [HWAddressSanitizer](#hwaddresssanitizer) a memory error detector similar to AddressSanitizer, but based on partial hardware assistance. -* [LeakSanitizer][clang-lsan] a run-time memory leak detector. -* [MemorySanitizer][clang-msan] a detector of uninitialized reads. -* [MemTagSanitizer][clang-memtag] fast memory error detector based on +* [LeakSanitizer](#leaksanitizer) a run-time memory leak detector. +* [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads. +* [MemTagSanitizer](#memtagsanitizer) fast memory error detector based on Armv8.5-A Memory Tagging Extension. -* [ShadowCallStack][clang-scs] provides backward-edge control flow protection. -* [ThreadSanitizer][clang-tsan] a fast data race detector. +* [ShadowCallStack](#shadowcallstack) provides backward-edge control flow protection. +* [ThreadSanitizer](#threadsanitizer) a fast data race detector. To enable a sanitizer compile with `-Zsanitizer=address`,`-Zsanitizer=cfi`, `-Zsanitizer=hwaddress`, `-Zsanitizer=leak`, `-Zsanitizer=memory`, @@ -58,6 +58,8 @@ AddressSanitizer works with non-instrumented code although it will impede its ability to detect some bugs. It is not expected to produce false positive reports. +See the [Clang AddressSanitizer documentation][clang-asan] for more details. + ## Examples Stack buffer overflow: @@ -204,6 +206,8 @@ tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)). LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto). +See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details. + ## Example ```text @@ -430,6 +434,8 @@ HWAddressSanitizer requires `tagged-globals` target feature to instrument globals. To enable this target feature compile with `-C target-feature=+tagged-globals` +See the [Clang HWAddressSanitizer documentation][clang-hwasan] for more details. + ## Example Heap buffer overflow: @@ -507,6 +513,8 @@ LeakSanitizer is supported on the following targets: * `x86_64-apple-darwin` * `x86_64-unknown-linux-gnu` +See the [Clang LeakSanitizer documentation][clang-lsan] for more details. + # MemorySanitizer MemorySanitizer is detector of uninitialized reads. @@ -521,6 +529,8 @@ MemorySanitizer requires all program code to be instrumented. C/C++ dependencies need to be recompiled using Clang with `-fsanitize=memory` option. Failing to achieve that will result in false positive reports. +See the [Clang MemorySanitizer documentation][clang-msan] for more details. + ## Example Detecting the use of uninitialized memory. The `-Zbuild-std` flag rebuilds and @@ -569,7 +579,7 @@ MemTagSanitizer is supported on the following targets: MemTagSanitizer requires hardware support and the `mte` target feature. To enable this target feature compile with `-C target-feature="+mte"`. -More information can be found in the associated [LLVM documentation](https://llvm.org/docs/MemTagSanitizer.html). +See the [LLVM MemTagSanitizer documentation][llvm-memtag] for more details. # ShadowCallStack @@ -581,7 +591,9 @@ ShadowCallStack can be enabled with `-Zsanitizer=shadow-call-stack` option and i * `aarch64-linux-android` -A runtime must be provided by the application or operating system. See the [LLVM documentation][clang-scs] for further details. +A runtime must be provided by the application or operating system. + +See the [Clang ShadowCallStack documentation][clang-scs] for more details. # ThreadSanitizer @@ -604,6 +616,8 @@ can lead to false positive reports. ThreadSanitizer does not support atomic fences `std::sync::atomic::fence`, nor synchronization performed using inline assembly code. +See the [Clang ThreadSanitizer documentation][clang-tsan] for more details. + ## Example ```rust @@ -673,6 +687,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT * [HWAddressSanitizer in Clang][clang-hwasan] * [LeakSanitizer in Clang][clang-lsan] * [MemorySanitizer in Clang][clang-msan] +* [MemTagSanitizer in LLVM][llvm-memtag] * [ThreadSanitizer in Clang][clang-tsan] [clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html @@ -682,3 +697,4 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html [clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html +[llvm-memtag]: https://llvm.org/docs/MemTagSanitizer.html diff --git a/src/doc/unstable-book/src/language-features/raw-dylib.md b/src/doc/unstable-book/src/language-features/raw-dylib.md index 23fc5b305..5fd208ae7 100644 --- a/src/doc/unstable-book/src/language-features/raw-dylib.md +++ b/src/doc/unstable-book/src/language-features/raw-dylib.md @@ -26,9 +26,9 @@ fn main() { ## Limitations -Currently, this feature is only supported on `-windows-msvc` targets. Non-Windows platforms don't have import -libraries, and an incompatibility between LLVM and the BFD linker means that it is not currently supported on -`-windows-gnu` targets. +This feature is unstable for the `x86` architecture, and stable for all other architectures. -On the `i686-pc-windows-msvc` target, this feature supports only the `cdecl`, `stdcall`, `system`, and `fastcall` -calling conventions. +This feature is only supported on Windows. + +On the `x86` architecture, this feature supports only the `cdecl`, `stdcall`, `system`, `fastcall`, and +`vectorcall` calling conventions. diff --git a/src/doc/unstable-book/src/language-features/unix-sigpipe.md b/src/doc/unstable-book/src/language-features/unix-sigpipe.md new file mode 100644 index 000000000..aa39b6eb2 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/unix-sigpipe.md @@ -0,0 +1,54 @@ +# `unix_sigpipe` + +The tracking issue for this feature is: [#97889] + +[#97889]: https://github.com/rust-lang/rust/issues/97889 + +--- + +The `#[unix_sigpipe = "..."]` attribute on `fn main()` can be used to specify how libstd shall setup `SIGPIPE` on Unix platforms before invoking `fn main()`. This attribute is ignored on non-Unix targets. There are three variants: +* `#[unix_sigpipe = "inherit"]` +* `#[unix_sigpipe = "sig_dfl"]` +* `#[unix_sigpipe = "sig_ign"]` + +## `#[unix_sigpipe = "inherit"]` + +Leave `SIGPIPE` untouched before entering `fn main()`. Unless the parent process has changed the default `SIGPIPE` handler from `SIG_DFL` to something else, this will behave the same as `#[unix_sigpipe = "sig_dfl"]`. + +## `#[unix_sigpipe = "sig_dfl"]` + +Set the `SIGPIPE` handler to `SIG_DFL`. This will result in your program getting killed if it tries to write to a closed pipe. This is normally what you want if your program produces textual output. + +### Example + +```rust,no_run +#![feature(unix_sigpipe)] +#[unix_sigpipe = "sig_dfl"] +fn main() { loop { println!("hello world"); } } +``` + +```bash +% ./main | head -n 1 +hello world +``` + +## `#[unix_sigpipe = "sig_ign"]` + +Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers. + +This is what libstd has done by default since 2014. Omitting `#[unix_sigpipe = "..."]` is the same as having `#[unix_sigpipe = "sig_ign"]`. + +### Example + +```rust,no_run +#![feature(unix_sigpipe)] +#[unix_sigpipe = "sig_ign"] +fn main() { loop { println!("hello world"); } } +``` + +```bash +% ./main | head -n 1 +hello world +thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', library/std/src/io/stdio.rs:1016:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` |