diff options
Diffstat (limited to '')
132 files changed, 1663 insertions, 636 deletions
diff --git a/src/doc/book/.github/workflows/main.yml b/src/doc/book/.github/workflows/main.yml index 64ab49c51..65574a070 100644 --- a/src/doc/book/.github/workflows/main.yml +++ b/src/doc/book/.github/workflows/main.yml @@ -12,8 +12,8 @@ jobs: - name: Install Rust run: | rustup set profile minimal - rustup toolchain install 1.65 -c rust-docs - rustup default 1.65 + rustup toolchain install 1.67 -c rust-docs + rustup default 1.67 - name: Install mdbook run: | mkdir bin diff --git a/src/doc/book/CONTRIBUTING.md b/src/doc/book/CONTRIBUTING.md index 3c9500687..a58ea4203 100644 --- a/src/doc/book/CONTRIBUTING.md +++ b/src/doc/book/CONTRIBUTING.md @@ -38,11 +38,13 @@ that governs all sub-projects, including this one. Please respect it! ## Expectations -Because the book is [printed](https://nostarch.com/rust), and because we want +Because the book is [printed][nostarch], and because we want to keep the online version of the book close to the print version when possible, it may take longer than you're used to for us to address your issue or pull request. +[nostarch]: https://nostarch.com/rust-programming-language-2nd-edition + So far, we've been doing a larger revision to coincide with [Rust Editions](https://doc.rust-lang.org/edition-guide/). Between those larger revisions, we will only be correcting errors. If your issue or pull request diff --git a/src/doc/book/README.md b/src/doc/book/README.md index 94e1a004a..f6341efc9 100644 --- a/src/doc/book/README.md +++ b/src/doc/book/README.md @@ -6,7 +6,7 @@ This repository contains the source of "The Rust Programming Language" book. [The book is available in dead-tree form from No Starch Press][nostarch]. -[nostarch]: https://nostarch.com/rust +[nostarch]: https://nostarch.com/rust-programming-language-2nd-edition You can also read the book for free online. Please see the book as shipped with the latest [stable], [beta], or [nightly] Rust releases. Be aware that issues @@ -73,7 +73,7 @@ kinds of contributions we're looking for. [contrib]: https://github.com/rust-lang/book/blob/main/CONTRIBUTING.md -Because the book is [printed](https://nostarch.com/rust), and because we want +Because the book is [printed][nostarch], and because we want to keep the online version of the book close to the print version when possible, it may take longer than you're used to for us to address your issue or pull request. diff --git a/src/doc/book/ci/dictionary.txt b/src/doc/book/ci/dictionary.txt index 9eb695d5b..a91df4a03 100644 --- a/src/doc/book/ci/dictionary.txt +++ b/src/doc/book/ci/dictionary.txt @@ -546,6 +546,7 @@ unsafety unsized unsynchronized Unyank +UpperCamelCase URIs UsefulType username diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt index 70a0c930c..3640c0694 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt @@ -18,6 +18,7 @@ error[E0308]: mismatched types = note: expected reference `&String` found reference `&{integer}` note: associated function defined here + --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/cmp.rs:783:8 For more information about this error, try `rustc --explain E0308`. error: could not compile `guessing_game` due to previous error diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt index 8095bbd8d..9517af95f 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt @@ -4,10 +4,10 @@ warning: unused `Result` that must be used --> src/main.rs:10:5 | 10 | io::stdin().read_line(&mut guess); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(unused_must_use)]` on by default = note: this `Result` may be an `Err` variant, which should be handled + = note: `#[warn(unused_must_use)]` on by default warning: `guessing_game` (bin "guessing_game") generated 1 warning Finished dev [unoptimized + debuginfo] target(s) in 0.59s diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt index c0484ea1b..d27a7fae2 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt @@ -8,7 +8,7 @@ error[E0308]: mismatched types | | | implicitly returns `()` as its body has no tail or `return` expression 8 | x + 1; - | - help: remove this semicolon + | - help: remove this semicolon to return this value For more information about this error, try `rustc --explain E0308`. error: could not compile `functions` due to previous error diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt b/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt index 05987f7c8..4a5356701 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/output.txt @@ -12,6 +12,10 @@ error[E0382]: borrow of moved value: `s1` | ^^ value borrowed here after move | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +3 | let s2 = s1.clone(); + | ++++++++ For more information about this error, try `rustc --explain E0382`. error: could not compile `ownership` due to previous error diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt index d4a040e8e..a16dc0180 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/output.txt @@ -8,15 +8,10 @@ error[E0277]: cannot add `Option<i8>` to `i8` | = help: the trait `Add<Option<i8>>` is not implemented for `i8` = help: the following other types implement trait `Add<Rhs>`: - <&'a f32 as Add<f32>> - <&'a f64 as Add<f64>> - <&'a i128 as Add<i128>> - <&'a i16 as Add<i16>> - <&'a i32 as Add<i32>> - <&'a i64 as Add<i64>> <&'a i8 as Add<i8>> - <&'a isize as Add<isize>> - and 48 others + <&i8 as Add<&i8>> + <i8 as Add<&i8>> + <i8 as Add> For more information about this error, try `rustc --explain E0277`. error: could not compile `enums` due to previous error diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt index bec72849a..75d056f84 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/output.txt @@ -7,6 +7,10 @@ error[E0004]: non-exhaustive patterns: `None` not covered | ^ pattern `None` not covered | note: `Option<i32>` defined here + --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/option.rs:518:1 + | + = note: +/rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/option.rs:522:5: not covered = note: the matched value is of type `Option<i32>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/output.txt b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/output.txt index 39b650540..1bc89bf32 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/output.txt +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/output.txt @@ -1,11 +1,5 @@ $ cargo build Compiling restaurant v0.1.0 (file:///projects/restaurant) -error[E0433]: failed to resolve: use of undeclared crate or module `hosting` - --> src/lib.rs:11:9 - | -11 | hosting::add_to_waitlist(); - | ^^^^^^^ use of undeclared crate or module `hosting` - warning: unused import: `crate::front_of_house::hosting` --> src/lib.rs:7:5 | @@ -14,6 +8,12 @@ warning: unused import: `crate::front_of_house::hosting` | = note: `#[warn(unused_imports)]` on by default +error[E0433]: failed to resolve: use of undeclared crate or module `hosting` + --> src/lib.rs:11:9 + | +11 | hosting::add_to_waitlist(); + | ^^^^^^^ use of undeclared crate or module `hosting` + For more information about this error, try `rustc --explain E0433`. warning: `restaurant` (lib) generated 1 warning error: could not compile `restaurant` due to previous error; 1 warning emitted diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-19/output.txt b/src/doc/book/listings/ch08-common-collections/listing-08-19/output.txt index 95577772e..3a682457c 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-19/output.txt +++ b/src/doc/book/listings/ch08-common-collections/listing-08-19/output.txt @@ -14,7 +14,6 @@ error[E0277]: the type `String` cannot be indexed by `{integer}` <String as Index<RangeTo<usize>>> <String as Index<RangeToInclusive<usize>>> <String as Index<std::ops::Range<usize>>> - <str as Index<I>> For more information about this error, try `rustc --explain E0277`. error: could not compile `collections` due to previous error diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/output.txt index 2fa5cf077..e8c31e79e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/output.txt +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/output.txt @@ -10,7 +10,7 @@ test tests::exploration ... ok failures: ---- tests::another stdout ---- -thread 'main' panicked at 'Make this test fail', src/lib.rs:10:9 +thread 'tests::another' panicked at 'Make this test fail', src/lib.rs:10:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/output.txt index 681cfbb81..b0d10deaa 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/output.txt +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/output.txt @@ -11,7 +11,7 @@ failures: ---- tests::this_test_will_fail stdout ---- I got the value 8 -thread 'main' panicked at 'assertion failed: `(left == right)` +thread 'tests::this_test_will_fail' panicked at 'assertion failed: `(left == right)` left: `5`, right: `10`', src/lib.rs:19:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt index 7c62822f7..6fbb5e496 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/output.txt @@ -10,7 +10,7 @@ test tests::smaller_cannot_hold_larger ... ok failures: ---- tests::larger_can_hold_smaller stdout ---- -thread 'main' panicked at 'assertion failed: larger.can_hold(&smaller)', src/lib.rs:28:9 +thread 'tests::larger_can_hold_smaller' panicked at 'assertion failed: larger.can_hold(&smaller)', src/lib.rs:28:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt index 28e2414be..00bf63fff 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/output.txt @@ -9,7 +9,7 @@ test tests::it_adds_two ... FAILED failures: ---- tests::it_adds_two stdout ---- -thread 'main' panicked at 'assertion failed: `(left == right)` +thread 'tests::it_adds_two' panicked at 'assertion failed: `(left == right)` left: `4`, right: `5`', src/lib.rs:11:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt index 3366e3ace..68d724f11 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/output.txt @@ -9,7 +9,7 @@ test tests::greeting_contains_name ... FAILED failures: ---- tests::greeting_contains_name stdout ---- -thread 'main' panicked at 'assertion failed: result.contains(\"Carol\")', src/lib.rs:12:9 +thread 'tests::greeting_contains_name' panicked at 'assertion failed: result.contains(\"Carol\")', src/lib.rs:12:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt index cebebdaee..03d6ad7f1 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/output.txt @@ -9,7 +9,7 @@ test tests::greeting_contains_name ... FAILED failures: ---- tests::greeting_contains_name stdout ---- -thread 'main' panicked at 'Greeting did not contain name, value was `Hello!`', src/lib.rs:12:9 +thread 'tests::greeting_contains_name' panicked at 'Greeting did not contain name, value was `Hello!`', src/lib.rs:12:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt index c176e88b8..0b045e8be 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/output.txt @@ -9,7 +9,7 @@ test tests::greater_than_100 - should panic ... FAILED failures: ---- tests::greater_than_100 stdout ---- -thread 'main' panicked at 'Guess value must be greater than or equal to 1, got 200.', src/lib.rs:13:13 +thread 'tests::greater_than_100' panicked at 'Guess value must be greater than or equal to 1, got 200.', src/lib.rs:13:13 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: panic did not contain expected string panic message: `"Guess value must be greater than or equal to 1, got 200."`, diff --git a/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt b/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt index 4ececf245..bc03145a1 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt +++ b/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/output.txt @@ -20,7 +20,7 @@ failures: ---- tests::this_test_will_fail stdout ---- I got the value 8 -thread 'main' panicked at 'assertion failed: `(left == right)` +thread 'tests::this_test_will_fail' panicked at 'assertion failed: `(left == right)` left: `5`, right: `10`', src/lib.rs:19:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-12/output.txt b/src/doc/book/listings/ch12-an-io-project/listing-12-12/output.txt index c18902518..9870b2125 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-12/output.txt +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-12/output.txt @@ -4,10 +4,10 @@ warning: unused `Result` that must be used --> src/main.rs:19:5 | 19 | run(config); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^ | - = note: `#[warn(unused_must_use)]` on by default = note: this `Result` may be an `Err` variant, which should be handled + = note: `#[warn(unused_must_use)]` on by default warning: `minigrep` (bin "minigrep") generated 1 warning Finished dev [unoptimized + debuginfo] target(s) in 0.71s diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-16/output.txt b/src/doc/book/listings/ch12-an-io-project/listing-12-16/output.txt index 3c34e3945..be4a97eea 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-16/output.txt +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-16/output.txt @@ -9,7 +9,7 @@ test tests::one_result ... FAILED failures: ---- tests::one_result stdout ---- -thread 'main' panicked at 'assertion failed: `(left == right)` +thread 'tests::one_result' panicked at 'assertion failed: `(left == right)` left: `["safe, fast, productive."]`, right: `[]`', src/lib.rs:44:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-14/output.txt b/src/doc/book/listings/ch13-functional-features/listing-13-14/output.txt index 228c764ed..993037991 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-14/output.txt +++ b/src/doc/book/listings/ch13-functional-features/listing-13-14/output.txt @@ -4,10 +4,10 @@ warning: unused `Map` that must be used --> src/main.rs:4:5 | 4 | v1.iter().map(|x| x + 1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(unused_must_use)]` on by default = note: iterators are lazy and do nothing unless consumed + = note: `#[warn(unused_must_use)]` on by default warning: `iterators` (bin "iterators") generated 1 warning Finished dev [unoptimized + debuginfo] target(s) in 0.47s diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt b/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt index d5522cd53..04b6976fe 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt @@ -4,11 +4,11 @@ error[E0072]: recursive type `List` has infinite size --> src/main.rs:1:1 | 1 | enum List { - | ^^^^^^^^^ recursive type has infinite size + | ^^^^^^^^^ 2 | Cons(i32, List), | ---- recursive without indirection | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `List` representable +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | 2 | Cons(i32, Box<List>), | ++++ + diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-23/output.txt b/src/doc/book/listings/ch15-smart-pointers/listing-15-23/output.txt index 3749c845c..0ffabf765 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-23/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-23/output.txt @@ -9,7 +9,7 @@ test tests::it_sends_an_over_75_percent_warning_message ... FAILED failures: ---- tests::it_sends_an_over_75_percent_warning_message stdout ---- -thread 'main' panicked at 'already borrowed: BorrowMutError', src/lib.rs:60:53 +thread 'tests::it_sends_an_over_75_percent_warning_message' panicked at 'already borrowed: BorrowMutError', src/lib.rs:60:53 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt index 0634b86e5..e8cf21a73 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt @@ -22,6 +22,9 @@ note: required because it's used within this closure 11 | let handle = thread::spawn(move || { | ^^^^^^^ note: required by a bound in `spawn` + --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/thread/mod.rs:704:8 + | + = note: required by this bound in `spawn` For more information about this error, try `rustc --explain E0277`. error: could not compile `shared-state` due to previous error diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/output.txt b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/output.txt index 0fd5373b8..52efabb5c 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/output.txt +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/output.txt @@ -9,11 +9,19 @@ error[E0005]: refutable pattern in local binding: `None` not covered = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `Option<i32>` defined here + --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/option.rs:518:1 + | + = note: +/rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/option.rs:522:5: not covered = note: the matched value is of type `Option<i32>` help: you might want to use `if let` to ignore the variant that isn't matched | 3 | let x = if let Some(x) = some_option_value { x } else { todo!() }; | ++++++++++ ++++++++++++++++++++++ +help: alternatively, you might want to use let else to handle the variant that isn't matched + | +3 | let Some(x) = some_option_value else { todo!() }; + | ++++++++++++++++ For more information about this error, try `rustc --explain E0005`. error: could not compile `patterns` due to previous error diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt index 702d10a23..6488fb29c 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt @@ -6,9 +6,9 @@ warning: irrefutable `if let` pattern 2 | if let x = 5 { | ^^^^^^^^^ | - = note: `#[warn(irrefutable_let_patterns)]` on by default = note: this pattern will always match, so the `if let` is useless = help: consider replacing the `if let` with a `let` + = note: `#[warn(irrefutable_let_patterns)]` on by default warning: `patterns` (bin "patterns") generated 1 warning Finished dev [unoptimized + debuginfo] target(s) in 0.39s diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-20/output.txt b/src/doc/book/listings/ch19-advanced-features/listing-19-20/output.txt index a3b281e3f..594287604 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-20/output.txt +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-20/output.txt @@ -11,8 +11,8 @@ error[E0790]: cannot call associated function on trait without specifying the co | help: use the fully-qualified path to the only available implementation | -20 | println!("A baby dog is called a {}", <::Dog as Animal>::baby_name()); - | +++++++++ + +20 | println!("A baby dog is called a {}", <Dog as Animal>::baby_name()); + | +++++++ + For more information about this error, try `rustc --explain E0790`. error: could not compile `traits-example` due to previous error diff --git a/src/doc/book/listings/ch20-web-server/listing-20-22/output.txt b/src/doc/book/listings/ch20-web-server/listing-20-22/output.txt index a6c9e8d3b..342bf9a16 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-22/output.txt +++ b/src/doc/book/listings/ch20-web-server/listing-20-22/output.txt @@ -9,6 +9,7 @@ error[E0507]: cannot move out of `worker.thread` which is behind a mutable refer | move occurs because `worker.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait | note: this function takes ownership of the receiver `self`, which moves `worker.thread` + --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/thread/mod.rs:1581:17 For more information about this error, try `rustc --explain E0507`. error: could not compile `hello` due to previous error diff --git a/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt b/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt index e4c0eeb2a..fec2377dc 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt +++ b/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/output.txt @@ -7,6 +7,7 @@ error[E0599]: no method named `join` found for enum `Option` in the current scop | ^^^^ method not found in `Option<JoinHandle<()>>` | note: the method `join` exists on the type `JoinHandle<()>` + --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/thread/mod.rs:1581:5 help: consider using `Option::expect` to unwrap the `JoinHandle<()>` value, panicking if the value is an `Option::None` | 52 | worker.thread.expect("REASON").join().unwrap(); diff --git a/src/doc/book/rust-toolchain b/src/doc/book/rust-toolchain index 5b6cd6b3c..9ebd7af32 100644 --- a/src/doc/book/rust-toolchain +++ b/src/doc/book/rust-toolchain @@ -1 +1 @@ -1.65 +1.67 diff --git a/src/doc/book/src/ch00-00-introduction.md b/src/doc/book/src/ch00-00-introduction.md index 9df8e6c88..536988cb1 100644 --- a/src/doc/book/src/ch00-00-introduction.md +++ b/src/doc/book/src/ch00-00-introduction.md @@ -4,7 +4,7 @@ > Language][nsprust] available in print and ebook format from [No Starch > Press][nsp]. -[nsprust]: https://nostarch.com/rust +[nsprust]: https://nostarch.com/rust-programming-language-2nd-edition [nsp]: https://nostarch.com/ Welcome to *The Rust Programming Language*, an introductory book about Rust. diff --git a/src/doc/book/src/ch03-01-variables-and-mutability.md b/src/doc/book/src/ch03-01-variables-and-mutability.md index 883a53050..058f7bb5c 100644 --- a/src/doc/book/src/ch03-01-variables-and-mutability.md +++ b/src/doc/book/src/ch03-01-variables-and-mutability.md @@ -82,7 +82,7 @@ First, you aren’t allowed to use `mut` with constants. Constants aren’t just immutable by default—they’re always immutable. You declare constants using the `const` keyword instead of the `let` keyword, and the type of the value *must* be annotated. We’ll cover types and type annotations in the next section, -[“Data Types,”][data-types]<!-- ignore -->, so don’t worry about the details +[“Data Types”][data-types]<!-- ignore -->, so don’t worry about the details right now. Just know that you must always annotate the type. Constants can be declared in any scope, including the global scope, which makes diff --git a/src/doc/book/src/ch10-01-syntax.md b/src/doc/book/src/ch10-01-syntax.md index c22aef7c3..431dba966 100644 --- a/src/doc/book/src/ch10-01-syntax.md +++ b/src/doc/book/src/ch10-01-syntax.md @@ -33,9 +33,9 @@ the duplication by introducing a generic type parameter in a single function. To parameterize the types in a new single function, we need to name the type parameter, just as we do for the value parameters to a function. You can use any identifier as a type parameter name. But we’ll use `T` because, by -convention, type parameter names in Rust are short, often just a letter, and Rust’s -type-naming convention is CamelCase. Short for “type,” `T` is the default -choice of most Rust programmers. +convention, type parameter names in Rust are short, often just a letter, and +Rust’s type-naming convention is UpperCamelCase. Short for “type,” `T` is the +default choice of most Rust programmers. When we use a parameter in the body of the function, we have to declare the parameter name in the signature so the compiler knows what that name means. @@ -274,7 +274,7 @@ method. ### Performance of Code Using Generics You might be wondering whether there is a runtime cost when using generic type -parameters. The good news is that using generic types won't make your program run +parameters. The good news is that using generic types won't make your program run any slower than it would with concrete types. Rust accomplishes this by performing monomorphization of the code using diff --git a/src/doc/book/src/title-page.md b/src/doc/book/src/title-page.md index 12d1a6598..5f7a7a680 100644 --- a/src/doc/book/src/title-page.md +++ b/src/doc/book/src/title-page.md @@ -2,7 +2,7 @@ *by Steve Klabnik and Carol Nichols, with contributions from the Rust Community* -This version of the text assumes you’re using Rust 1.65 (released 2022-11-03) +This version of the text assumes you’re using Rust 1.67.1 (released 2023-02-09) or later. See the [“Installation” section of Chapter 1][install]<!-- ignore --> to install or update Rust. @@ -18,7 +18,7 @@ Press][nsprust]. [install]: ch01-01-installation.html [editions]: appendix-05-editions.html -[nsprust]: https://nostarch.com/rust +[nsprust]: https://nostarch.com/rust-programming-language-2nd-edition [translations]: appendix-06-translation.html > **🚨 Want a more interactive learning experience? Try out a different version diff --git a/src/doc/embedded-book/src/assets/verify.jpeg b/src/doc/embedded-book/src/assets/verify.jpeg Binary files differindex a6e9376c5..ed4664578 100644 --- a/src/doc/embedded-book/src/assets/verify.jpeg +++ b/src/doc/embedded-book/src/assets/verify.jpeg diff --git a/src/doc/embedded-book/src/collections/index.md b/src/doc/embedded-book/src/collections/index.md index 7319a397a..aa03666ac 100644 --- a/src/doc/embedded-book/src/collections/index.md +++ b/src/doc/embedded-book/src/collections/index.md @@ -49,9 +49,8 @@ in your program instead of this allocator. ``` rust,ignore // Bump pointer allocator implementation -extern crate cortex_m; - -use core::alloc::GlobalAlloc; +use core::alloc::{GlobalAlloc, Layout}; +use core::cell::UnsafeCell; use core::ptr; use cortex_m::interrupt; @@ -144,8 +143,7 @@ as they are exact same implementation. allocator. Just `use` its collections and proceed to instantiate them: ```rust,ignore -extern crate heapless; // v0.4.x - +// heapless version: v0.4.x use heapless::Vec; use heapless::consts::*; @@ -155,6 +153,7 @@ fn main() -> ! { xs.push(42).unwrap(); assert_eq!(xs.pop(), Some(42)); + loop {} } ``` diff --git a/src/doc/embedded-book/src/interoperability/c-with-rust.md b/src/doc/embedded-book/src/interoperability/c-with-rust.md index d5d8db39b..6bec3bd87 100644 --- a/src/doc/embedded-book/src/interoperability/c-with-rust.md +++ b/src/doc/embedded-book/src/interoperability/c-with-rust.md @@ -125,8 +125,6 @@ For projects with limited dependencies or complexity, or for projects where it i In the simplest case of compiling a single C file as a dependency to a static library, an example `build.rs` script using the [`cc` crate] would look like this: ```rust,ignore -extern crate cc; - fn main() { cc::Build::new() .file("foo.c") diff --git a/src/doc/embedded-book/src/intro/install/macos.md b/src/doc/embedded-book/src/intro/install/macos.md index b3e51bcf1..9a797563a 100644 --- a/src/doc/embedded-book/src/intro/install/macos.md +++ b/src/doc/embedded-book/src/intro/install/macos.md @@ -1,8 +1,11 @@ # macOS -All the tools can be install using [Homebrew]: +All the tools can be installed using [Homebrew] or [MacPorts]: [Homebrew]: http://brew.sh/ +[MacPorts]: https://www.macports.org/ + +## Install tools with [Homebrew] ``` text $ # GDB @@ -20,6 +23,21 @@ $ brew install qemu $ brew install --HEAD openocd ``` +## Install tools with [MacPorts] + +``` text +$ # GDB +$ sudo port install arm-none-eabi-gcc + +$ # OpenOCD +$ sudo port install openocd + +$ # QEMU +$ sudo port install qemu +``` + + + That's all! Go to the [next section]. [next section]: verify.md diff --git a/src/doc/embedded-book/src/intro/install/verify.md b/src/doc/embedded-book/src/intro/install/verify.md index 921db8cc7..e60911dc3 100644 --- a/src/doc/embedded-book/src/intro/install/verify.md +++ b/src/doc/embedded-book/src/intro/install/verify.md @@ -8,7 +8,7 @@ discovery board has two USB connectors; use the one labeled "USB ST-LINK" that sits on the center of the edge of the board. Also check that the ST-LINK header is populated. See the picture below; the -ST-LINK header is circled in red. +ST-LINK header is highlighted. <p align="center"> <img title="Connected discovery board" src="../../assets/verify.jpeg"> diff --git a/src/doc/embedded-book/src/peripherals/singletons.md b/src/doc/embedded-book/src/peripherals/singletons.md index 3f04aa170..1f3a556e8 100644 --- a/src/doc/embedded-book/src/peripherals/singletons.md +++ b/src/doc/embedded-book/src/peripherals/singletons.md @@ -61,8 +61,7 @@ This has a small runtime overhead because we must wrap the `SerialPort` structur Although we created our own `Peripherals` structure above, it is not necessary to do this for your code. the `cortex_m` crate contains a macro called `singleton!()` that will perform this action for you. ```rust,ignore -#[macro_use(singleton)] -extern crate cortex_m; +use cortex_m::singleton; fn main() { // OK if `main` is executed only once diff --git a/src/doc/embedded-book/src/start/registers.md b/src/doc/embedded-book/src/start/registers.md index d5bb3e0cc..fe184792c 100644 --- a/src/doc/embedded-book/src/start/registers.md +++ b/src/doc/embedded-book/src/start/registers.md @@ -24,7 +24,7 @@ You may well find that the code you need to access the peripherals in your micro A board crate is the perfect starting point, if you're new to embedded Rust. They nicely abstract the HW details that might be overwhelming when starting studying this subject, and makes standard tasks easy, like turning a LED on or off. The functionality it exposes varies a lot between boards. Since this book aims at staying hardware agnostic, the board crates won't be covered by this book. -If you want to experiment with the STM32F3DISCOVERY board, it is highly recommmand to take a look at the [stm32f3-discovery] board crate, which provides functionality to blink the board LEDs, access its compass, bluetooth and more. The [Discovery] book offers a great introduction to the use of a board crate. +If you want to experiment with the STM32F3DISCOVERY board, it is highly recommended to take a look at the [stm32f3-discovery] board crate, which provides functionality to blink the board LEDs, access its compass, bluetooth and more. The [Discovery] book offers a great introduction to the use of a board crate. But if you're working on a system that doesn't yet have dedicated board crate, or you need functionality not provided by existing crates, read on as we start from the bottom, with the micro-architecture crates. diff --git a/src/doc/index.md b/src/doc/index.md index bf08960f3..7c97c16c2 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -4,6 +4,20 @@ nav { display: none; } +body { + font-family: serif; +} +h1, h2, h3, h4, h5, h6 { + font-family: sans-serif; +} +h3 { + font-size: 1.35rem; +} +h4 { + font-size: 1.1rem; +} + +/* Formatting for docs search bar */ #search-input { width: calc(100% - 58px); } @@ -21,53 +35,74 @@ nav { #search-but:hover, #search-input:focus { border-color: #55a9ff; } -h2 { - font-size: 18px; + +/* Formatting for external link icon */ +svg.external-link { + display: inline-block; + position: relative; + vertical-align: super; + width: 0.7rem; + height: 0.7rem; + padding-left: 2px; + top: 3px; } </style> -Welcome to an overview of the documentation provided by the [Rust project]. -All of these projects are managed by the Docs Team; there are other -unofficial documentation resources as well! +Welcome to an overview of the documentation provided by the [Rust +project]. This page contains links to various helpful references, +most of which are available offline (if opened with `rustup doc`). Many of these +resources take the form of "books"; we collectively call these "The Rust +Bookshelf." Some are large, some are small. -Many of these resources take the form of "books"; we collectively call these -"The Rust Bookshelf." Some are large, some are small. +All of these books are managed by the Rust Organization, but other unofficial +documentation resources are included here as well! -# Learn Rust +If you're just looking for the standard library reference, here it is: +[Rust API documentation](std/index.html) -If you'd like to learn Rust, this is the spot for you! All of these resources + +## Learning Rust + +If you'd like to learn Rust, this is the section for you! All of these resources assume that you have programmed before, but not in any specific language: -## The Rust Programming Language +### The Rust Programming Language -Affectionately nicknamed "the book," [The Rust Programming -Language](book/index.html) will give you an overview of the language from -first principles. You'll build a few projects along the way, and by the end, -you'll have a solid grasp of the language. +Affectionately nicknamed "the book," [The Rust Programming Language](book/index.html) +will give you an overview of the language from first principles. You'll build a +few projects along the way, and by the end, you'll have a solid grasp of how to +use the language. -## Rust By Example +### Rust By Example If reading multiple hundreds of pages about a language isn't your style, then -[Rust By Example](rust-by-example/index.html) has you covered. While the book talks about code with -a lot of words, RBE shows off a bunch of code, and keeps the talking to a -minimum. It also includes exercises! +[Rust By Example](rust-by-example/index.html) has you covered. RBE shows off a +bunch of code without using a lot of words. It also includes exercises! + +### Rustlings + +[Rustlings](https://github.com/rust-lang/rustlings) guides you +through downloading and setting up the Rust toolchain, then provides an +interactive tool that teaches you how to solve coding challenges in Rust. + +### Rust Playground -## Rustlings +The [Rust Playground](https://play.rust-lang.org) is a great place +to try out and share small bits of code, or experiment with some of the most +popular crates. -[Rustlings](https://github.com/rust-lang/rustlings) guides you through downloading and setting up the Rust toolchain, -and teaches you the basics of reading and writing Rust syntax. It's an -alternative to Rust by Example that works with your own environment. -# Use Rust +## Using Rust -Once you've gotten familiar with the language, these resources can help you -when you're actually using it day-to-day. +Once you've gotten familiar with the language, these resources can help you put +it to work. -## The Standard Library +### The Standard Library -Rust's standard library has [extensive API documentation](std/index.html), -with explanations of how to use various things, as well as example code for -accomplishing various tasks. +Rust's standard library has [extensive API documentation](std/index.html), with +explanations of how to use various things, as well as example code for +accomplishing various tasks. Code examples have a "Run" button on hover that +opens the sample in the playground. <div> <form action="std/index.html" method="get"> @@ -77,76 +112,143 @@ accomplishing various tasks. </form> </div> -## The Edition Guide +### Your Personal Documentation -[The Edition Guide](edition-guide/index.html) describes the Rust editions. +Whenever you are working in a crate, `cargo doc --open` will generate +documentation for your project _and_ all its dependencies in their correct +version, and open it in your browser. Add the flag `--document-private-items` to +also show items not marked `pub`. -## The Rustc Book +### The Edition Guide -[The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`. +[The Edition Guide](edition-guide/index.html) describes the Rust editions and +their differences. -## The Cargo Book +### The `rustc` Book -[The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and dependency manager. +[The `rustc` Book](rustc/index.html) describes the Rust compiler, `rustc`. -## The Rustdoc Book +### The Cargo Book + +[The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and +dependency manager. + +### The Rustdoc Book [The Rustdoc Book](rustdoc/index.html) describes our documentation tool, `rustdoc`. -## The Clippy Book +### The Clippy Book [The Clippy Book](clippy/index.html) describes our static analyzer, Clippy. -## Extended Error Listing +### Extended Error Listing 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_codes/index.html), if you prefer to read them that way. +diagnostics from the compiler on those errors (with `rustc --explain`). You can +also read them here if you prefer: [rustc error codes](error_codes/index.html) + -# Master Rust +## Mastering Rust Once you're quite familiar with the language, you may find these advanced resources useful. -## The Reference +### The Reference -[The Reference](reference/index.html) is not a formal spec, but is more detailed and -comprehensive than the book. +[The Reference](reference/index.html) is not a formal spec, but is more detailed +and comprehensive than the book. -## The Style Guide +### The Style Guide -[The Rust Style Guide](style-guide/index.html) describes the standard formatting of Rust -code. Most developers use rustfmt to format their code, and rustfmt's default -formatting matches this style guide. +[The Rust Style Guide](style-guide/index.html) describes the standard formatting +of Rust code. Most developers use `cargo fmt` to invoke `rustfmt` and format the +code automatically (the result matches this style guide). -## The Rustonomicon +### The Rustonomicon -[The Rustonomicon](nomicon/index.html) is your guidebook to the dark arts of unsafe -Rust. It's also sometimes called "the 'nomicon." +[The Rustonomicon](nomicon/index.html) is your guidebook to the dark arts of +unsafe Rust. It's also sometimes called "the 'nomicon." -## The Unstable Book +### The Unstable Book -[The Unstable Book](unstable-book/index.html) has documentation for unstable features. +[The Unstable Book](unstable-book/index.html) has documentation for unstable +features. -## The `rustc` Contribution Guide +### The `rustc` Contribution Guide -[The `rustc` Guide](https://rustc-dev-guide.rust-lang.org/) documents how -the compiler works and how to contribute to it. This is useful if you want to build -or modify the Rust compiler from source (e.g. to target something non-standard). +[The `rustc` Guide](https://rustc-dev-guide.rust-lang.org/) +documents how the compiler works and how to contribute to it. This is useful if +you want to build or modify the Rust compiler from source (e.g. to target +something non-standard). -# Specialize Rust -When using Rust in specific domain areas, consider using the following resources tailored to each domain. +## Specialized Rust -## Embedded Systems +When using Rust in specific domains, consider using the following resources +tailored to each area. -When developing for Bare Metal or Embedded Linux systems, you may find these resources maintained by the [Embedded Working Group] useful. +### Embedded Systems + +When developing for Bare Metal or Embedded Linux systems, you may find these +resources maintained by the [Embedded Working Group] useful. [Embedded Working Group]: https://github.com/rust-embedded -### The Embedded Rust Book +#### The Embedded Rust Book -[The Embedded Rust Book] is targeted at developers familiar with embedded development and familiar with Rust, but have not used Rust for embedded development. +[The Embedded Rust Book] is targeted at developers familiar with embedded +development and familiar with Rust, but have not used Rust for embedded +development. [The Embedded Rust Book]: embedded-book/index.html [Rust project]: https://www.rust-lang.org + +<script> +// check if a given link is external +function isExternalLink(url) { + const tmp = document.createElement('a'); + tmp.href = url; + return tmp.host !== window.location.host; +} + +// Add the `external` class to all <a> tags with external links and append the external link SVG +function updateExternalAnchors() { + /* + External link SVG from Font-Awesome + CC BY-SA 3.0 https://creativecommons.org/licenses/by-sa/3.0 + via Wikimedia Commons + */ + const svgText = `<svg + class='external-link' + xmlns='http://www.w3.org/2000/svg' + viewBox='0 -256 1850 1850' + width='100%' + height='100%'> + <g transform='matrix(1,0,0,-1,30,1427)'> + <path d='M 1408,608 V 288 Q 1408,169 1323.5,84.5 1239,0 1120, + 0 H 288 Q 169,0 84.5,84.5 0,169 0,288 v 832 Q 0,1239 84.5,1323.5 169, + 1408 288,1408 h 704 q 14,0 23,-9 9,-9 9,-23 v -64 q 0,-14 -9,-23 -9, + -9 -23,-9 H 288 q -66,0 -113,-47 -47,-47 -47,-113 V 288 q 0,-66 47, + -113 47,-47 113,-47 h 832 q 66,0 113,47 47,47 47,113 v 320 q 0,14 9, + 23 9,9 23,9 h 64 q 14,0 23,-9 9,-9 9,-23 z m 384,864 V 960 q 0, + -26 -19,-45 -19,-19 -45,-19 -26,0 -45,19 L 1507,1091 855,439 q -10, + -10 -23,-10 -13,0 -23,10 L 695,553 q -10,10 -10,23 0,13 10,23 l 652, + 652 -176,176 q -19,19 -19,45 0,26 19,45 19,19 45,19 h 512 q 26,0 45, + -19 19,-19 19,-45 z' style='fill:currentColor' /> + </g> + </svg>`; + let allAnchors = document.getElementsByTagName("a"); + + for (var i = 0; i < allAnchors.length; ++i) { + let anchor = allAnchors[i]; + if (isExternalLink(anchor.href)) { + anchor.classList.add("external"); + anchor.innerHTML += svgText; + } + } +} + +// on page load, update external anchors +document.addEventListener("DOMContentLoaded", updateExternalAnchors); + +</script> diff --git a/src/doc/nomicon/src/dropck.md b/src/doc/nomicon/src/dropck.md index 75940219c..4063d5619 100644 --- a/src/doc/nomicon/src/dropck.md +++ b/src/doc/nomicon/src/dropck.md @@ -250,7 +250,7 @@ fn main() { inspector: None, days: Box::new(1), }; - world.inspector = Some(Inspector(&world.days, "gatget")); + world.inspector = Some(Inspector(&world.days, "gadget")); } ``` diff --git a/src/doc/nomicon/src/ffi.md b/src/doc/nomicon/src/ffi.md index 8d1a882b3..684e7125b 100644 --- a/src/doc/nomicon/src/ffi.md +++ b/src/doc/nomicon/src/ffi.md @@ -721,17 +721,20 @@ No `transmute` required! ## FFI and unwinding -It’s important to be mindful of unwinding when working with FFI. Each -non-`Rust` ABI comes in two variants, one with `-unwind` suffix and one without. If -you expect Rust `panic`s or foreign (e.g. C++) exceptions to cross an FFI -boundary, that boundary must use the appropriate `-unwind` ABI string (note -that compiling with `panic=abort` will still cause `panic!` to immediately -abort the process, regardless of which ABI is specified by the function that -`panic`s). +It’s important to be mindful of unwinding when working with FFI. Most +ABI strings come in two variants, one with an `-unwind` suffix and one without. +The `Rust` ABI always permits unwinding, so there is no `Rust-unwind` ABI. +If you expect Rust `panic`s or foreign (e.g. C++) exceptions to cross an FFI +boundary, that boundary must use the appropriate `-unwind` ABI string. Conversely, if you do not expect unwinding to cross an ABI boundary, use one of -the non-`unwind` ABI strings (other than `Rust`, which always permits -unwinding). If an unwinding operation does encounter an ABI boundary that is +the non-`unwind` ABI strings. + +> Note: Compiling with `panic=abort` will still cause `panic!` to immediately +abort the process, regardless of which ABI is specified by the function that +`panic`s. + +If an unwinding operation does encounter an ABI boundary that is not permitted to unwind, the behavior depends on the source of the unwinding (Rust `panic` or a foreign exception): diff --git a/src/doc/nomicon/src/send-and-sync.md b/src/doc/nomicon/src/send-and-sync.md index 34539daa3..808a5c3ae 100644 --- a/src/doc/nomicon/src/send-and-sync.md +++ b/src/doc/nomicon/src/send-and-sync.md @@ -94,6 +94,7 @@ to the heap. use std::{ mem::{align_of, size_of}, ptr, + cmp::max, }; struct Carton<T>(ptr::NonNull<T>); @@ -105,8 +106,8 @@ impl<T> Carton<T> { let mut memptr: *mut T = ptr::null_mut(); unsafe { let ret = libc::posix_memalign( - (&mut memptr).cast(), - align_of::<T>(), + (&mut memptr as *mut *mut T).cast(), + max(align_of::<T>(), size_of::<usize>()), size_of::<T>() ); assert_eq!(ret, 0, "Failed to allocate or invalid alignment"); diff --git a/src/doc/nomicon/src/subtyping.md b/src/doc/nomicon/src/subtyping.md index 6f0c12db4..cc48a5970 100644 --- a/src/doc/nomicon/src/subtyping.md +++ b/src/doc/nomicon/src/subtyping.md @@ -339,7 +339,7 @@ lifetimes to be covariant: as soon as you try to stuff them in something like a mutable reference, they inherit invariance and you're prevented from doing anything bad. -However Box makes it easier to focus on by-value aspect of references that we +However, Box makes it easier to focus on the by-value aspect of references that we partially glossed over. Unlike a lot of languages which allow values to be freely aliased at all times, diff --git a/src/doc/reference/src/behavior-considered-undefined.md b/src/doc/reference/src/behavior-considered-undefined.md index f8bffd13e..31963d1e5 100644 --- a/src/doc/reference/src/behavior-considered-undefined.md +++ b/src/doc/reference/src/behavior-considered-undefined.md @@ -25,7 +25,7 @@ code. * Data races. * Evaluating a [dereference expression] (`*expr`) on a raw pointer that is [dangling] or unaligned, even in [place expression context] - (e.g. `addr_of!(&*expr)`). + (e.g. `addr_of!(*expr)`). * Breaking the [pointer aliasing rules]. `Box<T>`, `&mut T` and `&T` follow LLVM’s scoped [noalias] model, except if the `&T` contains an [`UnsafeCell<U>`]. References and boxes must not be [dangling] while they are diff --git a/src/doc/reference/src/destructors.md b/src/doc/reference/src/destructors.md index f89fde157..84aac89d3 100644 --- a/src/doc/reference/src/destructors.md +++ b/src/doc/reference/src/destructors.md @@ -162,7 +162,7 @@ smallest scope that contains the expression and is one of the following: * The `else` block of an `if` expression. * The condition expression of an `if` or `while` expression, or a `match` guard. -* The expression for a match arm. +* The body expression for a match arm. * The second operand of a [lazy boolean expression]. > **Notes**: diff --git a/src/doc/reference/src/expressions/if-expr.md b/src/doc/reference/src/expressions/if-expr.md index 591437fc9..fe387c828 100644 --- a/src/doc/reference/src/expressions/if-expr.md +++ b/src/doc/reference/src/expressions/if-expr.md @@ -129,7 +129,7 @@ The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperat Use of a lazy boolean operator is ambiguous with a planned feature change of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]). When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below: -<!-- ignore: psuedo code --> +<!-- ignore: pseudo code --> ```rust,ignore // Before... if let PAT = EXPR && EXPR { .. } diff --git a/src/doc/reference/src/expressions/operator-expr.md b/src/doc/reference/src/expressions/operator-expr.md index 9f7e8edac..691f801e8 100644 --- a/src/doc/reference/src/expressions/operator-expr.md +++ b/src/doc/reference/src/expressions/operator-expr.md @@ -600,7 +600,7 @@ It will then set the value of the assigned operand's place to the value of perfo > **Note**: This is different than other expressions in that the right operand is evaluated before the left one. -Otherwise, this expression is syntactic sugar for calling the function of the overloading compound assigment trait of the operator (see the table earlier in this chapter). +Otherwise, this expression is syntactic sugar for calling the function of the overloading compound assignment trait of the operator (see the table earlier in this chapter). A mutable borrow of the assigned operand is automatically taken. For example, the following expression statements in `example` are equivalent: diff --git a/src/doc/reference/src/items/external-blocks.md b/src/doc/reference/src/items/external-blocks.md index d89536968..ce2190829 100644 --- a/src/doc/reference/src/items/external-blocks.md +++ b/src/doc/reference/src/items/external-blocks.md @@ -90,6 +90,7 @@ There are also some platform-specific ABI strings: `__fastcall` and GCC and clang's `__attribute__((fastcall))` * `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's `__vectorcall` and clang's `__attribute__((vectorcall))` +* `extern "efiapi"` -- The ABI used for [UEFI] functions. ## Variadic functions @@ -288,6 +289,7 @@ Attributes on extern function parameters follow the same rules and restrictions as [regular function parameters]. [IDENTIFIER]: ../identifiers.md +[UEFI]: https://uefi.org/specifications [WebAssembly module]: https://webassembly.github.io/spec/core/syntax/modules.html [functions]: functions.md [statics]: static-items.md diff --git a/src/doc/reference/src/linkage.md b/src/doc/reference/src/linkage.md index b15200511..82864b004 100644 --- a/src/doc/reference/src/linkage.md +++ b/src/doc/reference/src/linkage.md @@ -73,7 +73,7 @@ be ignored in favor of only building the artifacts specified by command line. being built for a different target. Note that these outputs are stackable in the sense that if multiple are -specified, then the compiler will produce each form of output at once without +specified, then the compiler will produce each form of output without having to recompile. However, this only applies for outputs specified by the same method. If only `crate_type` attributes are specified, then they will all be built, but if one or more `--crate-type` command line flags are specified, diff --git a/src/doc/reference/src/patterns.md b/src/doc/reference/src/patterns.md index 14bbac155..370e1990c 100644 --- a/src/doc/reference/src/patterns.md +++ b/src/doc/reference/src/patterns.md @@ -380,16 +380,19 @@ match tuple { > **<sup>Syntax</sup>**\ > _RangePattern_ :\ -> _InclusiveRangePattern_\ -> | _HalfOpenRangePattern_\ +> _RangeInclusivePattern_\ +> | _RangeFromPattern_\ +> | _RangeToInclusivePattern_\ > | _ObsoleteRangePattern_ > -> _InclusiveRangePattern_ :\ +> _RangeInclusivePattern_ :\ > _RangePatternBound_ `..=` _RangePatternBound_ > -> _HalfOpenRangePattern_ :\ +> _RangeFromPattern_ :\ > _RangePatternBound_ `..` -> | `..=` _RangePatternBound_ +> +> _RangeToInclusivePattern_ :\ +> `..=` _RangePatternBound_ > > _ObsoleteRangePattern_ :\ > _RangePatternBound_ `...` _RangePatternBound_ @@ -402,16 +405,13 @@ match tuple { > | [_PathExpression_] *Range patterns* match scalar values within the range defined by their bounds. -A bound on the left of its sigils is a *lower bound*. +They comprise a *sigil* (one of `..`, `..=`, or `...`) and a bound on one or both sides. +A bound on the left of the sigil is a *lower bound*. A bound on the right is an *upper bound*. -A range pattern may be closed or half-open. - -A range pattern is *closed* if it has both a lower and an upper bound. -The only closed ranged pattern is the inclusive range pattern. -*Inclusive range patterns* match all the values between and including both of its bounds. -It is written as its lower bounds, followed by `..=`, followed by its upper bounds. -The type of it is the type unification of its upper and lower bounds. +A range pattern with both a lower and upper bound will match all values between and including both of its bounds. +It is written as its lower bound, followed by `..=`, followed by its upper bound. +The type of the range pattern is the type unification of its upper and lower bounds. For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`. @@ -419,19 +419,15 @@ The lower bound cannot be greater than the upper bound. That is, in `a..=b`, a ≤ b must be the case. For example, it is an error to have a range pattern `10..=0`. -Range patterns are *half-open* if they have only an upper or lower bound. -They have the same type as their upper or lower bound. - -A half open range with only a lower bound is written as its lower bound followed by `..`. -These range patterns will match on any value greater than or equal to the lower bound. +A range pattern with only a lower bound will match any value greater than or equal to the lower bound. +It is written as its lower bound followed by `..`, and has the same type as its lower bound. For example, `1..` will match 1, 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but not 0, and not negative numbers for signed integers. -The bounds can be literals or paths that point to constant values. -A half open range with only an upper bound is written as `..=` followed by its upper bound. -These range patterns will match on any value less than or equal to the upper bound. -For example, `..=10` will match 10, 1, 0, and for signed interger types, all negative values. +A range pattern with only an upper bound matches any value less than or equal to the upper bound. +It is written as `..=` followed by its upper bound, and has the same type as its upper bound. +For example, `..=10` will match 10, 1, 0, and for signed integer types, all negative values. -Half-open range patterns cannot be used as the top-level pattern for subpatterns in [slice patterns](#slice-patterns). +Range patterns with only one bound cannot be used as the top-level pattern for subpatterns in [slice patterns](#slice-patterns). The bounds is written as one of: @@ -529,7 +525,7 @@ The range of values for a `char` type are precisely those ranges containing all Floating point range patterns are deprecated and may be removed in a future Rust release. See [issue #41620](https://github.com/rust-lang/rust/issues/41620) for more information. -> **Edition Differences**: Before the 2021 edition, closed range patterns may also be written using `...` as an alternative to `..=`, with the same meaning. +> **Edition Differences**: Before the 2021 edition, range patterns with both a lower and upper bound may also be written using `...` in place of `..=`, with the same meaning. > **Note**: Although range patterns use the same syntax as [range expressions], there are no exclusive range patterns. > That is, neither `x .. y` nor `.. x` are valid range patterns. @@ -747,7 +743,8 @@ match v[..] { Slice patterns are irrefutable when matching an array as long as each element is irrefutable. When matching a slice, it is irrefutable only in the form with a single `..` [rest pattern](#rest-patterns) or [identifier pattern](#identifier-patterns) with the `..` rest pattern as a subpattern. -Within a slice, a half-open range pattern like `a..` must be enclosed in parentheses, as in `(a..)`, to clarify it is intended to match a single value. +Within a slice, a range pattern without both lower and upper bound must be enclosed in parentheses, as in `(a..)`, to clarify it is intended to match against a single slice element. +A range pattern with both lower and upper bound, like `a..=b`, is not required to be enclosed in parentheses. ## Path patterns diff --git a/src/doc/reference/src/trait-bounds.md b/src/doc/reference/src/trait-bounds.md index c8dab3f1c..0a6731288 100644 --- a/src/doc/reference/src/trait-bounds.md +++ b/src/doc/reference/src/trait-bounds.md @@ -27,7 +27,7 @@ provided on any type in a [where clause]. There are also shorter forms for certain common cases: * Bounds written after declaring a [generic parameter][generic]: - `fn f<A: Copy>() {}` is the same as `fn f<A> where A: Copy () {}`. + `fn f<A: Copy>() {}` is the same as `fn f<A>() where A: Copy {}`. * In trait declarations as [supertraits]: `trait Circle : Shape {}` is equivalent to `trait Circle where Self : Shape {}`. * In trait declarations as bounds on [associated types]: diff --git a/src/doc/rust-by-example/src/error/option_unwrap/and_then.md b/src/doc/rust-by-example/src/error/option_unwrap/and_then.md index c065f2043..42a1f3ec0 100644 --- a/src/doc/rust-by-example/src/error/option_unwrap/and_then.md +++ b/src/doc/rust-by-example/src/error/option_unwrap/and_then.md @@ -39,10 +39,7 @@ fn have_recipe(food: Food) -> Option<Food> { fn cookable_v1(food: Food) -> Option<Food> { match have_recipe(food) { None => None, - Some(food) => match have_ingredients(food) { - None => None, - Some(food) => Some(food), - }, + Some(food) => have_ingredients(food), } } diff --git a/src/doc/rust-by-example/src/error/result/result_map.md b/src/doc/rust-by-example/src/error/result/result_map.md index 24537c318..c453d9fa9 100644 --- a/src/doc/rust-by-example/src/error/result/result_map.md +++ b/src/doc/rust-by-example/src/error/result/result_map.md @@ -56,7 +56,7 @@ use std::num::ParseIntError; // As with `Option`, we can use combinators such as `map()`. // This function is otherwise identical to the one above and reads: -// Modify n if the value is valid, otherwise pass on the error. +// Multiply if both values can be parsed from str, otherwise pass on the error. fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { first_number_str.parse::<i32>().and_then(|first_number| { second_number_str.parse::<i32>().map(|second_number| first_number * second_number) diff --git a/src/doc/rust-by-example/src/generics/bounds.md b/src/doc/rust-by-example/src/generics/bounds.md index 5d7e849a8..86e54e670 100644 --- a/src/doc/rust-by-example/src/generics/bounds.md +++ b/src/doc/rust-by-example/src/generics/bounds.md @@ -58,10 +58,10 @@ fn main() { let _triangle = Triangle { length: 3.0, height: 4.0 }; print_debug(&rectangle); - println!("Area: {}", rectangle.area()); + println!("Area: {}", area(&rectangle)); //print_debug(&_triangle); - //println!("Area: {}", _triangle.area()); + //println!("Area: {}", area(&_triangle)); // ^ TODO: Try uncommenting these. // | Error: Does not implement either `Debug` or `HasArea`. } diff --git a/src/doc/rust-by-example/src/hello/comment.md b/src/doc/rust-by-example/src/hello/comment.md index 5027f0a22..4ea6dcd44 100644 --- a/src/doc/rust-by-example/src/hello/comment.md +++ b/src/doc/rust-by-example/src/hello/comment.md @@ -14,7 +14,7 @@ a few different varieties: fn main() { // This is an example of a line comment. // There are two slashes at the beginning of the line. - // And nothing written inside these will be read by the compiler. + // And nothing written after these will be read by the compiler. // println!("Hello, world!"); diff --git a/src/doc/rust-by-example/src/index.md b/src/doc/rust-by-example/src/index.md index fecc1906a..ecadff4cc 100644 --- a/src/doc/rust-by-example/src/index.md +++ b/src/doc/rust-by-example/src/index.md @@ -27,7 +27,7 @@ Now let's begin! - [Flow of Control](flow_control.md) - `if`/`else`, `for`, and others. -- [Functions](fn.md) - Learn about Methods, Closures and High Order Functions. +- [Functions](fn.md) - Learn about Methods, Closures and Higher Order Functions. - [Modules](mod.md) - Organize code using modules diff --git a/src/doc/rust-by-example/src/primitives/tuples.md b/src/doc/rust-by-example/src/primitives/tuples.md index e745d89be..75c265e75 100644 --- a/src/doc/rust-by-example/src/primitives/tuples.md +++ b/src/doc/rust-by-example/src/primitives/tuples.md @@ -43,7 +43,7 @@ fn main() { let pair = (1, true); println!("Pair is {:?}", pair); - println!("Uhe reversed pair is {:?}", reverse(pair)); + println!("The reversed pair is {:?}", reverse(pair)); // To create one element tuples, the comma is required to tell them apart // from a literal surrounded by parentheses. diff --git a/src/doc/rust-by-example/src/std_misc/file/create.md b/src/doc/rust-by-example/src/std_misc/file/create.md index 709213c9d..4f113df88 100644 --- a/src/doc/rust-by-example/src/std_misc/file/create.md +++ b/src/doc/rust-by-example/src/std_misc/file/create.md @@ -53,6 +53,6 @@ proident, sunt in culpa qui officia deserunt mollit anim id est laborum. (As in the previous example, you are encouraged to test this example under failure conditions.) -There is [`OpenOptions`] struct that can be used to configure how a file is opened. +The [`OpenOptions`] struct can be used to configure how a file is opened. [`OpenOptions`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml index a21e342cb..2346698d4 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml @@ -16,10 +16,11 @@ jobs: env: MDBOOK_VERSION: 0.4.21 MDBOOK_LINKCHECK_VERSION: 0.7.6 - MDBOOK_MERMAID_VERSION: 0.11.2 - MDBOOK_TOC_VERSION: 0.9.0 + MDBOOK_MERMAID_VERSION: 0.12.6 + MDBOOK_TOC_VERSION: 0.11.2 DEPLOY_DIR: book/html BASE_SHA: ${{ github.event.pull_request.base.sha }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v3 with: diff --git a/src/doc/rustc-dev-guide/CITATION.cff b/src/doc/rustc-dev-guide/CITATION.cff new file mode 100644 index 000000000..fee82ad8c --- /dev/null +++ b/src/doc/rustc-dev-guide/CITATION.cff @@ -0,0 +1,9 @@ +cff-version: 1.2.0 +message: If you use this guide, please cite it using these metadata. +title: Rust Compiler Development Guide (rustc-dev-guide) +abstract: A guide to developing the Rust compiler (rustc) +authors: + - name: "The Rust Project Developers" +date-released: "2018-01-16" +license: "MIT OR Apache-2.0" +repository-code: "https://github.com/rust-lang/rustc-dev-guide" diff --git a/src/doc/rustc-dev-guide/README.md b/src/doc/rustc-dev-guide/README.md index 006ea3231..e501c9161 100644 --- a/src/doc/rustc-dev-guide/README.md +++ b/src/doc/rustc-dev-guide/README.md @@ -43,7 +43,7 @@ rustdocs][rustdocs]. To build a local static HTML site, install [`mdbook`](https://github.com/rust-lang/mdBook) with: ``` -> cargo install mdbook mdbook-linkcheck mdbook-toc +> cargo install mdbook mdbook-linkcheck mdbook-toc mdbook-mermaid ``` and execute the following command in the root of the repository: diff --git a/src/doc/rustc-dev-guide/book.toml b/src/doc/rustc-dev-guide/book.toml index dc216760e..a5d794b50 100644 --- a/src/doc/rustc-dev-guide/book.toml +++ b/src/doc/rustc-dev-guide/book.toml @@ -1,7 +1,7 @@ [book] -title = "Guide to Rustc Development" -author = "Rustc developers" -description = "A guide to developing rustc" +title = "Rust Compiler Development Guide" +author = "The Rust Project Developers" +description = "A guide to developing the Rust compiler (rustc)" [build] create-missing = false @@ -18,6 +18,9 @@ git-repository-url = "https://github.com/rust-lang/rustc-dev-guide" edit-url-template = "https://github.com/rust-lang/rustc-dev-guide/edit/master/{path}" additional-js = ["mermaid.min.js", "mermaid-init.js"] +[output.html.search] +use-boolean-and = true + [output.html.fold] enable = true level = 0 @@ -40,6 +43,9 @@ exclude = [ cache-timeout = 86400 warning-policy = "error" +[output.linkcheck.http-headers] +'github\.com' = ["Authorization: Bearer $GITHUB_TOKEN"] + [output.html.redirect] "/compiletest.html" = "tests/compiletest.html" "/diagnostics/sessiondiagnostic.html" = "diagnostics/diagnostic-structs.html" 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 70fce8b1c..d9e8145a3 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 @@ -170,7 +170,7 @@ fn main() { for (path, dates) in dates_by_file { println!( - "- [ ] {}", + "- {}", path.strip_prefix(&root_dir_path).unwrap_or(&path).display(), ); for (line, date) in dates { diff --git a/src/doc/rustc-dev-guide/examples/README b/src/doc/rustc-dev-guide/examples/README new file mode 100644 index 000000000..ca49dd74d --- /dev/null +++ b/src/doc/rustc-dev-guide/examples/README @@ -0,0 +1,11 @@ +For each example to compile, you will need to first run the following: + + rustup component add rustc-dev llvm-tools + +To create an executable: + + rustc rustc-driver-example.rs + +To run an executable: + + rustup run nightly ./rustc-driver-example diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index 8d8b40cd7..9708ab01d 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -1,10 +1,6 @@ #![feature(rustc_private)] -// NOTE: For the example to compile, you will need to first run the following: -// rustup component add rustc-dev llvm-tools-preview - -// version: rustc 1.68.0-nightly (935dc0721 2022-12-19) - +extern crate rustc_driver; extern crate rustc_error_codes; extern crate rustc_errors; extern crate rustc_hash; @@ -46,10 +42,9 @@ fn main() { "# .into(), }, - input_path: None, // Option<PathBuf> - output_dir: None, // Option<PathBuf> - output_file: None, // Option<PathBuf> - file_loader: None, // Option<Box<dyn FileLoader + Send + Sync>> + output_dir: None, // Option<PathBuf> + output_file: None, // Option<PathBuf> + file_loader: None, // Option<Box<dyn FileLoader + Send + Sync>> lint_caps: FxHashMap::default(), // FxHashMap<lint::LintId, lint::Level> // This is a callback from the driver that is called when [`ParseSess`] is created. parse_sess_created: None, //Option<Box<dyn FnOnce(&mut ParseSess) + Send>> @@ -71,17 +66,17 @@ fn main() { rustc_interface::run_compiler(config, |compiler| { compiler.enter(|queries| { // Parse the program and print the syntax tree. - let parse = queries.parse().unwrap().take(); + let parse = queries.parse().unwrap().get_mut().clone(); println!("{parse:?}"); // Analyze the program and inspect the types of definitions. - queries.global_ctxt().unwrap().take().enter(|tcx| { + queries.global_ctxt().unwrap().enter(|tcx| { for id in tcx.hir().items() { let hir = tcx.hir(); let item = hir.item(id); match item.kind { rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => { let name = item.ident; - let ty = tcx.type_of(hir.local_def_id(item.hir_id())); + let ty = tcx.type_of(item.hir_id().owner.def_id); println!("{name:?}:\t{ty:?}") } _ => (), diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs index 49ee9ff44..5bc2312a2 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs @@ -1,10 +1,6 @@ #![feature(rustc_private)] -// NOTE: For the example to compile, you will need to first run the following: -// rustup component add rustc-dev llvm-tools-preview - -// version: rustc 1.68.0-nightly (935dc0721 2022-12-19) - +extern crate rustc_driver; extern crate rustc_error_codes; extern crate rustc_errors; extern crate rustc_hash; @@ -67,7 +63,6 @@ fn main() { }, crate_cfg: rustc_hash::FxHashSet::default(), crate_check_cfg: CheckCfg::default(), - input_path: None, output_dir: None, output_file: None, file_loader: None, @@ -80,7 +75,7 @@ fn main() { }; rustc_interface::run_compiler(config, |compiler| { compiler.enter(|queries| { - queries.global_ctxt().unwrap().take().enter(|tcx| { + queries.global_ctxt().unwrap().enter(|tcx| { // Run the analysis phase on the local crate to trigger the type error. let _ = tcx.analysis(()); }); diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index 07b09e9df..53f8df81a 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -1,11 +1,7 @@ #![feature(rustc_private)] -// NOTE: For the example to compile, you will need to first run the following: -// rustup component add rustc-dev llvm-tools-preview - -// version: rustc 1.68.0-nightly (935dc0721 2022-12-19) - extern crate rustc_ast_pretty; +extern crate rustc_driver; extern crate rustc_error_codes; extern crate rustc_errors; extern crate rustc_hash; @@ -45,7 +41,6 @@ fn main() { }, crate_cfg: rustc_hash::FxHashSet::default(), crate_check_cfg: CheckCfg::default(), - input_path: None, output_dir: None, output_file: None, file_loader: None, @@ -59,13 +54,12 @@ fn main() { rustc_interface::run_compiler(config, |compiler| { compiler.enter(|queries| { // TODO: add this to -Z unpretty - let ast_krate = queries.parse().unwrap().take(); + let ast_krate = queries.parse().unwrap().get_mut().clone(); for item in ast_krate.items { println!("{}", item_to_string(&item)); } - // Analyze the crate and inspect the types under the cursor. - queries.global_ctxt().unwrap().take().enter(|tcx| { + queries.global_ctxt().unwrap().enter(|tcx| { // Every compilation contains a single crate. let hir_krate = tcx.hir(); // Iterate over the top-level items in the crate, looking for the main function. @@ -78,7 +72,7 @@ fn main() { if let rustc_hir::StmtKind::Local(local) = block.stmts[0].kind { if let Some(expr) = local.init { let hir_id = expr.hir_id; // hir_id identifies the string "Hello, world!" - let def_id = tcx.hir().local_def_id(item.hir_id()); // def_id identifies the main function + let def_id = item.hir_id().owner.def_id; // def_id identifies the main function let ty = tcx.typeck(def_id).node_type(hir_id); println!("{expr:#?}: {ty:?}"); } diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 360265c0e..adc397fd8 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -8,7 +8,7 @@ # Building and debugging `rustc` -- [How to Build and Run the Compiler](./building/how-to-build-and-run.md) +- [How to build and run the compiler](./building/how-to-build-and-run.md) - [Prerequisites](./building/prerequisites.md) - [Suggested Workflows](./building/suggested.md) - [Distribution artifacts](./building/build-install-distribution-artifacts.md) @@ -25,7 +25,7 @@ - [Test headers](./tests/headers.md) - [Performance testing](./tests/perf.md) - [Crater](./tests/crater.md) -- [Debugging the Compiler](./compiler-debugging.md) +- [Debugging the compiler](./compiler-debugging.md) - [Using the tracing/logging instrumentation](./tracing.md) - [Profiling the compiler](./profiling.md) - [with the linux perf tool](./profiling/with_perf.md) @@ -57,7 +57,7 @@ # High-level Compiler Architecture - [Prologue](./part-2-intro.md) -- [Overview of the Compiler](./overview.md) +- [Overview of the compiler](./overview.md) - [The compiler source code](./compiler-src.md) - [Bootstrapping](./building/bootstrapping.md) - [Queries: demand-driven compilation](./query.md) @@ -75,7 +75,7 @@ - [Prologue](./part-3-intro.md) - [Command-line arguments](./cli.md) -- [The Rustc Driver and Interface](./rustc-driver.md) +- [rustc_driver and rustc_interface](./rustc-driver.md) - [Example: Type checking](./rustc-driver-interacting-with-the-ast.md) - [Example: Getting diagnostics](./rustc-driver-getting-diagnostics.md) - [Syntax and the AST](./syntax-intro.md) @@ -95,7 +95,7 @@ - [MIR construction](./mir/construction.md) - [MIR visitor and traversal](./mir/visitor.md) - [MIR passes: getting the MIR for a function](./mir/passes.md) -- [Identifiers in the Compiler](./identifiers.md) +- [Identifiers in the compiler](./identifiers.md) - [Closure expansion](./closure.md) - [Inline assembly](./asm.md) @@ -117,6 +117,10 @@ - [Lowering to logic](./traits/lowering-to-logic.md) - [Goals and clauses](./traits/goals-and-clauses.md) - [Canonical queries](./traits/canonical-queries.md) + - [Next-gen trait solving](./solve/trait-solving.md) + - [The solver](./solve/the-solver.md) + - [Canonicalization](./solve/canonicalization.md) + - [Coinduction](./solve/coinduction.md) - [Type checking](./type-checking.md) - [Method Lookup](./method-lookup.md) - [Variance](./variance.md) @@ -164,7 +168,7 @@ - [Profile-guided Optimization](./profile-guided-optimization.md) - [LLVM Source-Based Code Coverage](./llvm-coverage-instrumentation.md) - [Sanitizers Support](./sanitizers.md) -- [Debugging Support in the Rust Compiler](./debugging-support-in-rustc.md) +- [Debugging support in the Rust compiler](./debugging-support-in-rustc.md) --- diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index 42306dc1c..019d31138 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -23,7 +23,7 @@ Term | Meaning <span id="double-ptr">double pointer</span> | A pointer with additional metadata. See "fat pointer" for more. <span id="drop-glue">drop glue</span> | (internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types. <span id="dst">DST</span> | Short for Dynamically-Sized Type, this is a type for which the compiler cannot statically know the size in memory (e.g. `str` or `[u8]`). Such types don't implement `Sized` and cannot be allocated on the stack. They can only occur as the last field in a struct. They can only be used behind a pointer (e.g. `&str` or `&[u8]`). -<span id="ebl">early-bound lifetime</span> | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `Substs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions)) +<span id="ebl">early-bound lifetime</span> | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted using a `Substs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#bound-regions)) <span id="empty-type">empty type</span> | see "uninhabited type". <span id="fat-ptr">fat pointer</span> | A two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of "fat pointers": references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers". <span id="free-var">free variable</span> | A "free variable" is one that is not bound within an expression or term; see [the background chapter for more](./background.md#free-vs-bound) @@ -42,7 +42,7 @@ Term | Meaning <span id="irlo">IRLO</span> | `IRLO` or `irlo` is sometimes used as an abbreviation for [internals.rust-lang.org](https://internals.rust-lang.org). <span id="item">item</span> | A kind of "definition" in the language, such as a static, const, use statement, module, struct, etc. Concretely, this corresponds to the `Item` type. <span id="lang-item">lang item</span> | Items that represent concepts intrinsic to the language itself, such as special built-in traits like `Sync` and `Send`; or traits representing operations such as `Add`; or functions that are called by the compiler. ([see more](https://doc.rust-lang.org/1.9.0/book/lang-items.html)) -<span id="lbl">late-bound lifetime</span> | A lifetime region that is substituted at its call site. Bound in a HRTB and substituted by specific functions in the compiler, such as `liberate_late_bound_regions`. Contrast with **early-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#bound-regions)) +<span id="lbl">late-bound lifetime</span> | A lifetime region that is substituted at its call site. Bound in a HRTB and substituted by specific functions in the compiler, such as `liberate_late_bound_regions`. Contrast with **early-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#bound-regions)) <span id="local-crate">local crate</span> | The crate currently being compiled. This is in contrast to "upstream crates" which refer to dependencies of the local crate. <span id="lto">LTO</span> | Short for Link-Time Optimizations, this is a set of optimizations offered by LLVM that occur just before the final binary is linked. These include optimizations like removing functions that are never used in the final program, for example. _ThinLTO_ is a variant of LTO that aims to be a bit more scalable and efficient, but possibly sacrifices some optimizations. You may also read issues in the Rust repo about "FatLTO", which is the loving nickname given to non-Thin LTO. LLVM documentation: [here][lto] and [here][thinlto]. <span id="llvm">[LLVM]</span> | (actually not an acronym :P) an open-source compiler backend. It accepts LLVM IR and outputs native binaries. Various languages (e.g. Rust) can then implement a compiler front-end that outputs LLVM IR and use LLVM to compile to all the platforms LLVM supports. diff --git a/src/doc/rustc-dev-guide/src/asm.md b/src/doc/rustc-dev-guide/src/asm.md index 3b6b5e093..b19f2ad46 100644 --- a/src/doc/rustc-dev-guide/src/asm.md +++ b/src/doc/rustc-dev-guide/src/asm.md @@ -277,7 +277,7 @@ pub enum InlineAsmOperand<'tcx> { } ``` -As part of HAIR lowering, `InOut` and `SplitInOut` operands are lowered to a split form with a +As part of THIR lowering, `InOut` and `SplitInOut` operands are lowered to a split form with a separate `in_value` and `out_place`. Semantically, the `InlineAsm` terminator is similar to the `Call` terminator except that it has diff --git a/src/doc/rustc-dev-guide/src/ast-validation.md b/src/doc/rustc-dev-guide/src/ast-validation.md index ff549ca62..f3ac35e8a 100644 --- a/src/doc/rustc-dev-guide/src/ast-validation.md +++ b/src/doc/rustc-dev-guide/src/ast-validation.md @@ -1,6 +1,36 @@ # AST Validation -AST validation is the process of checking various correctness properties about -the AST after macro expansion. +<!-- toc --> -**TODO**: write this chapter. [#656](https://github.com/rust-lang/rustc-dev-guide/issues/656) +## About + +_AST validation_ is a separate AST pass that visits each +item in the tree and performs simple checks. This pass +doesn't perform any complex analysis, type checking or +name resolution. + +Before performing any validation, the compiler first expands +the macros. Then this pass performs validations to check +that each AST item is in the correct state. And when this pass +is done, the compiler runs the crate resolution pass. + +## Validations + +Validations are defined in `AstValidator` type, which +itself is located in `rustc_ast_passes` crate. This +type implements various simple checks which emit errors +when certain language rules are broken. + +In addition, `AstValidator` implements `Visitor` trait +that defines how to visit AST items (which can be functions, +traits, enums, etc). + +For each item, visitor performs specific checks. For +example, when visiting a function declaration, +`AstValidator` checks that the function has: + +* no more than `u16::MAX` parameters; +* c-variadic functions are declared with at least one named argument; +* c-variadic argument goes the last in the declaration; +* documentation comments aren't applied to function parameters; +* and other validations. 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 ea50cd754..c5eb57e64 100644 --- a/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md +++ b/src/doc/rustc-dev-guide/src/backend/backend-agnostic.md @@ -2,16 +2,21 @@ <!-- toc --> -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]). +[`rustc_codegen_ssa`] +provides an abstract interface for all backends to implement, +namely LLVM, [Cranelift], and [GCC]. -[Cranelift]: https://github.com/bytecodealliance/wasmtime/tree/HEAD/cranelift +[Cranelift]: https://github.com/bjorn3/rustc_codegen_cranelift +[GCC]: https://github.com/rust-lang/rustc_codegen_gcc +[`rustc_codegen_ssa`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html -# Refactoring of `rustc_codegen_llvm` +Below is some background information on the refactoring that created this +abstract interface. + +## Refactoring of `rustc_codegen_llvm` by Denis Merigoux, October 23rd 2018 -## State of the code before the refactoring +### State of the code before the refactoring All the code related to the compilation of MIR into LLVM IR was contained inside the `rustc_codegen_llvm` crate. Here is the breakdown of the most @@ -51,7 +56,7 @@ While the LLVM-specific code will be left in `rustc_codegen_llvm`, all the new traits and backend-agnostic code will be moved in `rustc_codegen_ssa` (name suggestion by @eddyb). -## Generic types and structures +### Generic types and structures @irinagpopa started to parametrize the types of `rustc_codegen_llvm` by a generic `Value` type, implemented in LLVM by a reference `&'ll Value`. This @@ -103,7 +108,7 @@ of the backend and it makes more sense to leave their definition to the backend implementor than to allow just a narrow spot via a generic field for the backend's context. -## Traits and interface +### Traits and interface Because they have to be defined by the backend, `CodegenCx` and `Builder` will be the structures implementing all the traits defining the backend's interface. @@ -170,7 +175,7 @@ called. However, when implementing a Rust backend for `rustc`, these methods will need information from `CodegenCx`, hence the additional parameter (unused in the LLVM implementation of the trait). -## State of the code after the refactoring +### State of the code after the refactoring The traits offer an API which is very similar to the API of LLVM. This is not the best solution since LLVM has a very special way of doing things: when diff --git a/src/doc/rustc-dev-guide/src/backend/monomorph.md b/src/doc/rustc-dev-guide/src/backend/monomorph.md index 4a0b55f62..cbc56acfc 100644 --- a/src/doc/rustc-dev-guide/src/backend/monomorph.md +++ b/src/doc/rustc-dev-guide/src/backend/monomorph.md @@ -133,7 +133,7 @@ the substitutions with the identity parameter before being added to the set of collected items - thereby reducing the copies from two (`[u16, u32]` and `[u64, u32]`) to one (`[A, u32]`). -`unused_generic_params` will also invoked during code generation when the +`unused_generic_params` will also be invoked during code generation when the symbol name for `foo` is being computed for use in the callsites of `foo` (which have the regular substitutions present, otherwise there would be a symbol mismatch between the caller and the function). 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 38fbb2e44..a02011149 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -2,7 +2,7 @@ <!-- toc --> -<!-- date-check: Aug 2022 --> +<!-- date-check: Feb 2023 --> There is no formal policy about when to update LLVM or what it can be updated to, but a few guidelines are applied: @@ -16,9 +16,9 @@ but a few guidelines are applied: There are two reasons we would want to update LLVM: -* A bug could have been fixed! Often we find bugs in the compiler and fix - them upstream in LLVM. We'll want to pull fixes back to the compiler itself as - they're merged upstream. +* A bug could have been fixed! + Note that if we are the ones who fixed such a bug, + we prefer to upstream it, then pull it back for use by rustc. * LLVM itself may have a new release. @@ -172,9 +172,11 @@ so let's go through each in detail. Ideally the above instructions are pretty smooth, but here's some caveats to keep in mind while going through them: -* LLVM bugs are hard to find, don't hesitate to ask for help! Bisection is - definitely your friend here (yes LLVM takes forever to build, yet bisection is - still your friend) +* LLVM bugs are hard to find, don't hesitate to ask for help! + Bisection is definitely your friend here + (yes LLVM takes forever to build, yet bisection is still your friend). + Note that you can make use of [Dev Desktops], + which is an initiative to provide the contributors with remote access to powerful hardware. * If you've got general questions, [wg-llvm] can help you out. * Creating branches is a privileged operation on GitHub, so you'll need someone with write access to create the branches for you most likely. @@ -184,3 +186,4 @@ keep in mind while going through them: [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 +[Dev Desktops]: https://forge.rust-lang.org/infra/docs/dev-desktop.html diff --git a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md index 2dbbc0c1e..bd8a07843 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md +++ b/src/doc/rustc-dev-guide/src/borrow_check/region_inference/lifetime_parameters.md @@ -43,8 +43,8 @@ only variant of [`ty::RegionKind`] that we use is the [`ReVar`] variant. These region variables are broken into two major categories, based on their index: -[`ty::RegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html -[`ReVar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.RegionKind.html#variant.ReVar +[`ty::RegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html +[`ReVar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.RegionKind.html#variant.ReVar - 0..N: universal regions -- the ones we are discussing here. In this case, the code must be correct with respect to any value of those diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping.md b/src/doc/rustc-dev-guide/src/building/bootstrapping.md index 543c68c2e..fe34cb500 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping.md @@ -1,8 +1,7 @@ -# Bootstrapping the Compiler +# Bootstrapping the compiler <!-- toc --> - [*Bootstrapping*][boot] is the process of using a compiler to compile itself. More accurately, it means using an older compiler to compile a newer version of the same compiler. @@ -16,6 +15,11 @@ version. This is exactly how `x.py` works: it downloads the current beta release of rustc, then uses it to compile the new compiler. +Note that this documentation mostly covers user-facing information. See +[bootstrap/README.md][bootstrap-internals] to read about bootstrap internals. + +[bootstrap-internals]: https://github.com/rust-lang/rust/blob/master/src/bootstrap/README.md + ## Stages of bootstrapping Compiling `rustc` is done in stages. Here's a diagram, adapted from Joshua Nelson's @@ -86,7 +90,7 @@ because one must first build the new compiler with an older compiler and then use that to build the new compiler with itself. For development, you usually only want the `stage1` compiler, which you can build with `./x.py build library`. -See [Building the Compiler](./how-to-build-and-run.html#building-the-compiler). +See [Building the compiler](./how-to-build-and-run.html#building-the-compiler). ### Stage 3 @@ -135,31 +139,6 @@ bootstrapping the compiler. [intrinsics]: ../appendix/glossary.md#intrinsic [ocaml-compiler]: https://github.com/rust-lang/rust/tree/ef75860a0a72f79f97216f8aaa5b388d98da6480/src/boot -## Contributing to bootstrap - -When you use the bootstrap system, you'll call it through `x.py`. -However, most of the code lives in `src/bootstrap`. -`bootstrap` has a difficult problem: it is written in Rust, but yet it is run -before the Rust compiler is built! To work around this, there are two -components of bootstrap: the main one written in rust, and `bootstrap.py`. -`bootstrap.py` is what gets run by `x.py`. It takes care of downloading the -`stage0` compiler, which will then build the bootstrap binary written in -Rust. - -Because there are two separate codebases behind `x.py`, they need to -be kept in sync. In particular, both `bootstrap.py` and the bootstrap binary -parse `config.toml` and read the same command line arguments. `bootstrap.py` -keeps these in sync by setting various environment variables, and the -programs sometimes have to add arguments that are explicitly ignored, to be -read by the other. - -### Adding a setting to config.toml - -This section is a work in progress. In the meantime, you can see an example -contribution [here][bootstrap-build]. - -[bootstrap-build]: https://github.com/rust-lang/rust/pull/71994 - ## Understanding stages of bootstrap ### Overview @@ -407,44 +386,51 @@ usually means something is quite wrong -- or you're trying to compile e.g. the unlikely case that you actually need to invoke rustc in such a situation, you can tell the bootstrap shim to print all env variables by adding `-vvv` to your `x.py` command. -### Directories and artifacts generated by `bootstrap` - -This is an incomplete reference for the outputs generated by bootstrap: - -| Stage 0 Action | Output | -|-----------------------------------------------------------|----------------------------------------------| -| `beta` extracted | `build/HOST/stage0` | -| `stage0` builds `bootstrap` | `build/bootstrap` | -| `stage0` builds `test`/`std` | `build/HOST/stage0-std/TARGET` | -| copy `stage0-std` (HOST only) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | -| `stage0` builds `rustc` with `stage0-sysroot` | `build/HOST/stage0-rustc/HOST` | -| copy `stage0-rustc` (except executable) | `build/HOST/stage0-sysroot/lib/rustlib/HOST` | -| build `llvm` | `build/HOST/llvm` | -| `stage0` builds `codegen` with `stage0-sysroot` | `build/HOST/stage0-codegen/HOST` | -| `stage0` builds `rustdoc`, `clippy`, `miri`, with `stage0-sysroot` | `build/HOST/stage0-tools/HOST` | - -`--stage=0` stops here. - -| Stage 1 Action | Output | -|-----------------------------------------------------|---------------------------------------| -| copy (uplift) `stage0-rustc` executable to `stage1` | `build/HOST/stage1/bin` | -| copy (uplift) `stage0-codegen` to `stage1` | `build/HOST/stage1/lib` | -| copy (uplift) `stage0-sysroot` to `stage1` | `build/HOST/stage1/lib` | -| `stage1` builds `test`/`std` | `build/HOST/stage1-std/TARGET` | -| copy `stage1-std` (HOST only) | `build/HOST/stage1/lib/rustlib/HOST` | -| `stage1` builds `rustc` | `build/HOST/stage1-rustc/HOST` | -| copy `stage1-rustc` (except executable) | `build/HOST/stage1/lib/rustlib/HOST` | -| `stage1` builds `codegen` | `build/HOST/stage1-codegen/HOST` | - -`--stage=1` stops here. - -| Stage 2 Action | Output | -|--------------------------------------------------------|-----------------------------------------------------------------| -| copy (uplift) `stage1-rustc` executable | `build/HOST/stage2/bin` | -| copy (uplift) `stage1-sysroot` | `build/HOST/stage2/lib and build/HOST/stage2/lib/rustlib/HOST` | -| `stage2` builds `test`/`std` (not HOST targets) | `build/HOST/stage2-std/TARGET` | -| copy `stage2-std` (not HOST targets) | `build/HOST/stage2/lib/rustlib/TARGET` | -| `stage2` builds `rustdoc`, `clippy`, `miri` | `build/HOST/stage2-tools/HOST` | -| copy `rustdoc` | `build/HOST/stage2/bin` | - -`--stage=2` stops here. +Finally, bootstrap makes use of the [cc-rs crate] which has [its own +method][env-vars] of configuring C compilers and C flags via environment +variables. + +[cc-rs crate]: https://github.com/rust-lang/cc-rs +[env-vars]: https://github.com/rust-lang/cc-rs#external-configuration-via-environment-variables + +## Clarification of build command's stdout + +In this part, we will investigate the build command's stdout in an action +(similar, but more detailed and complete documentation compare to topic above). +When you execute `x.py build --dry-run` command, the build output will be something +like the following: + +```text +Building stage0 library artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) +Copying stage0 library from stage0 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu) +Building stage0 compiler artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) +Copying stage0 rustc from stage0 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu) +Assembling stage1 compiler (x86_64-unknown-linux-gnu) +Building stage1 library artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) +Copying stage1 library from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu) +Building stage1 tool rust-analyzer-proc-macro-srv (x86_64-unknown-linux-gnu) +Building rustdoc for stage1 (x86_64-unknown-linux-gnu) +``` + +### Building stage0 {std,compiler} artifacts + +These steps use the provided (downloaded, usually) compiler to compile the +local Rust source into libraries we can use. + +### Copying stage0 {std,rustc} + +This copies the library and compiler artifacts from Cargo into +`stage0-sysroot/lib/rustlib/{target-triple}/lib` + +### Assembling stage1 compiler + +This copies the libraries we built in "building stage0 ... artifacts" into +the stage1 compiler's lib directory. These are the host libraries that the +compiler itself uses to run. These aren't actually used by artifacts the new +compiler generates. This step also copies the rustc and rustdoc binaries we +generated into `build/$HOST/stage/bin`. + +The stage1/bin/rustc is a fully functional compiler, but it doesn't yet have +any libraries to link built binaries or libraries to. The next 3 steps will +provide those libraries for it; they are mostly equivalent to constructing +the stage1/bin compiler so we don't go through them individually. diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 24786c0c0..6651b3691 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -1,4 +1,4 @@ -# How to Build and Run the Compiler +# How to build and run the compiler The compiler is built using a tool called `x.py`. You will need to have Python installed to run it. @@ -52,7 +52,7 @@ If you have already built `rustc` and you change settings related to LLVM, then execute `rm -rf build` for subsequent configuration changes to take effect. Note that `./x.py clean` will not cause a rebuild of LLVM. -## Building the Compiler +## Building the compiler Note that building will require a relatively large amount of storage space. You may want to have upwards of 10 or 15 gigabytes available to build the compiler. @@ -122,16 +122,11 @@ you will likely need to build at some point; for example, if you want to run the entire test suite). ```bash -rustup toolchain link stage1 build/<host-triple>/stage1 -rustup toolchain link stage2 build/<host-triple>/stage2 +rustup toolchain link stage0 build/host/stage0-sysroot # beta compiler + stage0 std +rustup toolchain link stage1 build/host/stage1 +rustup toolchain link stage2 build/host/stage2 ``` -The `<host-triple>` would typically be one of the following: - -- Linux: `x86_64-unknown-linux-gnu` -- Mac: `x86_64-apple-darwin` or `aarch64-apple-darwin` -- Windows: `x86_64-pc-windows-msvc` - Now you can run the `rustc` you built with. If you run with `-vV`, you should see a version number ending in `-dev`, indicating a build from your local environment: diff --git a/src/doc/rustc-dev-guide/src/building/prerequisites.md b/src/doc/rustc-dev-guide/src/building/prerequisites.md index 8fee0a4b5..3dc2ea934 100644 --- a/src/doc/rustc-dev-guide/src/building/prerequisites.md +++ b/src/doc/rustc-dev-guide/src/building/prerequisites.md @@ -29,7 +29,7 @@ laptop. We suggest downloading LLVM from CI so you don't have to build it from s Like `cargo`, the build system will use as many cores as possible. Sometimes this can cause you to run low on memory. You can use `-j` to adjust the number -concurrent jobs. If a full build takes more than ~45 minutes to an hour, you +of concurrent jobs. If a full build takes more than ~45 minutes to an hour, you are probably spending most of the time swapping memory in and out; try using `-j1`. diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index f81daa5bc..2e2592094 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -19,51 +19,25 @@ You can also install the hook as a step of running `./x.py setup`! ## Configuring `rust-analyzer` for `rustc` +### Visual Studio Code + `rust-analyzer` can help you check and format your code whenever you save 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-check: nov 2022 --><!-- the date comment is for the edition below --> - -```JSON -{ - "rust-analyzer.checkOnSave.overrideCommand": [ - "python3", - "x.py", - "check", - "--json-output" - ], - "rust-analyzer.rustfmt.overrideCommand": [ - "./build/host/stage0/bin/rustfmt", - "--edition=2021" - ], - "rust-analyzer.procMacro.server": "./build/host/stage0/libexec/rust-analyzer-proc-macro-srv", - "rust-analyzer.procMacro.enable": true, - "rust-analyzer.cargo.buildScripts.enable": true, - "rust-analyzer.cargo.buildScripts.invocationLocation": "root", - "rust-analyzer.cargo.buildScripts.invocationStrategy": "once", - "rust-analyzer.cargo.buildScripts.overrideCommand": [ - "python3", - "x.py", - "check", - "--json-output" - ], - "rust-analyzer.cargo.sysroot": "./build/host/stage0-sysroot", - "rust-analyzer.rustc.source": "./Cargo.toml", -} -``` - -in your `.vscode/settings.json` file. This will ask `rust-analyzer` to use -`./x.py check` to check the sources, and the stage 0 rustfmt to format them. +of these tools when hacking on `rustc`. For example, `x.py setup` will prompt +you to create a `.vscode/settings.json` file which will configure Visual Studio code. +This will ask `rust-analyzer` to use `./x.py check` to check the sources, and the +stage 0 rustfmt to format them. +The recommended `rust-analyzer` settings live at [`src/etc/vscode_settings.json`]. If you have enough free disk space and you would like to be able to run `x.py` commands while rust-analyzer runs in the background, you can also add `--build-dir build-rust-analyzer` to the `overrideCommand` to avoid x.py locking. If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a -`.vim/coc-settings.json` and enter the same settings as above, but replacing -`editor.formatOnSave: true,` with -`"coc.preferences.formatOnSaveFiletypes": ["rust"],`. +`.vim/coc-settings.json` and copy the settings from [`src/etc/vscode_settings.json`]. + +[`src/etc/vscode_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/vscode_settings.json If running `./x.py check` on save is inconvenient, in VS Code you can use a [Build Task] instead: @@ -87,6 +61,35 @@ Task] instead: [Build Task]: https://code.visualstudio.com/docs/editor/tasks + +### Neovim + +For Neovim users there are several options for configuring for rustc. The easiest way is by using +[neoconf.nvim](https://github.com/folke/neoconf.nvim/), which allows for project-local +configuration files with the native LSP. The steps for how to use it are below. Note that requires +Rust-Analyzer to already be configured with Neovim. Steps for this can be +[found here](https://rust-analyzer.github.io/manual.html#nvim-lsp). + +1. First install the plugin. This can be done by following the steps in the README. +2. Run `x.py setup`, which will have a prompt for it to create a `.vscode/settings.json` file. +`neoconf` is able to read and update Rust-Analyzer settings automatically when the project is +opened when this file is detected. + +If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a +`.vim/coc-settings.json` and copy the settings from +[this file](https://github.com/rust-lang/rust/blob/master/src/etc/vscode_settings.json). + +Another way is without a plugin, and creating your own logic in your configuration. To do this you +must translate the JSON to Lua yourself. The translation is 1:1 and fairly straight-forward. It +must be put in the `["rust-analyzer"]` key of the setup table, which is +[shown here](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#rust_analyzer) + +If you would like to use the build task that is described above, you may either make your own +command in your config, or you can install a plugin such as +[overseer.nvim](https://github.com/stevearc/overseer.nvim) that can [read VSCode's `task.json` +files](https://github.com/stevearc/overseer.nvim/blob/master/doc/guides.md#vs-code-tasks), and +follow the same instructions as above. + ## Check, check, and check again When doing simple refactorings, it can be useful to run `./x.py check` @@ -175,6 +178,27 @@ You can also use `--keep-stage 1` when running tests. Something like this: - Initial test run: `./x.py test tests/ui` - Subsequent test run: `./x.py test tests/ui --keep-stage 1` +## Using incremental compilation + +You can further enable the `--incremental` flag to save additional +time in subsequent rebuilds: + +```bash +./x.py test tests/ui --incremental --test-args issue-1234 +``` + +If you don't want to include the flag with every command, you can +enable it in the `config.toml`: + +```toml +[rust] +incremental = true +``` + +Note that incremental compilation will use more disk space than usual. +If disk space is a concern for you, you might want to check the size +of the `build` directory from time to time. + ## Fine-tuning optimizations Setting `optimize = false` makes the compiler too slow for tests. However, to diff --git a/src/doc/rustc-dev-guide/src/closure.md b/src/doc/rustc-dev-guide/src/closure.md index 5746fd4de..e356f415d 100644 --- a/src/doc/rustc-dev-guide/src/closure.md +++ b/src/doc/rustc-dev-guide/src/closure.md @@ -155,7 +155,7 @@ This uses the stage1 compiler and enables `debug!` logging for the The other option is to step through the code using lldb or gdb. -1. `rust-lldb build/x86_64-apple-darwin/stage1/bin/rustc test.rs` +1. `rust-lldb build/host/stage1/bin/rustc test.rs` 2. In lldb: 1. `b upvar.rs:134` // Setting the breakpoint on a certain line in the upvar.rs file` 2. `r` // Run the program until it hits the breakpoint diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index eac9aeb6d..6052ea58a 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -1,5 +1,4 @@ # Debugging the compiler -[debugging]: #debugging <!-- toc --> @@ -185,7 +184,7 @@ stack backtrace: Cool, now I have a backtrace for the error! -## Getting the the error creation location +## Getting the error creation location `-Z track-diagnostics` can help figure out where errors are emitted. It uses `#[track_caller]` for this and prints its location alongside the error: @@ -341,3 +340,37 @@ error: aborting due to previous error ``` [`Layout`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/abi/struct.Layout.html + + +## Configuring CodeLLDB for debugging `rustc` + +If you are using VSCode, and have edited your `config.toml` to request debugging +level 1 or 2 for the parts of the code you're interested in, then you should be +able to use the [CodeLLDB] extension in VSCode to debug it. + +Here is a sample `launch.json` file, being used to run a stage 1 compiler direct +from the directory where it is built (does not have to be "installed"): + +```javascript +// .vscode/launch.json +{ + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Launch", + "args": [], // array of string command-line arguments to pass to compiler + "program": "${workspaceFolder}/build/host/stage1/bin/rustc", + "windows": { // applicable if using windows + "program": "${workspaceFolder}/build/host/stage1/bin/rustc.exe" + }, + "cwd": "${workspaceFolder}", // current working directory at program start + "stopOnEntry": false, + "sourceLanguages": ["rust"] + } + ] + } +``` + +[CodeLLDB]: https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb diff --git a/src/doc/rustc-dev-guide/src/compiler-src.md b/src/doc/rustc-dev-guide/src/compiler-src.md index 1f55a9d09..9c7d0bb2e 100644 --- a/src/doc/rustc-dev-guide/src/compiler-src.md +++ b/src/doc/rustc-dev-guide/src/compiler-src.md @@ -27,8 +27,10 @@ The repository consists of three main directories: `proc_macro`, `test`), as well as the Rust runtime (`backtrace`, `rtstartup`, `lang_start`). +- `tests/` contains the compiler tests. + - `src/` contains the source code for rustdoc, clippy, cargo, the build system, - compiler tests, language docs, etc. + language docs, etc. ## Compiler diff --git a/src/doc/rustc-dev-guide/src/constants.md b/src/doc/rustc-dev-guide/src/constants.md index a33a283f3..91d21bd32 100644 --- a/src/doc/rustc-dev-guide/src/constants.md +++ b/src/doc/rustc-dev-guide/src/constants.md @@ -78,5 +78,5 @@ the constant doesn't use them in any way. This can cause [`ty::Const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Const.html [`ty::ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.ConstKind.html -[`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html +[`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html [pcg-unused-substs]: https://github.com/rust-lang/project-const-generics/issues/33 diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index bc39508a4..383660fc1 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -202,7 +202,7 @@ Periodically the changes made to subtree based dependencies need to be synchroni repository and the upstream tool repositories. Subtree synchronizations are typically handled by the respective tool maintainers. Other users -are welcome to submit synchronization PRs, however, in order to do so you you will need to modify +are welcome to submit synchronization PRs, however, in order to do so you will need to modify your local git installation and follow a very precise set of instructions. These instructions are documented, along with several useful tips and tricks, in the [syncing subtree changes][clippy-sync-docs] section in Clippy's Contributing guide. @@ -320,7 +320,7 @@ Here are those same steps in detail: merged because CI will be broken. You'll want to write a message on the PR referencing your change, and how the PR should be merged once your change makes it into a nightly. 5. Wait for your PR to merge. -6. Wait for a nightly +6. Wait for a nightly. 7. (optional) Help land your PR on the upstream repository now that your changes are in nightly. 8. (optional) Send a PR to rust-lang/rust updating the submodule. @@ -390,20 +390,20 @@ Just a few things to keep in mind: add a special annotation before specifying the date: ```md - <!-- date-check --> Jul 2022 + <!-- date-check --> Jan 2023 ``` Example: ```md - As of <!-- date-check --> Jul 2022, the foo did the bar. + As of <!-- date-check --> Jan 2023, 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 --> + <!-- date-check: Jan 2023 --> ``` - A link to a relevant WG, tracking issue, `rustc` rustdoc page, or similar, that may provide diff --git a/src/doc/rustc-dev-guide/src/crates-io.md b/src/doc/rustc-dev-guide/src/crates-io.md index f012c5bb5..403d61a81 100644 --- a/src/doc/rustc-dev-guide/src/crates-io.md +++ b/src/doc/rustc-dev-guide/src/crates-io.md @@ -11,10 +11,9 @@ you should avoid adding dependencies to the compiler for several reasons: - The dependency may have transitive dependencies that have one of the above problems. -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. +<!-- date-check: Feb 2023 --> +Note that 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.md b/src/doc/rustc-dev-guide/src/diagnostics.md index b50b7bd18..d32de068e 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -112,10 +112,11 @@ Here are a few examples: - Dead code: this is a lint. While the user probably doesn't want dead code in their crate, making this a hard error would make refactoring and development very painful. -- [safe_packed_borrows future compatibility warning][safe_packed_borrows]: - this is a silencable lint related to safety. It was judged that the making - this a hard (fixed) error would cause too much breakage, so instead a - warning is emitted that eventually will be turned into a hard error. +- [future-incompatible lints]: + these are silencable lints. + It was decided that making them fixed errors would cause too much breakage, + so warnings are instead emitted, + and will eventually be turned into fixed (hard) errors. Hard-coded warnings (those using the `span_warn` methods) should be avoided for normal code, preferring to use lints instead. Some cases, such as warnings @@ -124,7 +125,7 @@ with CLI flags, will require the use of hard-coded warnings. See the `deny` [lint level](#diagnostic-levels) below for guidelines when to use an error-level lint instead of a fixed error. -[safe_packed_borrows]: https://github.com/rust-lang/rust/issues/46043 +[future-incompatible lints]: #future-incompatible-lints ## Diagnostic output style guide @@ -637,12 +638,12 @@ broader meaning than what rustc exposes to users of the compiler. Inside rustc, future-incompatible lints are for signalling to the user that code they have written may not compile in the future. In general, future-incompatible code exists for two reasons: -* the user has written unsound code that the compiler mistakenly accepted. While +* The user has written unsound code that the compiler mistakenly accepted. While it is within Rust's backwards compatibility guarantees to fix the soundness hole (breaking the user's code), the lint is there to warn the user that this will happen in some upcoming version of rustc *regardless of which edition the code uses*. This is the meaning that rustc exclusively exposes to users as "future incompatible". -* the user has written code that will either no longer compiler *or* will change +* The user has written code that will either no longer compiler *or* will change meaning in an upcoming *edition*. These are often called "edition lints" and can be typically seen in the various "edition compatibility" lint groups (e.g., `rust_2021_compatibility`) that are used to lint against code that will break if the user updates the crate's edition. @@ -665,7 +666,7 @@ declare_lint! { Notice the `reason` field which describes why the future incompatible change is happening. This will change the diagnostic message the user receives as well as determine which lint groups the lint is added to. In the example above, the lint is an "edition lint" -(since it's "reason" is `EditionError`) signifying to the user that the use of anonymous +(since its "reason" is `EditionError`), signifying to the user that the use of anonymous parameters will no longer compile in Rust 2018 and beyond. Inside [LintStore::register_lints][fi-lint-groupings], lints with `future_incompatible` 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 dcaba533e..78fdd032d 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-items.md @@ -48,7 +48,7 @@ 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. <!-- date-check: Aug 2022 --> +2. <!-- date-check: Feb 2023 --> Diagnostic items in code are accessed via symbols in [`rustc_span::symbol::sym`]. To add your newly-created diagnostic item, 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 e26ba5f34..790d74dcf 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -23,7 +23,7 @@ pub struct FieldAlreadyDeclared { #[primary_span] #[label] pub span: Span, - #[label(hir_analysis_previous_decl_label)] + #[label(previous_decl_label)] pub prev_span: Span, } ``` @@ -82,7 +82,7 @@ these attributes can also take a value that is the attribute name to look for Other types have special behavior when used in a `Diagnostic` derive: -- Any attribute applied to an `Option<T>` and will only emit a +- Any attribute applied to an `Option<T>` will only emit a subdiagnostic if the option is `Some(..)`. - Any attribute applied to a `Vec<T>` will be repeated for each element of the vector. diff --git a/src/doc/rustc-dev-guide/src/diagnostics/translation.md b/src/doc/rustc-dev-guide/src/diagnostics/translation.md index e36333039..e3ccec7d7 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/translation.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/translation.md @@ -222,7 +222,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-check --> June 2022, there are no locale bundles +As of <!-- date-check --> Jan 2023, 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/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index 4e1f520ff..bc294d1b3 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -81,7 +81,7 @@ normally used for: building, testing, creating releases, formatting, etc. [bootstrapping]: ./building/bootstrapping.md -### Configuring the Compiler +### Configuring the compiler In the top level of the repo: @@ -114,6 +114,10 @@ serious development work. In particular, `./x.py build` and `./x.py test` provide many ways to compile or test a subset of the code, which can save a lot of time. +Also, note that `x.py` supports all kinds of path suffixes for `compiler`, `library`, +and `src/tools` directories. So, you can simply run `x.py test tidy` instead of +`x.py test src/tools/tidy`. Or, `x.py build std` instead of `x.py build library/std`. + [rust-analyzer]: ./building/suggested.html#configuring-rust-analyzer-for-rustc See the chapters on [building](./building/how-to-build-and-run.md), diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index cac3d6534..a426157a2 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -238,18 +238,22 @@ Changes not staged for commit: 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, -as of <!-- date-check --> Aug 2022, +These changes are not changes to files: they are changes to submodules (more on this +[later](#git-submodules)). To get rid of those, run `./x.py --help`, which will automatically update +the submodules. + +Some submodules are not actually needed; for example, `src/llvm-project` doesn't need to be checked +out if you're using `download-ci-llvm`. To avoid having to keep fetching its history, you can use +`git submodule deinit -f src/llvm-project`, which will also avoid it showing as modified again. + +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` +error: failed to read `/home/jyn/rustc-worktree/src/tools/cargo/Cargo.toml` Caused by: No such file or directory (os error 2) @@ -260,8 +264,6 @@ 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 -(Note that as of Sept 2022 `miri` is a subtree and not a submodule.) - ## Rebasing and Conflicts When you edit your code locally, you are making changes to the version of diff --git a/src/doc/rustc-dev-guide/src/hir.md b/src/doc/rustc-dev-guide/src/hir.md index 8316f7ce3..160b47645 100644 --- a/src/doc/rustc-dev-guide/src/hir.md +++ b/src/doc/rustc-dev-guide/src/hir.md @@ -117,9 +117,9 @@ that `n` must be some HIR expression, you can do [Expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Expr.html Finally, you can use the HIR map to find the parents of nodes, via -calls like [`tcx.hir().get_parent_node(n)`][get_parent_node]. +calls like [`tcx.hir().get_parent(n)`][get_parent]. -[get_parent_node]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.get_parent_node +[get_parent]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.get_parent ## HIR Bodies diff --git a/src/doc/rustc-dev-guide/src/identifiers.md b/src/doc/rustc-dev-guide/src/identifiers.md index 18a3efefc..1b60b3b0b 100644 --- a/src/doc/rustc-dev-guide/src/identifiers.md +++ b/src/doc/rustc-dev-guide/src/identifiers.md @@ -1,4 +1,4 @@ -# Identifiers in the Compiler +# Identifiers in the compiler If you have read the few previous chapters, you now know that `rustc` uses many different intermediate representations to perform different kinds of analyses. diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing_new_features.md index 9147c1b41..9bd853080 100644 --- a/src/doc/rustc-dev-guide/src/implementing_new_features.md +++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md @@ -33,7 +33,7 @@ like this; for example, the compiler team recommends filing a Major Change Proposal ([MCP][mcp]) as a lightweight way to garner support and feedback without requiring full consensus. -[mcp]: compiler/mcp.md#public-facing-changes-require-rfcbot-fcp +[mcp]: https://forge.rust-lang.org/compiler/mcp.html#public-facing-changes-require-rfcbot-fcp You don't need to have the implementation fully ready for r+ to propose an FCP, but it is generally a good idea to have at least a proof 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 b29b32a62..8cd765011 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -222,13 +222,9 @@ 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-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 +[^llvm-and-covmap-versions]: +The Rust compiler (as of <!-- date-check: --> Feb 2023) supports _LLVM Coverage Mapping Format_ 6. +The Rust compiler will automatically use the most up-to-date coverage mapping format version that is compatible with the compiler's built-in version of LLVM. ```rust @@ -301,11 +297,10 @@ $ ./x.py test tests/run-make-fulldeps/coverage --bless ``` [mir-opt-test]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/instrument_coverage.rs -[coverage-test-samples]: https://github.com/rust-lang/rust/tree/master/tests/run-make-fulldeps/coverage -[`coverage-reports`]: https://github.com/rust-lang/rust/tree/master/tests/run-make-fulldeps/coverage-reports -[`coverage-spanview`]: https://github.com/rust-lang/rust/tree/master/tests/run-make-fulldeps/coverage-spanview +[coverage-test-samples]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage +[`coverage-reports`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-reports [spanview-debugging]: compiler-debugging.md#viewing-spanview-output -[`coverage-llvmir`]: https://github.com/rust-lang/rust/tree/master/tests/run-make-fulldeps/coverage-llvmir +[`coverage-llvmir`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-llvmir ## Implementation Details of the `InstrumentCoverage` MIR Pass diff --git a/src/doc/rustc-dev-guide/src/mir/debugging.md b/src/doc/rustc-dev-guide/src/mir/debugging.md index 3da17785b..4e1d68938 100644 --- a/src/doc/rustc-dev-guide/src/mir/debugging.md +++ b/src/doc/rustc-dev-guide/src/mir/debugging.md @@ -14,10 +14,10 @@ elements obscured by overlaps, and tooltips to view the MIR statements). This flag takes an optional value: `statement` (the default), `terminator`, or `block`, to generate span highlights with different levels of granularity. -`-Z dump-mir=F` is a handy compiler options that will let you view the MIR for +`-Z dump-mir=F` is a handy compiler option that will let you view the MIR for each function at each stage of compilation. `-Z dump-mir` takes a **filter** `F` which allows you to control which functions and which passes you are -interesting in. For example: +interested in. For example: ```bash > rustc -Z dump-mir=foo ... diff --git a/src/doc/rustc-dev-guide/src/mir/visitor.md b/src/doc/rustc-dev-guide/src/mir/visitor.md index 505b700b3..17186fe75 100644 --- a/src/doc/rustc-dev-guide/src/mir/visitor.md +++ b/src/doc/rustc-dev-guide/src/mir/visitor.md @@ -37,10 +37,10 @@ code that will execute whenever a `foo` is found. If you want to recursively walk the contents of the `foo`, you then invoke the `super_foo` method. (NB. You never want to override `super_foo`.) -A very simple example of a visitor can be found in [`LocalUseCounter`]. -By implementing `visit_local` method, this visitor counts how many times each local is used. +A very simple example of a visitor can be found in [`LocalUseVisitor`]. +By implementing `visit_local` method, this visitor counts how many times each local is mutably used. -[`LocalUseCounter`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/simplify_try/struct.LocalUseCounter.html +[`LocalUseVisitor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/const_debuginfo/struct.LocalUseVisitor.html ## Traversal diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md index ca37f94b2..de06c742b 100644 --- a/src/doc/rustc-dev-guide/src/overview.md +++ b/src/doc/rustc-dev-guide/src/overview.md @@ -1,4 +1,4 @@ -# Overview of the Compiler +# Overview of the compiler <!-- toc --> diff --git a/src/doc/rustc-dev-guide/src/profiling/with_perf.md b/src/doc/rustc-dev-guide/src/profiling/with_perf.md index af30b4732..c9bd88ecd 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with_perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with_perf.md @@ -90,14 +90,15 @@ You can also use that same command to use cachegrind or other profiling tools. If you prefer to run things manually, that is also possible. You first need to find the source for the test you want. Sources for the tests -are found in [the `collector/benchmarks` directory][dir]. So let's go -into the directory of a specific test; we'll use `clap-rs` as an -example: +are found in [the `collector/compile-benchmarks` directory][compile-time dir] +and [the `collector/runtime-benchmarks` directory][runtime dir]. So let's +go into the directory of a specific test; we'll use `clap-rs` as an example: -[dir]: https://github.com/rust-lang/rustc-perf/tree/master/collector/benchmarks +[compile-time dir]: https://github.com/rust-lang/rustc-perf/tree/master/collector/compile-benchmarks +[runtime dir]: https://github.com/rust-lang/rustc-perf/tree/master/collector/runtime-benchmarks ```bash -cd collector/benchmarks/clap-rs +cd collector/compile-benchmarks/clap-3.1.6 ``` In this case, let's say we want to profile the `cargo check` 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 bb19ad9d3..3c2102a50 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,34 +7,8 @@ To get diagnostics from the compiler, configure `rustc_interface::Config` to output diagnostic to a buffer, and run `TyCtxt.analysis`. The following was tested -with <!-- date-check: Jan 2023 --> `nightly-2022-12-19` (See [here][example] -for the complete example): - -[example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-getting-diagnostics.rs +with <!-- date-check: Feb 2023 --> `nightly-2023-02-13`: ```rust -let buffer = sync::Arc::new(sync::Mutex::new(Vec::new())); -let config = rustc_interface::Config { - opts: config::Options { - // Configure the compiler to emit diagnostics in compact JSON format. - error_format: config::ErrorOutputType::Json { - pretty: false, - json_rendered: rustc_errors::emitter::HumanReadableErrorType::Default( - rustc_errors::emitter::ColorConfig::Never, - ), - }, - /* other config */ - }, - /* other config */ -}; -rustc_interface::run_compiler(config, |compiler| { - compiler.enter(|queries| { - queries.global_ctxt().unwrap().take().enter(|tcx| { - // Run the analysis phase on the local crate to trigger the type error. - let _ = tcx.analysis(()); - }); - }); -}); -// Read buffered diagnostics. -let diagnostics = String::from_utf8(buffer.lock().unwrap().clone()).unwrap(); +{{#include ../examples/rustc-driver-getting-diagnostics.rs}} ``` diff --git a/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md b/src/doc/rustc-dev-guide/src/rustc-driver-interacting-with-the-ast.md index 5b495b4fe..d058a5838 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,45 +5,8 @@ ## Getting the type of an expression To get the type of an expression, use the `global_ctxt` to get a `TyCtxt`. -The following was tested with <!-- date-check: Jan 2023 --> `nightly-2022-12-19` -(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 +The following was tested with <!-- date-check: Feb 2023 --> `nightly-2023-02-13`: ```rust -let config = rustc_interface::Config { - input: config::Input::Str { - name: source_map::FileName::Custom("main.rs".to_string()), - input: "fn main() { let message = \"Hello, world!\"; println!(\"{}\", message); }" - .to_string(), - }, - /* other config */ -}; -rustc_interface::run_compiler(config, |compiler| { - compiler.enter(|queries| { - // Analyze the crate and inspect the types under the cursor. - queries.global_ctxt().unwrap().take().enter(|tcx| { - // Every compilation contains a single crate. - let hir_krate = tcx.hir(); - // Iterate over the top-level items in the crate, looking for the main function. - for id in hir_krate.items() { - let item = hir_krate.item(id); - // Use pattern-matching to find a specific node inside the main function. - if let rustc_hir::ItemKind::Fn(_, _, body_id) = item.kind { - let expr = &tcx.hir().body(body_id).value; - if let rustc_hir::ExprKind::Block(block, _) = expr.kind { - if let rustc_hir::StmtKind::Local(local) = block.stmts[0].kind { - if let Some(expr) = local.init { - let hir_id = expr.hir_id; // hir_id identifies the string "Hello, world!" - let def_id = tcx.hir().local_def_id(item.hir_id()); // def_id identifies the main function - let ty = tcx.typeck(def_id).node_type(hir_id); - println!("{:?}: {:?}", expr, ty); - } - } - } - } - } - }) - }); -}); +{{#include ../examples/rustc-driver-interacting-with-the-ast.rs}} ``` diff --git a/src/doc/rustc-dev-guide/src/rustc-driver.md b/src/doc/rustc-dev-guide/src/rustc-driver.md index cef50111d..192811da1 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver.md @@ -1,4 +1,4 @@ -# The Rustc Driver and Interface +# `rustc_driver` and `rustc_interface` The [`rustc_driver`] is essentially `rustc`'s `main()` function. It acts as the glue for running the various phases of the compiler in the correct order, diff --git a/src/doc/rustc-dev-guide/src/solve/canonicalization.md b/src/doc/rustc-dev-guide/src/solve/canonicalization.md new file mode 100644 index 000000000..a14be5216 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/solve/canonicalization.md @@ -0,0 +1,84 @@ +# Canonicalization + +Canonicalization is the process of *isolating* a value from its context and is necessary +for global caching of goals which include inference variables. + +The idea is that given the goals `u32: Trait<?x>` and `u32: Trait<?y>`, where `?x` and `?y` +are two different currently unconstrained inference variables, we should get the same result +for both goals. We can therefore prove *the canonical query* `exists<T> u32: Trait<T>` once +and reuse the result. + +Let's first go over the way canonical queries work and then dive into the specifics of +how canonicalization works. + +## A walkthrough of canonical queries + +To make this a bit easier, let's use the trait goal `u32: Trait<?x>` as an example with the +assumption that the only relevant impl is `impl<T> Trait<Vec<T>> for u32`. + +### Canonicalizing the input + +We start by *canonicalizing* the goal, replacing inference variables with existential and +placeholders with universal bound variables. This would result in the *canonical goal* +`exists<T> u32: Trait<T>`. + +We remember the original values of all bound variables in the original context. Here this would +map `T` back to `?x`. These original values are used later on when dealing with the query +response. + +We now call the canonical query with the canonical goal. + +### Instantiating the canonical goal inside of the query + +To actually try to prove the canonical goal we start by instantiating the bound variables with +inference variables and placeholders again. + +This happens inside of the query in a completely separate `InferCtxt`. Inside of the query we +now have a goal `u32: Trait<?0>`. We also remember which value we've used to instantiate the bound +variables in the canonical goal, which maps `T` to `?0`. + +We now compute the goal `u32: Trait<?0>` and figure out that this holds, but we've constrained +`?0` to `Vec<?1>`. We finally convert this result to something useful to the caller. + +### Canonicalizing the query response + +We have to return to the caller both whether the goal holds, and the inference constraints +from inside of the query. + +To return the inference results to the caller we canonicalize the mapping from bound variables +to the instantiated values in the query. This means that the query response is `Certainty::Yes` +and a mapping from `T` to `exists<U> Vec<U>`. + +### Instantiating the query response + +The caller now has to apply the constraints returned by the query. For this they first +instantiate the bound variables of the canonical response with inference variables and +placeholders again, so the mapping in the response is now from `T` to `Vec<?z>`. + +It now equates the original value of `T` (`?x`) with the value for `T` in the +response (`Vec<?z>`), which correctly constrains `?x` to `Vec<?z>`. + +## `ExternalConstraints` + +Computing a trait goal may not only constrain inference variables, it can also add region +obligations, e.g. given a goal `(): AOutlivesB<'a, 'b>` we would like to return the fact that +`'a: 'b` has to hold. + +This is done by not only returning the mapping from bound variables to the instantiated values +from the query but also extracting additional `ExternalConstraints` from the `InferCtxt` context +while building the response. + +## How exactly does canonicalization work + +TODO: link to code once the PR lands and elaborate + +- types and consts: infer to existentially bound var, placeholder to universally bound var, + considering universes +- generic parameters in the input get treated as placeholders in the root universe +- all regions in the input get all mapped to existentially bound vars and we "uniquify" them. + `&'a (): Trait<'a>` gets canonicalized to `exists<'0, '1> &'0 (): Trait<'1>`. We do not care + about their universes and simply put all regions into the highest universe of the input. +- once we collected all canonical vars we compress their universes, see comment in `finalize`. +- in the output everything in a universe of the caller gets put into the root universe and only + gets its correct universe when we unify the var values with the orig values of the caller +- we do not uniquify regions in the response and don't canonicalize `'static`
\ No newline at end of file diff --git a/src/doc/rustc-dev-guide/src/solve/coinduction.md b/src/doc/rustc-dev-guide/src/solve/coinduction.md new file mode 100644 index 000000000..c682e002d --- /dev/null +++ b/src/doc/rustc-dev-guide/src/solve/coinduction.md @@ -0,0 +1,250 @@ +# Coinduction + +The trait solver may use coinduction when proving goals. +Coinduction is fairly subtle so we're giving it its own chapter. + +## Coinduction and induction + +With induction, we recursively apply proofs until we end up with a finite proof tree. +Consider the example of `Vec<Vec<Vec<u32>>>: Debug` which results in the following tree. + +- `Vec<Vec<Vec<u32>>>: Debug` + - `Vec<Vec<u32>>: Debug` + - `Vec<u32>: Debug` + - `u32: Debug` + +This tree is finite. But not all goals we would want to hold have finite proof trees, +consider the following example: + +```rust +struct List<T> { + value: T, + next: Option<Box<List<T>>>, +} +``` + +For `List<T>: Send` to hold all its fields have to recursively implement `Send` as well. +This would result in the following proof tree: + +- `List<T>: Send` + - `T: Send` + - `Option<Box<List<T>>>: Send` + - `Box<List<T>>: Send` + - `List<T>: Send` + - `T: Send` + - `Option<Box<List<T>>>: Send` + - `Box<List<T>>: Send` + - ... + +This tree would be infinitely large which is exactly what coinduction is about. + +> To **inductively** prove a goal you need to provide a finite proof tree for it. +> To **coinductively** prove a goal the provided proof tree may be infinite. + +## Why is coinduction correct + +When checking whether some trait goals holds, we're asking "does there exist an `impl` +which satisfies this bound". Even if are infinite chains of nested goals, we still have a +unique `impl` which should be used. + +## How to implement coinduction + +While our implementation can not check for coinduction by trying to construct an infinite +tree as that would take infinite resources, it still makes sense to think of coinduction +from this perspective. + +As we cannot check for infinite trees, we instead search for patterns for which we know that +they would result in an infinite proof tree. The currently pattern we detect are (canonical) +cycles. If `T: Send` relies on `T: Send` then it's pretty clear that this will just go on forever. + +With cycles we have to be careful with caching. Because of canonicalization of regions and +inference variables encountering a cycle doesn't mean that we would get an infinite proof tree. +Looking at the following example: +```rust +trait Foo {} +struct Wrapper<T>(T); + +impl<T> Foo for Wrapper<Wrapper<T>> +where + Wrapper<T>: Foo +{} +``` +Proving `Wrapper<?0>: Foo` uses the impl `impl<T> Foo for Wrapper<Wrapper<T>>` which constrains +`?0` to `Wrapper<?1>` and then requires `Wrapper<?1>: Foo`. Due to canonicalization this would be +detected as a cycle. + +The idea to solve is to return a *provisional result* whenever we detect a cycle and repeatedly +retry goals until the *provisional result* is equal to the final result of that goal. We +start out by using `Yes` with no constraints as the result and then update it to the result of +the previous iteration whenever we have to rerun. + +TODO: elaborate here. We use the same approach as chalk for coinductive cycles. +Note that the treatment for inductive cycles currently differs by simply returning `Overflow`. +See [the relevant chapters][chalk] in the chalk book. + +[chalk]: https://rust-lang.github.io/chalk/book/recursive/inductive_cycles.html + + +## Future work + +We currently only consider auto-traits, `Sized`, and `WF`-goals to be coinductive. +In the future we pretty much intend for all goals to be coinductive. +Lets first elaborate on why allowing more coinductive proofs is even desirable. + +### Recursive data types already rely on coinduction... + +...they just tend to avoid them in the trait solver. + +```rust +enum List<T> { + Nil, + Succ(T, Box<List<T>>), +} + +impl<T: Clone> Clone for List<T> { + fn clone(&self) -> Self { + match self { + List::Nil => List::Nil, + List::Succ(head, tail) => List::Succ(head.clone(), tail.clone()), + } + } +} +``` + +We are using `tail.clone()` in this impl. For this we have to prove `Box<List<T>>: Clone` +which requires `List<T>: Clone` but that relies on the impl which we are currently checking. +By adding that requirement to the `where`-clauses of the impl, which is what we would +do with [perfect derive], we move that cycle into the trait solver and [get an error][ex1]. + +### Recursive data types + +We also need coinduction to reason about recursive types containing projections, +e.g. the following currently fails to compile even though it should be valid. +```rust +use std::borrow::Cow; +pub struct Foo<'a>(Cow<'a, [Foo<'a>]>); +``` +This issue has been known since at least 2015, see +[#23714](https://github.com/rust-lang/rust/issues/23714) if you want to know more. + +### Explicitly checked implied bounds + +When checking an impl, we assume that the types in the impl headers are well-formed. +This means that when using instantiating the impl we have to prove that's actually the case. +[#100051](https://github.com/rust-lang/rust/issues/100051) shows that this is not the case. +To fix this, we have to add `WF` predicates for the types in impl headers. +Without coinduction for all traits, this even breaks `core`. + +```rust +trait FromResidual<R> {} +trait Try: FromResidual<<Self as Try>::Residual> { + type Residual; +} + +struct Ready<T>(T); +impl<T> Try for Ready<T> { + type Residual = Ready<()>; +} +impl<T> FromResidual<<Ready<T> as Try>::Residual> for Ready<T> {} +``` + +When checking that the impl of `FromResidual` is well formed we get the following cycle: + +The impl is well formed if `<Ready<T> as Try>::Residual` and `Ready<T>` are well formed. +- `wf(<Ready<T> as Try>::Residual)` requires +- `Ready<T>: Try`, which requires because of the super trait +- `Ready<T>: FromResidual<Ready<T> as Try>::Residual>`, **because of implied bounds on impl** +- `wf(<Ready<T> as Try>::Residual)` :tada: **cycle** + +### Issues when extending coinduction to more goals + +There are some additional issues to keep in mind when extending coinduction. +The issues here are not relevant for the current solver. + +#### Implied super trait bounds + +Our trait system currently treats super traits, e.g. `trait Trait: SuperTrait`, +by 1) requiring that `SuperTrait` has to hold for all types which implement `Trait`, +and 2) assuming `SuperTrait` holds if `Trait` holds. + +Relying on 2) while proving 1) is unsound. This can only be observed in case of +coinductive cycles. Without cycles, whenever we rely on 2) we must have also +proven 1) without relying on 2) for the used impl of `Trait`. + +```rust +trait Trait: SuperTrait {} + +impl<T: Trait> Trait for T {} + +// Keeping the current setup for coinduction +// would allow this compile. Uff :< +fn sup<T: SuperTrait>() {} +fn requires_trait<T: Trait>() { sup::<T>() } +fn generic<T>() { requires_trait::<T>() } +``` +This is not really fundamental to coinduction but rather an existing property +which is made unsound because of it. + +##### Possible solutions + +The easiest way to solve this would be to completely remove 2) and always elaborate +`T: Trait` to `T: Trait` and `T: SuperTrait` outside of the trait solver. +This would allow us to also remove 1), but as we still have to prove ordinary +`where`-bounds on traits, that's just additional work. + +While one could imagine ways to disable cyclic uses of 2) when checking 1), +at least the ideas of myself - @lcnr - are all far to complex to be reasonable. + +#### `normalizes_to` goals and progress + +A `normalizes_to` goal represents the requirement that `<T as Trait>::Assoc` normalizes +to some `U`. This is achieved by defacto first normalizing `<T as Trait>::Assoc` and then +equating the resulting type with `U`. It should be a mapping as each projection should normalize +to exactly one type. By simply allowing infinite proof trees, we would get the following behavior: + +```rust +trait Trait { + type Assoc; +} + +impl Trait for () { + type Assoc = <() as Trait>::Assoc; +} +``` + +If we now compute `normalizes_to(<() as Trait>::Assoc, Vec<u32>)`, we would resolve the impl +and get the associated type `<() as Trait>::Assoc`. We then equate that with the expected type, +causing us to check `normalizes_to(<() as Trait>::Assoc, Vec<u32>)` again. +This just goes on forever, resulting in an infinite proof tree. + +This means that `<() as Trait>::Assoc` would be equal to any other type which is unsound. + +##### How to solve this + +**WARNING: THIS IS SUBTLE AND MIGHT BE WRONG** + +Unlike trait goals, `normalizes_to` has to be *productive*[^1]. A `normalizes_to` goal +is productive once the projection normalizes to a rigid type constructor, +so `<() as Trait>::Assoc` normalizing to `Vec<<() as Trait>::Assoc>` would be productive. + +A `normalizes_to` goal has two kinds of nested goals. Nested requirements needed to actually +normalize the projection, and the equality between the normalized projection and the +expected type. Only the equality has to be productive. A branch in the proof tree is productive +if it is either finite, or contains at least one `normalizes_to` where the alias is resolved +to a rigid type constructor. + +Alternatively, we could simply always treat the equate branch of `normalizes_to` as inductive. +Any cycles should result in infinite types, which aren't supported anyways and would only +result in overflow when deeply normalizing for codegen. + +experimentation and examples: https://hackmd.io/-8p0AHnzSq2VAE6HE_wX-w?view + +Another attempt at a summary. +- in projection eq, we must make progress with constraining the rhs +- a cycle is only ok if while equating we have a rigid ty on the lhs after norm at least once +- cycles outside of the recursive `eq` call of `normalizes_to` are always fine + +[^1]: related: https://coq.inria.fr/refman/language/core/coinductive.html#top-level-definitions-of-corecursive-functions + +[perfect derive]: https://smallcultfollowing.com/babysteps/blog/2022/04/12/implied-bounds-and-perfect-derive +[ex1]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0a9c3830b93a2380e6978d6328df8f72 diff --git a/src/doc/rustc-dev-guide/src/solve/the-solver.md b/src/doc/rustc-dev-guide/src/solve/the-solver.md new file mode 100644 index 000000000..61e6cad1c --- /dev/null +++ b/src/doc/rustc-dev-guide/src/solve/the-solver.md @@ -0,0 +1,17 @@ +# The solver + +Also consider reading the documentation for [the recursive solver in chalk][chalk] +as it is very similar to this implementation and also talks about limitations of this +approach. + +[chalk]: https://rust-lang.github.io/chalk/book/recursive.html + +The basic structure of the solver is a pure function +`fn evaluate_goal(goal: Goal<'tcx>) -> Response`. +While the actual solver is not fully pure to deal with overflow and cycles, we are +going to defer that for now. + +To deal with inference variables and to improve caching, we use +[canonicalization](./canonicalization.md). + +TODO: write the remaining code for this as well. diff --git a/src/doc/rustc-dev-guide/src/solve/trait-solving.md b/src/doc/rustc-dev-guide/src/solve/trait-solving.md new file mode 100644 index 000000000..71f6581c2 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/solve/trait-solving.md @@ -0,0 +1,114 @@ +# Trait solving (new) + +This chapter describes how trait solving works with the new WIP solver located in +[`rustc_trait_selection/solve`][solve]. Feel free to also look at the docs for +[the current solver](../traits/resolution.md) and [the chalk solver](../traits/chalk.md) +can be found separately. + +## Core concepts + +The goal of the trait system is to check whether a given trait bound is satisfied. +Most notably when typechecking the body of - potentially generic - functions. +For example: + +```rust +fn uses_vec_clone<T: Clone>(x: Vec<T>) -> (Vec<T>, Vec<T>) { + (x.clone(), x) +} +``` +Here the call to `x.clone()` requires us to prove that `Vec<T>` implements `Clone` given +the assumption that `T: Clone` is true. We can assume `T: Clone` as that will be proven by +callers of this function. + +The concept of "prove the `Vec<T>: Clone` with the assumption `T: Clone`" is called a [`Goal`]. +Both `Vec<T>: Clone` and `T: Clone` are represented using [`Predicate`]. There are other +predicates, most notably equality bounds on associated items: `<Vec<T> as IntoIterator>::Item == T`. +See the `PredicateKind` enum for an exhaustive list. A `Goal` is represented as the `predicate` we +have to prove and the `param_env` in which this predicate has to hold. + +We prove goals by checking whether each possible [`Candidate`] applies for the given goal by +recursively proving its nested goals. For a list of possible candidates with examples, look at +[`CandidateSource`]. The most important candidates are `Impl` candidates, i.e. trait implementations +written by the user, and `ParamEnv` candidates, i.e. assumptions in our current environment. + +Looking at the above example, to prove `Vec<T>: Clone` we first use +`impl<T: Clone> Clone for Vec<T>`. To use this impl we have to prove the nested +goal that `T: Clone` holds. This can use the assumption `T: Clone` from the `ParamEnv` +which does not have any nested goals. Therefore `Vec<T>: Clone` holds. + +The trait solver can either return success, ambiguity or an error as a [`CanonicalResponse`]. +For success and ambiguity it also returns constraints inference and region constraints. + +## Requirements + +Before we dive into the new solver lets first take the time to go through all of our requirements +on the trait system. We can then use these to guide our design later on. + +TODO: elaborate on these rules and get more precise about their meaning. +Also add issues where each of these rules have been broken in the past +(or still are). + +### 1. The trait solver has to be *sound* + +This means that we must never return *success* for goals for which no `impl` exists. That would +simply be unsound by assuming a trait is implemented even though it is not. When using predicates +from the `where`-bounds, the `impl` will be proved by the user of the item. + +### 2. If type checker solves generic goal concrete instantiations of that goal have the same result + +Pretty much: If we successfully typecheck a generic function concrete instantiations +of that function should also typeck. We should not get errors post-monomorphization. +We can however get overflow as in the following snippet: + +```rust +fn foo<T: Trait>(x: ) +``` + +### 3. Trait goals in empty environments are proven by a unique impl + +If a trait goal holds with an empty environment, there is a unique `impl`, +either user-defined or builtin, which is used to prove that goal. + +This is necessary for codegen to select a unique method. +An exception here are *marker traits* which are allowed to overlap. + +### 4. Normalization in empty environments results in a unique type + +Normalization for alias types/consts has a unique result. Otherwise we can easily implement +transmute in safe code. Given the following function, we have to make sure that the input and +output types always get normalized to the same concrete type. +```rust +fn foo<T: Trait>( + x: <T as Trait>::Assoc +) -> <T as Trait>::Assoc { + x +} +``` + +### 5. During coherence trait solving has to be complete + +During coherence we never return *error* for goals which can be proven. This allows overlapping +impls which would break rule 3. + +### 6. Trait solving must be (free) lifetime agnostic + +Trait solving during codegen should have the same result as during typeck. As we erase +all free regions during codegen we must not rely on them during typeck. A noteworthy example +is special behavior for `'static`. + +### 7. Removing ambiguity makes strictly more things compile + +We *should* not rely on ambiguity for things to compile. +Not doing that will cause future improvements to be breaking changes. + +### 8. semantic equality implies structural equality + +Two types being equal in the type system must mean that they have the same `TypeId`. + + +[solve]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/index.html +[`Goal`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/struct.Goal.html +[`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html +[`Candidate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/assembly/struct.Candidate.html +[`CandidateSource`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/assembly/enum.CandidateSource.html +[`CanonicalResponse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/type.CanonicalResponse.html diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 9f0c56dc4..5fc6ba809 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -24,6 +24,11 @@ See the [Adding new tests](adding.md) chapter for a tutorial on creating a new test, and the [Running tests](running.md) chapter on how to run the test suite. +Compiletest itself tries to avoid running tests when the artifacts +that are involved (mainly the compiler) haven't changed. You can use +`x test --test-args --force-rerun` to rerun a test even when none of the +inputs have changed. + ## Test suites All of the tests are in the [`tests`] directory. diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md index 96c869109..0a3de6f8b 100644 --- a/src/doc/rustc-dev-guide/src/tests/running.md +++ b/src/doc/rustc-dev-guide/src/tests/running.md @@ -175,27 +175,6 @@ By passing `--pass $mode`, you can reduce the testing time. For each mode, please see [Controlling pass/fail expectations](ui.md#controlling-passfail-expectations). -## Using incremental compilation - -You can further enable the `--incremental` flag to save additional -time in subsequent rebuilds: - -```bash -./x.py test tests/ui --incremental --test-args issue-1234 -``` - -If you don't want to include the flag with every command, you can -enable it in the `config.toml`: - -```toml -[rust] -incremental = true -``` - -Note that incremental compilation will use more disk space than usual. -If disk space is a concern for you, you might want to check the size -of the `build` directory from time to time. - ## Running tests with different "compare modes" UI tests may have different output depending on certain "modes" that diff --git a/src/doc/rustc-dev-guide/src/traits/resolution.md b/src/doc/rustc-dev-guide/src/traits/resolution.md index 9cf753b19..639ebbdec 100644 --- a/src/doc/rustc-dev-guide/src/traits/resolution.md +++ b/src/doc/rustc-dev-guide/src/traits/resolution.md @@ -163,7 +163,7 @@ impl<T: Get> Get for Box<T> { } ``` -What happens when we invoke `get_it(&Box::new(1_u16))`, for example? In this +What happens when we invoke `get(&Box::new(1_u16))`, for example? In this case, the `Self` type is `Box<u16>` – that unifies with both impls, because the first applies to all types `T`, and the second to all `Box<T>`. In order for this to be unambiguous, the compiler does a *winnowing* @@ -248,7 +248,7 @@ because we know that each resolution will resolve to a particular impl. One interesting twist has to do with nested obligations. In general, in codegen, we only to figure out which candidate applies, we do not care about nested obligations, -as these are already assumed to be true. Nonetheless, we *do* currently do fulfill all of them. +as these are already assumed to be true. Nonetheless, we *do* currently fulfill all of them. That is because it can sometimes inform the results of type inference. That is, we do not have the full substitutions in terms of the type variables of the impl available to us, so we must run trait selection to figure diff --git a/src/doc/rustc-dev-guide/src/ty.md b/src/doc/rustc-dev-guide/src/ty.md index 90e17e85f..4a6cdb7c7 100644 --- a/src/doc/rustc-dev-guide/src/ty.md +++ b/src/doc/rustc-dev-guide/src/ty.md @@ -133,7 +133,7 @@ the `ty::Ty` to be a thin pointer-like type. This allows us to do cheap comparisons for equality, along with the other benefits of interning. -[tykind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html +[tykind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html ## Allocating and working with types @@ -148,18 +148,62 @@ These methods all return a `Ty<'tcx>` – note that the lifetime you get back is arena that this `tcx` has access to. Types are always canonicalized and interned (so we never allocate exactly the same type twice). -> N.B. -> Because types are interned, it is possible to compare them for equality efficiently using `==` -> – however, this is almost never what you want to do unless you happen to be hashing and looking -> for duplicates. This is because often in Rust there are multiple ways to represent the same type, -> particularly once inference is involved. If you are going to be testing for type equality, you -> probably need to start looking into the inference code to do it right. - You can also find various common types in the `tcx` itself by accessing its fields: `tcx.types.bool`, `tcx.types.char`, etc. (See [`CommonTypes`] for more.) [`CommonTypes`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.CommonTypes.html +<!-- N.B: This section is linked from the type comparison internal lint. --> +## Comparing types + +Because types are interned, it is possible to compare them for equality efficiently using `==` +– however, this is almost never what you want to do unless you happen to be hashing and looking +for duplicates. This is because often in Rust there are multiple ways to represent the same type, +particularly once inference is involved. + +For example, the type `{integer}` (`ty::Infer(ty::IntVar(..))` an integer inference variable, +the type of an integer literal like `0`) and `u8` (`ty::UInt(..)`) should often be treated as +equal when testing whether they can be assigned to each other (which is a common operation in +diagnostics code). `==` on them will return `false` though, since they are different types. + +The simplest way to compare two types correctly requires an inference context (`infcx`). +If you have one, you can use `infcx.can_eq(param_env, ty1, ty2)` +to check whether the types can be made equal. +This is typically what you want to check during diagnostics, which is concerned with questions such +as whether two types can be assigned to each other, not whether they're represented identically in +the compiler's type-checking layer. + +When working with an inference context, you have to be careful to ensure that potential inference +variables inside the types actually belong to that inference context. If you are in a function +that has access to an inference context already, this should be the case. Specifically, this is the +case during HIR type checking or MIR borrow checking. + +Another consideration is normalization. Two types may actually be the same, but one is behind an +associated type. To compare them correctly, you have to normalize the types first. This is +primarily a concern during HIR type checking and with all types from a `TyCtxt` query +(for example from `tcx.type_of()`). + +When a `FnCtxt` or an `ObligationCtxt` is available during type checking, `.normalize(ty)` +should be used on them to normalize the type. After type checking, diagnostics code can use +`tcx.normalize_erasing_regions(ty)`. + +There are also cases where using `==` on `Ty` is fine. This is for example the case in late lints +or after monomorphization, since type checking has been completed, meaning all inference variables +are resolved and all regions have been erased. In these cases, if you know that inference variables +or normalization won't be a concern, `#[allow]` or `#[expect]`ing the lint is recommended. + +When diagnostics code does not have access to an inference context, it should be threaded through +the function calls if one is available in some place (like during type checking). + +If no inference context is available at all, then one can be created as described in +[type-inference]. But this is only useful when the involved types (for example, if +they came from a query like `tcx.type_of()`) are actually substituted with fresh +inference variables using [`fresh_substs_for_item`]. This can be used to answer questions +like "can `Vec<T>` for any `T` be unified with `Vec<u32>`?". + +[type-inference]: ./type-inference.md#creating-an-inference-context +[`fresh_substs_for_item`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.fresh_substs_for_item + ## `ty::TyKind` Variants Note: `TyKind` is **NOT** the functional programming concept of *Kind*. @@ -207,16 +251,16 @@ There are many variants on the `TyKind` enum, which you can see by looking at it - [**And many more**...][kindvars] [wikiadt]: https://en.wikipedia.org/wiki/Algebraic_data_type -[kindadt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Adt -[kindforeign]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Foreign -[kindstr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Str -[kindslice]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Slice -[kindarray]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Array -[kindrawptr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.RawPtr -[kindref]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Ref -[kindparam]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Param -[kinderr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Error -[kindvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variants +[kindadt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Adt +[kindforeign]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Foreign +[kindstr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Str +[kindslice]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Slice +[kindarray]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Array +[kindrawptr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.RawPtr +[kindref]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Ref +[kindparam]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Param +[kinderr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Error +[kindvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variants ## Import conventions diff --git a/src/doc/rustc-dev-guide/src/type-checking.md b/src/doc/rustc-dev-guide/src/type-checking.md index 08f15e30b..b60694201 100644 --- a/src/doc/rustc-dev-guide/src/type-checking.md +++ b/src/doc/rustc-dev-guide/src/type-checking.md @@ -1,10 +1,12 @@ # Type checking -The [`rustc_typeck`][typeck] crate contains the source for "type collection" -and "type checking", as well as a few other bits of related functionality. (It -draws heavily on the [type inference] and [trait solving].) +The [`hir_analysis`] crate contains the source for "type collection" as well +as a bunch of related functionality. +Checking the bodies of functions is implemented in the [`hir_typeck`] crate. +These crates draw heavily on the [type inference] and [trait solving]. -[typeck]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/index.html +[`hir_analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/index.html +[`hir_typeck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/index.html [type inference]: ./type-inference.md [trait solving]: ./traits/resolution.md diff --git a/src/doc/rustc-dev-guide/src/type-inference.md b/src/doc/rustc-dev-guide/src/type-inference.md index ca88c1686..2bafeb247 100644 --- a/src/doc/rustc-dev-guide/src/type-inference.md +++ b/src/doc/rustc-dev-guide/src/type-inference.md @@ -36,18 +36,16 @@ signature, such as the `'a` in `for<'a> fn(&'a u32)`. A region is ## Creating an inference context -You create and "enter" an inference context by doing something like +You create an inference context by doing something like the following: ```rust,ignore -tcx.infer_ctxt().enter(|infcx| { - // Use the inference context `infcx` here. -}) +let infcx = tcx.infer_ctxt().build(); +// Use the inference context `infcx` here. ``` -Within the closure, -`infcx` has the type `InferCtxt<'a, 'tcx>` for some fresh `'a`, -while `'tcx` is the same as outside the inference context. +`infcx` has the type `InferCtxt<'tcx>`, the same `'tcx` lifetime as on +the `tcx` it was built from. The `tcx.infer_ctxt` method actually returns a builder, which means there are some kinds of configuration you can do before the `infcx` is diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml index 372350403..cea6033ed 100644 --- a/src/doc/rustc/book.toml +++ b/src/doc/rustc/book.toml @@ -5,3 +5,4 @@ title = "The rustc book" [output.html] git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustc" +edit-url-template = "https://github.com/rust-lang/rust/edit/master/src/doc/rustc/{path}" diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 7e355b7fc..c7f120daf 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -49,10 +49,10 @@ Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) platform security feature. This flag is currently ignored for non-Windows targets. It takes one of the following values: -* `y`, `yes`, `on`, `checks`, or no value: enable Control Flow Guard. +* `y`, `yes`, `on`, `true`, `checks`, or no value: enable Control Flow Guard. * `nochecks`: emit Control Flow Guard metadata without runtime enforcement checks (this should only be used for testing purposes as it does not provide security enforcement). -* `n`, `no`, `off`: do not enable Control Flow Guard (the default). +* `n`, `no`, `off`, `false`: do not enable Control Flow Guard (the default). ## debug-assertions @@ -60,8 +60,8 @@ This flag lets you turn `cfg(debug_assertions)` [conditional compilation](../../reference/conditional-compilation.md#debug_assertions) on or off. It takes one of the following values: -* `y`, `yes`, `on`, or no value: enable debug-assertions. -* `n`, `no`, or `off`: disable debug-assertions. +* `y`, `yes`, `on`, `true`, or no value: enable debug-assertions. +* `n`, `no`, `off` or `false`: disable debug-assertions. If not specified, debug assertions are automatically enabled only if the [opt-level](#opt-level) is 0. @@ -82,8 +82,8 @@ Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`. This flag controls whether or not the linker includes its default libraries. It takes one of the following values: -* `y`, `yes`, `on`, or no value: include default libraries (the default). -* `n`, `no`, or `off`: exclude default libraries. +* `y`, `yes`, `on`, `true` or no value: include default libraries (the default). +* `n`, `no`, `off` or `false`: exclude default libraries. For example, for gcc flavor linkers, this issues the `-nodefaultlibs` flag to the linker. @@ -93,8 +93,8 @@ the linker. This flag controls whether or not the compiler embeds LLVM bitcode into object files. It takes one of the following values: -* `y`, `yes`, `on`, or no value: put bitcode in rlibs (the default). -* `n`, `no`, or `off`: omit bitcode from rlibs. +* `y`, `yes`, `on`, `true` or no value: put bitcode in rlibs (the default). +* `n`, `no`, `off` or `false`: omit bitcode from rlibs. LLVM bitcode is required when rustc is performing link-time optimization (LTO). It is also required on some targets like iOS ones where vendors look for LLVM @@ -135,8 +135,8 @@ flag][option-emit] for more information. This flag forces the use of frame pointers. It takes one of the following values: -* `y`, `yes`, `on`, or no value: force-enable frame pointers. -* `n`, `no`, or `off`: do not force-enable frame pointers. This does +* `y`, `yes`, `on`, `true` or no value: force-enable frame pointers. +* `n`, `no`, `off` or `false`: do not force-enable frame pointers. This does not necessarily mean frame pointers will be removed. The default behaviour, if frame pointers are not force-enabled, depends on the @@ -147,8 +147,8 @@ target. This flag forces the generation of unwind tables. It takes one of the following values: -* `y`, `yes`, `on`, or no value: Unwind tables are forced to be generated. -* `n`, `no`, or `off`: Unwind tables are not forced to be generated. If unwind +* `y`, `yes`, `on`, `true` or no value: Unwind tables are forced to be generated. +* `n`, `no`, `off` or `false`: Unwind tables are not forced to be generated. If unwind tables are required by the target an error will be emitted. The default if not specified depends on the target. @@ -202,8 +202,8 @@ options should be separated by spaces. This flag controls whether the linker will keep dead code. It takes one of the following values: -* `y`, `yes`, `on`, or no value: keep dead code. -* `n`, `no`, or `off`: remove dead code (the default). +* `y`, `yes`, `on`, `true` or no value: keep dead code. +* `n`, `no`, `off` or `false`: remove dead code (the default). An example of when this flag might be useful is when trying to construct code coverage metrics. @@ -215,8 +215,8 @@ linker will use libraries and objects shipped with Rust instead or those in the It takes one of the following values: * no value: rustc will use heuristic to disable self-contained mode if system has necessary tools. -* `y`, `yes`, `on`: use only libraries/objects shipped with Rust. -* `n`, `no`, or `off`: rely on the user or the linker to provide non-Rust libraries/objects. +* `y`, `yes`, `on`, `true`: use only libraries/objects shipped with Rust. +* `n`, `no`, `off` or `false`: rely on the user or the linker to provide non-Rust libraries/objects. This allows overriding cases when detection fails or user wants to use shipped libraries. @@ -261,8 +261,8 @@ This flag defers LTO optimizations to the linker. See [linker-plugin-LTO](../linker-plugin-lto.md) for more details. It takes one of the following values: -* `y`, `yes`, `on`, or no value: enable linker plugin LTO. -* `n`, `no`, or `off`: disable linker plugin LTO (the default). +* `y`, `yes`, `on`, `true` or no value: enable linker plugin LTO. +* `n`, `no`, `off` or `false`: disable linker plugin LTO (the default). * A path to the linker plugin. More specifically this flag will cause the compiler to replace its typical @@ -292,9 +292,9 @@ optimizations](https://llvm.org/docs/LinkTimeOptimization.html) to produce better optimized code, using whole-program analysis, at the cost of longer linking time. It takes one of the following values: -* `y`, `yes`, `on`, `fat`, or no value: perform "fat" LTO which attempts to +* `y`, `yes`, `on`, `true`, `fat`, or no value: perform "fat" LTO which attempts to perform optimizations across all crates within the dependency graph. -* `n`, `no`, `off`: disables LTO. +* `n`, `no`, `off`, `false`: disables LTO. * `thin`: perform ["thin" LTO](http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html). This is similar to "fat", but takes substantially less time to run while @@ -333,8 +333,8 @@ This flag allows you to disable [the red zone](https://en.wikipedia.org/wiki/Red_zone_\(computing\)). It takes one of the following values: -* `y`, `yes`, `on`, or no value: disable the red zone. -* `n`, `no`, or `off`: enable the red zone. +* `y`, `yes`, `on`, `true` or no value: disable the red zone. +* `n`, `no`, `off` or `false`: enable the red zone. The default behaviour, if the flag is not specified, depends on the target. @@ -376,8 +376,8 @@ overflow](../../reference/expressions/operator-expr.md#overflow). When overflow-checks are enabled, a panic will occur on overflow. This flag takes one of the following values: -* `y`, `yes`, `on`, or no value: enable overflow checks. -* `n`, `no`, or `off`: disable overflow checks. +* `y`, `yes`, `on`, `true` or no value: enable overflow checks. +* `n`, `no`, `off` or `false`: disable overflow checks. If not specified, overflow checks are enabled if [debug-assertions](#debug-assertions) are enabled, disabled otherwise. @@ -409,8 +409,8 @@ for determining whether or not it is possible to statically or dynamically link with a dependency. For example, `cdylib` crate types may only use static linkage. This flag takes one of the following values: -* `y`, `yes`, `on`, or no value: use dynamic linking. -* `n`, `no`, or `off`: use static linking (the default). +* `y`, `yes`, `on`, `true` or no value: use dynamic linking. +* `n`, `no`, `off` or `false`: use static linking (the default). ## profile-generate @@ -487,24 +487,24 @@ The list of passes should be separated by spaces. This flag controls whether [`rpath`](https://en.wikipedia.org/wiki/Rpath) is enabled. It takes one of the following values: -* `y`, `yes`, `on`, or no value: enable rpath. -* `n`, `no`, or `off`: disable rpath (the default). +* `y`, `yes`, `on`, `true` or no value: enable rpath. +* `n`, `no`, `off` or `false`: disable rpath (the default). ## save-temps This flag controls whether temporary files generated during compilation are deleted once compilation finishes. It takes one of the following values: -* `y`, `yes`, `on`, or no value: save temporary files. -* `n`, `no`, or `off`: delete temporary files (the default). +* `y`, `yes`, `on`, `true` or no value: save temporary files. +* `n`, `no`, `off` or `false`: delete temporary files (the default). ## soft-float This option controls whether `rustc` generates code that emulates floating point instructions in software. It takes one of the following values: -* `y`, `yes`, `on`, or no value: use soft floats. -* `n`, `no`, or `off`: use hardware floats (the default). +* `y`, `yes`, `on`, `true` or no value: use soft floats. +* `n`, `no`, `off` or `false`: use hardware floats (the default). ## split-debuginfo @@ -562,7 +562,7 @@ Supported values for this option are: * `v0` — The "v0" mangling scheme. The specific format is not specified at this time. -The default if not specified will use a compiler-chosen default which may +The default, if not specified, will use a compiler-chosen default which may change in the future. [name mangling]: https://en.wikipedia.org/wiki/Name_mangling diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md index efbf861ea..d8843280b 100644 --- a/src/doc/rustc/src/json.md +++ b/src/doc/rustc/src/json.md @@ -223,7 +223,6 @@ flag][option-emit] documentation. - "link": The generated crate as specified by the crate-type. - "dep-info": The `.d` file with dependency information in a Makefile-like syntax. - "metadata": The Rust `.rmeta` file containing metadata about the crate. - - "save-analysis": A JSON file emitted by the `-Zsave-analysis` feature. */ "emit": "link" } diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 160570482..9eafa27e2 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -13,6 +13,8 @@ for targets at each tier, see the [Target Tier Policy](target-tier-policy.md). Targets are identified by their "target triple" which is the string to inform the compiler what kind of output should be produced. +Component availability is tracked [here](https://rust-lang.github.io/rustup-components-history/). + ## Tier 1 with Host Tools Tier 1 targets can be thought of as "guaranteed to work". The Rust project @@ -216,7 +218,7 @@ target | std | host | notes [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3 [`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | -[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.1 RTOS | +[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD `aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) @@ -308,7 +310,7 @@ target | std | host | notes `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 `x86_64-apple-tvos` | * | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator -[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ? | | x86 64-bit QNX Neutrino 7.1 RTOS | +[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS | [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | `x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support `x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index 29e70129a..4d97b8c6c 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -12,7 +12,6 @@ The [Fuchsia team]: - Tyler Mandry ([@tmandry](https://github.com/tmandry)) - Dan Johnson ([@computerdruid](https://github.com/computerdruid)) - David Koloski ([@djkoloski](https://github.com/djkoloski)) -- Andrew Pollack ([@andrewpollack](https://github.com/andrewpollack)) - Joseph Ryan ([@P1n3appl3](https://github.com/P1n3appl3)) As the team evolves over time, the specific members listed here may differ from @@ -687,7 +686,9 @@ Rust compiler locally. See "[Targeting Fuchsia with a compiler built from source for the steps to build locally. You'll also need to download a copy of the Fuchsia SDK. The current minimum -supported SDK version is [9.20220726.1.1](https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core/linux-amd64/+/version:9.20220726.1.1). +supported SDK version is [10.20221207.2.89][minimum_supported_sdk_version]. + +[minimum_supported_sdk_version]: https://chrome-infra-packages.appspot.com/p/fuchsia/sdk/core/linux-amd64/+/version:10.20221207.2.89 Fuchsia's test runner interacts with the Fuchsia emulator and is located at `src/ci/docker/scripts/fuchsia-test-runner.py`. We can use it to start our @@ -697,7 +698,7 @@ test environment with: src/ci/docker/scripts/fuchsia-test-runner.py start --rust ${RUST_SRC_PATH}/install --sdk ${SDK_PATH} - --target-arch {x64,arm64} + --target {x86_64-unknown-fuchsia|aarch64-unknown-fuchsia} ``` Where `${RUST_SRC_PATH}/install` is the `prefix` set in `config.toml` and @@ -715,28 +716,30 @@ run the full `tests/ui` test suite: --stage=2 \ test tests/ui \ --target x86_64-unknown-fuchsia \ - --run=always --jobs 1 \ - --test-args --target-rustcflags \ - --test-args -L \ - --test-args --target-rustcflags \ - --test-args ${SDK_PATH}/arch/{x64|arm64}/sysroot/lib \ + --run=always \ --test-args --target-rustcflags \ - --test-args -L \ + --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/sysroot/lib \ --test-args --target-rustcflags \ - --test-args ${SDK_PATH}/arch/{x64|arm64}/lib \ + --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/lib \ --test-args --target-rustcflags \ - --test-args -Cpanic=abort \ - --test-args --target-rustcflags \ - --test-args -Zpanic_abort_tests \ + --test-args -Clink-arg=--undefined-version \ --test-args --remote-test-client \ --test-args src/ci/docker/scripts/fuchsia-test-runner.py \ ) ``` -*Note: The test suite cannot be run in parallel at the moment, so `x.py` -must be run with `--jobs 1` to ensure only one test runs at a time.* +By default, `x.py` compiles test binaries with `panic=unwind`. If you built your +Rust toolchain with `-Cpanic=abort`, you need to tell `x.py` to compile test +binaries with `panic=abort` as well: -When finished, the test runner can be used to stop the test environment: +```sh + --test-args --target-rustcflags \ + --test-args -Cpanic=abort \ + --test-args --target-rustcflags \ + --test-args -Zpanic_abort_tests \ +``` + +When finished testing, the test runner can be used to stop the test environment: ```sh src/ci/docker/scripts/fuchsia-test-runner.py stop @@ -764,8 +767,9 @@ ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \ * `--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. +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` @@ -866,6 +870,64 @@ ${SDK_PATH}/tools/${ARCH}/ffx debug connect -- \ Linking to a Fuchsia checkout can help with debugging Fuchsia libraries, such as [fdio]. +### Debugging the compiler test suite + +Debugging the compiler test suite requires some special configuration: + +First, we have to properly configure zxdb so it will be able to find debug +symbols and source information for our test. The test runner can do this for us +with: + +```sh +src/ci/docker/scripts/fuchsia-test-runner.py debug \ + --rust-src ${RUST_SRC_PATH} \ + --fuchsia-src ${FUCHSIA_SRC_PATH} \ + --test ${TEST} +``` + +where `${TEST}` is relative to Rust's `tests` directory (e.g. `ui/abi/...`). + +This will start a zxdb session that is properly configured for the specific test +being run. All three arguments are optional, so you can omit `--fuchsia-src` if +you don't have it downloaded. Now is a good time to set any desired breakpoints, +like `b main`. + +Next, we have to tell `x.py` not to optimize or strip debug symbols from our +test suite binaries. We can do this by passing some new arguments to `rustc` +through our `x.py` invocation. The full invocation is: + +```sh +( \ + source config-env.sh && \ + ./x.py \ + --config config.toml \ + --stage=2 \ + test tests/${TEST} \ + --target x86_64-unknown-fuchsia \ + --run=always \ + --test-args --target-rustcflags \ + --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/sysroot/lib \ + --test-args --target-rustcflags \ + --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/lib \ + --test-args --target-rustcflags \ + --test-args -Clink-arg=--undefined-version \ + --test-args --target-rustcflags \ + --test-args -Cdebuginfo=2 \ + --test-args --target-rustcflags \ + --test-args -Copt-level=0 \ + --test-args --target-rustcflags \ + --test-args -Cstrip=none \ + --test-args --remote-test-client \ + --test-args src/ci/docker/scripts/fuchsia-test-runner.py \ +) +``` + +*If you built your Rust toolchain with `panic=abort`, make sure to include the +previous flags so your test binaries are also compiled with `panic=abort`.* + +Upon running this command, the test suite binary will be run and zxdb will +attach and load any relevant debug symbols. + [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 diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 37d0c3197..38198fe6c 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -2,9 +2,9 @@ **Tier: 3** -[BlackBerry® QNX®][BlackBerry] Neutrino (nto) Real-time operating system. +[QNX®][BlackBerry] Neutrino (nto) Real-time operating system. The support has been implemented jointly by [Elektrobit Automotive GmbH][Elektrobit] -and [BlackBerry][BlackBerry]. +and [Blackberry QNX][BlackBerry]. [BlackBerry]: https://blackberry.qnx.com [Elektrobit]: https://www.elektrobit.com @@ -19,19 +19,24 @@ and [BlackBerry][BlackBerry]. Currently, only cross-compilation for QNX Neutrino on AArch64 and x86_64 are supported (little endian). Adding other architectures that are supported by QNX Neutrino is possible. -The standard library does not yet support QNX Neutrino. Therefore, only `no_std` code can -be compiled. +The standard library, including `core` and `alloc` (with default allocator) are supported. -`core` and `alloc` (with default allocator) are supported. +For building or using the Rust toolchain for QNX Neutrino, the +[QNX Software Development Platform (SDP)](https://blackberry.qnx.com/en/products/foundation-software/qnx-software-development-platform) +must be installed and initialized. +Initialization is usually done by sourcing `qnxsdp-env.sh` (this will be installed as part of the SDP, see also installation instruction provided with the SDP). +Afterwards [`qcc`](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.utilities/topic/q/qcc.html) (QNX C/C++ compiler) +should be available (in the `$PATH` variable). +`qcc` will be called e.g. for linking executables. -Applications must link against `libc.so` (see example). This is required because applications -always link against the `crt` library and `crt` depends on `libc.so`. - -The correct version of `qcc` must be available by setting the `$PATH` variable (e.g. by sourcing `qnxsdp-env.sh` of the -QNX Neutrino toolchain). +When linking `no_std` applications, they must link against `libc.so` (see example). This is +required because applications always link against the `crt` library and `crt` depends on `libc.so`. +This is done automatically when using the standard library. ### Small example application +Small `no_std` example is shown below. Applications using the standard library work as well. + ```rust,ignore (platform-specific) #![no_std] #![no_main] @@ -89,30 +94,150 @@ changelog-seen = 2 2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host (for both `aarch64` and `x86_64` targets) -Run the following: +Compiling the Rust toolchain requires the same environment variables used for compiling C binaries. +Refer to the [QNX developer manual](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.prog/topic/devel_OS_version.html). + +To compile for QNX Neutrino (aarch64 and x86_64) and Linux (x86_64): ```bash -env \ - CC_aarch64-unknown-nto-qnx710="qcc" \ - CFLAGS_aarch64-unknown-nto-qnx710="-Vgcc_ntoaarch64le_cxx" \ - CXX_aarch64-unknown-nto-qnx710="qcc" \ - AR_aarch64_unknown_nto_qnx710="ntoaarch64-ar" \ - CC_x86_64-pc-nto-qnx710="qcc" \ - CFLAGS_x86_64-pc-nto-qnx710="-Vgcc_ntox86_64_cxx" \ - CXX_x86_64-pc-nto-qnx710="qcc" \ - AR_x86_64_pc_nto_qnx710="ntox86_64-ar" \ - ./x.py build --target aarch64-unknown-nto-qnx710 --target x86_64-pc-nto-qnx710 --target x86_64-unknown-linux-gnu rustc library/core library/alloc/ +export build_env=' + CC_aarch64-unknown-nto-qnx710=qcc + CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx + CXX_aarch64-unknown-nto-qnx710=qcc + AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar + CC_x86_64-pc-nto-qnx710=qcc + CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx + CXX_x86_64-pc-nto-qnx710=qcc + AR_x86_64_pc_nto_qnx710=ntox86_64-ar' + +env $build_env \ + ./x.py build \ + --target aarch64-unknown-nto-qnx710 \ + --target x86_64-pc-nto-qnx710 \ + --target x86_64-unknown-linux-gnu \ + rustc library/core library/alloc ``` +## Running the Rust test suite + +The test suites of the Rust compiler and standard library can be executed much like other Rust targets. +The environment for testing should match the one used during compiler compilation (refer to `build_env` and `qcc`/`PATH` above) with the +addition of the TEST_DEVICE_ADDR environment variable. +The TEST_DEVICE_ADDR variable controls the remote runner and should point to the target, despite localhost being shown in the following example. +Note that some tests are failing which is why they are currently excluded by the target maintainers which can be seen in the following example. + +To run all tests on a x86_64 QNX Neutrino target: + +```bash +export TEST_DEVICE_ADDR="localhost:12345" # must address the test target, can be a SSH tunnel +export build_env=' + CC_aarch64-unknown-nto-qnx710=qcc + CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx + CXX_aarch64-unknown-nto-qnx710=qcc + AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar + CC_x86_64-pc-nto-qnx710=qcc + CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx + CXX_x86_64-pc-nto-qnx710=qcc + AR_x86_64_pc_nto_qnx710=ntox86_64-ar' + +# Disable tests that only work on the host or don't make sense for this target. +# See also: +# - src/ci/docker/host-x86_64/i686-gnu/Dockerfile +# - https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Running.20tests.20on.20remote.20target +# - .github/workflows/ci.yml +export exclude_tests=' + --exclude src/bootstrap + --exclude src/tools/error_index_generator + --exclude src/tools/linkchecker + --exclude tests/ui-fulldeps + --exclude rustc + --exclude rustdoc + --exclude tests/run-make-fulldeps' + +env $build_env \ + ./x.py test -j 1 \ + $exclude_tests \ + --stage 1 \ + --target x86_64-pc-nto-qnx710 +``` + +Currently, only one thread can be used when testing due to limitations in `libc::fork` and `libc::posix_spawnp`. +See [fork documentation](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html) +(error section) for more information. +This can be achieved by using the `-j 1` parameter in the `x.py` call. +This issue is being researched and we will try to allow parallelism in the future. + ## Building Rust programs -Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you must either build Rust with the target enabled (see "Building the target" above), or build your own copy of `core` by using -`build-std` or similar. +Rust does not yet ship pre-compiled artifacts for this target. +To compile for this target, you must either build Rust with the target enabled (see "Building the target" above), +or build your own copy of `core` by using `build-std` or similar. ## Testing -Compiled executables can directly be run on QNX Neutrino. +Compiled executables can run directly on QNX Neutrino. + +### Rust std library test suite + +The target needs sufficient resources to execute all tests. The commands below assume that a QEMU image +is used. + +* Ensure that the temporary directory used by `remote-test-server` has enough free space and inodes. + 5GB of free space and 40000 inodes are known to be sufficient (the test will create more than 32k files). + To create a QEMU image in an empty directory, run this command inside the directory: + + ```bash + mkqnximage --type=qemu --ssh-ident=$HOME/.ssh/id_ed25519.pub --data-size=5000 --data-inodes=40000 + ``` + + `/data` should have enough free resources. + Set the `TMPDIR` environment variable accordingly when running `remote-test-server`, e.g.: + ```bash + TMPDIR=/data/tmp/rust remote-test-server --bind 0.0.0.0:12345 + ``` + +* Ensure the TCP stack can handle enough parallel connections (default is 200, should be 300 or higher). + After creating an image (see above), edit the file `output/build/startup.sh`: + 1. Search for `io-pkt-v6-hc` + 2. Add the parameter `-ptcpip threads_max=300`, e.g.: + ```text + io-pkt-v6-hc -U 33:33 -d e1000 -ptcpip threads_max=300 + ``` + 3. Update the image by running `mkqnximage` again with the same parameters as above for creating it. + +* Running and stopping the virtual machine + + To start the virtual machine, run inside the directory of the VM: + + ```bash + mkqnximage --run=-h + ``` + + To stop the virtual machine, run inside the directory of the VM: + + ```bash + mkqnximage --stop + ``` + +* Ensure local networking + + Ensure that 'localhost' is getting resolved to 127.0.0.1. If you can't ping the localhost, some tests may fail. + Ensure it's appended to /etc/hosts (if first `ping` command fails). + Commands have to be executed inside the virtual machine! + + ```bash + $ ping localhost + ping: Cannot resolve "localhost" (Host name lookup failure) + + $ echo "127.0.0.1 localhost" >> /etc/hosts + + $ ping localhost + PING localhost (127.0.0.1): 56 data bytes + 64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=1 ms + ``` ## Cross-compilation toolchains and C code -Compiling C code requires the same environment variables to be set as compiling the Rust toolchain (see above), to ensure `qcc` is used with proper arguments. To ensure compatibility, do not specify any further arguments that for example change calling conventions or memory layout. +Compiling C code requires the same environment variables to be set as compiling the Rust toolchain (see above), +to ensure `qcc` is used with proper arguments. +To ensure compatibility, do not specify any further arguments that for example change calling conventions or memory layout. diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md index d666d54b3..28a004a92 100644 --- a/src/doc/rustdoc/src/how-to-read-rustdoc.md +++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md @@ -84,6 +84,9 @@ When typing in the search bar, you can prefix your search term with a type followed by a colon (such as `mod:`) to restrict the results to just that kind of item. (The available items are listed in the help popup.) +Searching for `println!` will search for a macro named `println`, just like +searching for `macro:println` does. + ### Changing displayed theme You can change the displayed theme by opening the settings menu (the gear diff --git a/src/doc/style-guide/src/cargo.md b/src/doc/style-guide/src/cargo.md index f4993ba06..13b96ca8c 100644 --- a/src/doc/style-guide/src/cargo.md +++ b/src/doc/style-guide/src/cargo.md @@ -17,8 +17,7 @@ followed by the `description` at the end of that section. Don't use quotes around any standard key names; use bare keys. Only use quoted keys for non-standard keys whose names require them, and avoid introducing such key names when possible. See the [TOML -specification](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md#table) -for details. +specification](https://toml.io/en/v1.0.0#keys) for details. Put a single space both before and after the `=` between a key and value. Do not indent any key names; start all key names at the start of a line. diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md index 29b48bb1e..4ab1c36f9 100644 --- a/src/doc/style-guide/src/statements.md +++ b/src/doc/style-guide/src/statements.md @@ -99,6 +99,84 @@ let Foo { ); ``` +#### else blocks (let-else statements) + +If a let statement contains an `else` component, also known as a let-else statement, +then the `else` component should be formatted according to the same rules as the `else` block +in [control flow expressions (i.e. if-else, and if-let-else expressions)](./expressions.md#control-flow-expressions). +Apply the same formatting rules to the components preceding +the `else` block (i.e. the `let pattern: Type = initializer_expr ...` portion) +as described [above](#let-statements) + +Similarly to if-else expressions, if the initializer +expression is multi-lined, then the `else` keyword and opening brace of the block (i.e. `else {`) +should be put on the same line as the end of the initializer +expression with a preceding space if all the following are true: + +* The initializer expression ends with one or more closing + parentheses, square brackets, and/or braces +* There is nothing else on that line +* That line is not indented beyond the indent of the first line containing the `let` keyword + +For example: + +```rust +let Some(x) = y.foo( + "abc", + fairly_long_identifier, + "def", + "123456", + "string", + "cheese", +) else { + bar() +} +``` + +Otherwise, the `else` keyword and opening brace should be placed on the next line after the end of the initializer expression, and should not be indented (the `else` keyword should be aligned with the `let` keyword). + +For example: + +```rust +let Some(x) = abcdef() + .foo( + "abc", + some_really_really_really_long_ident, + "ident", + "123456", + ) + .bar() + .baz() + .qux("fffffffffffffffff") +else { + foo_bar() +} +``` + +##### Single line let-else statements + +The entire let-else statement may be formatted on a single line if all the following are true: + +* the entire statement is *short* +* the `else` block contains a single-line expression and no statements +* the `else` block contains no comments +* the let statement components preceding the `else` block can be formatted on a single line + +```rust +let Some(1) = opt else { return }; + +let Some(1) = opt else { + return; +}; + +let Some(1) = opt else { + // nope + return +}; +``` + +Formatters may allow users to configure the value of the threshold +used to determine whether a let-else statement is *short*. ### Macros in statement position diff --git a/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md b/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md new file mode 100644 index 000000000..c7f10afac --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md @@ -0,0 +1,43 @@ +# `export-executable-symbols` + +The tracking issue for this feature is: [#84161](https://github.com/rust-lang/rust/issues/84161). + +------------------------ + +The `-Zexport-executable-symbols` compiler flag makes `rustc` export symbols from executables. The resulting binary is runnable, but can also be used as a dynamic library. This is useful for interoperating with programs written in other languages, in particular languages with a runtime like Java or Lua. + +For example on windows: +```rust +#[no_mangle] +fn my_function() -> usize { + return 42; +} + +fn main() { + println!("Hello, world!"); +} +``` + +A standard `cargo build` will produce a `.exe` without an export directory. When the `export-executable-symbols` flag is added + +```Bash +export RUSTFLAGS="-Zexport-executable-symbols" +cargo build +``` + +the binary has an export directory with the functions: + +```plain +The Export Tables (interpreted .edata section contents) + +... + +[Ordinal/Name Pointer] Table + [ 0] my_function + [ 1] main +``` +(the output of `objdump -x` on the binary) + +Please note that the `#[no_mangle]` attribute is required. Without it, the symbol is not exported. + +The equivalent of this flag in C and C++ compilers is the `__declspec(dllexport)` annotation or the `-rdynamic` linker flag. diff --git a/src/doc/unstable-book/src/compiler-flags/instrument-xray.md b/src/doc/unstable-book/src/compiler-flags/instrument-xray.md new file mode 100644 index 000000000..7fb33cd68 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/instrument-xray.md @@ -0,0 +1,39 @@ +# `instrument-xray` + +The tracking issue for this feature is: [#102921](https://github.com/rust-lang/rust/issues/102921). + +------------------------ + +Enable generation of NOP sleds for XRay function tracing instrumentation. +For more information on XRay, +read [LLVM documentation](https://llvm.org/docs/XRay.html), +and/or the [XRay whitepaper](http://research.google.com/pubs/pub45287.html). + +Set the `-Z instrument-xray` compiler flag in order to enable XRay instrumentation. + + - `-Z instrument-xray` – use the default settings + - `-Z instrument-xray=skip-exit` – configure a custom setting + - `-Z instrument-xray=ignore-loops,instruction-threshold=300` – + multiple settings separated by commas + +Supported options: + + - `always` – force instrumentation of all functions + - `never` – do no instrument any functions + - `ignore-loops` – ignore presence of loops, + instrument functions based only on instruction count + - `instruction-threshold=10` – set a different instruction threshold for instrumentation + - `skip-entry` – do no instrument function entry + - `skip-exit` – do no instrument function exit + +The default settings are: + + - instrument both entry & exit from functions + - instrument functions with at least 200 instructions, + or containing a non-trivial loop + +Note that `-Z instrument-xray` only enables generation of NOP sleds +which on their own don't do anything useful. +In order to actually trace the functions, +you will need to link a separate runtime library of your choice, +such as Clang's [XRay Runtime Library](https://www.llvm.org/docs/XRay.html#xray-runtime-library). diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 70c3a445b..262cef345 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -531,6 +531,24 @@ LLVM KCFI is supported on the following targets: See the [Clang KernelControlFlowIntegrity documentation][clang-kcfi] for more details. +# KernelAddressSanitizer + +KernelAddressSanitizer (KASAN) is a freestanding version of AddressSanitizer +which is suitable for detecting memory errors in programs which do not have a +runtime environment, such as operating system kernels. KernelAddressSanitizer +requires manual implementation of the underlying functions used for tracking +KernelAddressSanitizer state. + +KernelAddressSanitizer is supported on the following targets: + +* `aarch64-unknown-none` +* `riscv64gc-unknown-none-elf` +* `riscv64imac-unknown-none-elf` +* `x86_64-unknown-none` + +See the [Linux Kernel's KernelAddressSanitizer documentation][linux-kasan] for +more details. + # LeakSanitizer LeakSanitizer is run-time memory leak detector. @@ -714,6 +732,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT * [AddressSanitizer in Clang][clang-asan] * [ControlFlowIntegrity in Clang][clang-cfi] * [HWAddressSanitizer in Clang][clang-hwasan] +* [Linux Kernel's KernelAddressSanitizer documentation][linux-kasan] * [LeakSanitizer in Clang][clang-lsan] * [MemorySanitizer in Clang][clang-msan] * [MemTagSanitizer in LLVM][llvm-memtag] @@ -727,4 +746,5 @@ 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 +[linux-kasan]: https://www.kernel.org/doc/html/latest/dev-tools/kasan.html [llvm-memtag]: https://llvm.org/docs/MemTagSanitizer.html diff --git a/src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md b/src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md new file mode 100644 index 000000000..51c5fd69c --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/tiny-const-eval-limit.md @@ -0,0 +1,6 @@ +# `tiny-const-eval-limit` + +-------------------- + +The `-Ztiny-const-eval-limit` compiler flag sets a tiny, non-configurable limit for const eval. +This flag should only be used by const eval tests in the rustc test suite. diff --git a/src/doc/unstable-book/src/library-features/char-error-internals.md b/src/doc/unstable-book/src/library-features/char-error-internals.md deleted file mode 100644 index 8013b4988..000000000 --- a/src/doc/unstable-book/src/library-features/char-error-internals.md +++ /dev/null @@ -1,5 +0,0 @@ -# `char_error_internals` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- diff --git a/src/doc/unstable-book/src/library-features/int-error-internals.md b/src/doc/unstable-book/src/library-features/int-error-internals.md deleted file mode 100644 index 402e4fa5e..000000000 --- a/src/doc/unstable-book/src/library-features/int-error-internals.md +++ /dev/null @@ -1,5 +0,0 @@ -# `int_error_internals` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- |