diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:25:56 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:25:56 +0000 |
commit | 018c4950b9406055dec02ef0fb52f132e2bb1e2c (patch) | |
tree | a835ebdf2088ef88fa681f8fad45f09922c1ae9a /src/doc | |
parent | Adding debian version 1.75.0+dfsg1-5. (diff) | |
download | rustc-018c4950b9406055dec02ef0fb52f132e2bb1e2c.tar.xz rustc-018c4950b9406055dec02ef0fb52f132e2bb1e2c.zip |
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/doc')
105 files changed, 2168 insertions, 452 deletions
diff --git a/src/doc/book/CONTRIBUTING.md b/src/doc/book/CONTRIBUTING.md index a58ea4203..a20cb5850 100644 --- a/src/doc/book/CONTRIBUTING.md +++ b/src/doc/book/CONTRIBUTING.md @@ -70,4 +70,4 @@ a new language! We're waiting on [mdbook support] for multiple languages before we merge any in, but feel free to start! [Translations]: https://github.com/rust-lang/book/issues?q=is%3Aopen+is%3Aissue+label%3ATranslations -[mdbook support]: https://github.com/rust-lang-nursery/mdBook/issues/5 +[mdbook support]: https://github.com/rust-lang/mdBook/issues/5 diff --git a/src/doc/book/README.md b/src/doc/book/README.md index f6341efc9..c70c85e72 100644 --- a/src/doc/book/README.md +++ b/src/doc/book/README.md @@ -26,7 +26,7 @@ See the [releases] to download just the code of all the code listings that appea Building the book requires [mdBook], ideally the same version that rust-lang/rust uses in [this file][rust-mdbook]. To get it: -[mdBook]: https://github.com/rust-lang-nursery/mdBook +[mdBook]: https://github.com/rust-lang/mdBook [rust-mdbook]: https://github.com/rust-lang/rust/blob/master/src/tools/rustbook/Cargo.toml ```bash @@ -93,7 +93,7 @@ a new language! We're waiting on [mdbook support] for multiple languages before we merge any in, but feel free to start! [Translations]: https://github.com/rust-lang/book/issues?q=is%3Aopen+is%3Aissue+label%3ATranslations -[mdbook support]: https://github.com/rust-lang-nursery/mdBook/issues/5 +[mdbook support]: https://github.com/rust-lang/mdBook/issues/5 ## Spellchecking diff --git a/src/doc/book/src/ch01-02-hello-world.md b/src/doc/book/src/ch01-02-hello-world.md index 8d8d754d7..f29146379 100644 --- a/src/doc/book/src/ch01-02-hello-world.md +++ b/src/doc/book/src/ch01-02-hello-world.md @@ -198,4 +198,4 @@ code. Next, we’ll introduce you to the Cargo tool, which will help you write real-world Rust programs. [troubleshooting]: ch01-01-installation.html#troubleshooting -[devtools]: appendix-04-useful-development-tools.md +[devtools]: appendix-04-useful-development-tools.html diff --git a/src/doc/edition-guide/src/editions/advanced-migrations.md b/src/doc/edition-guide/src/editions/advanced-migrations.md index b804ae644..a1a5d8071 100644 --- a/src/doc/edition-guide/src/editions/advanced-migrations.md +++ b/src/doc/edition-guide/src/editions/advanced-migrations.md @@ -190,7 +190,7 @@ We're now more idiomatic, and we didn't have to fix our code manually! [`cargo fix`]: ../../cargo/commands/cargo-fix.html [`explicit-outlives-requirements`]: ../../rustc/lints/listing/allowed-by-default.html#explicit-outlives-requirements [`keyword-idents`]: ../../rustc/lints/listing/allowed-by-default.html#keyword-idents -[`rustfix`]: https://github.com/rust-lang/rustfix +[`rustfix`]: https://crates.io/crates/rustfix [`unused-extern-crates`]: ../../rustc/lints/listing/allowed-by-default.html#unused-extern-crates [Cargo features]: ../../cargo/reference/features.html [Cargo package]: ../../cargo/reference/manifest.html#the-package-section @@ -206,5 +206,5 @@ We're now more idiomatic, and we didn't have to fix our code manually! [proc macros]: ../../reference/procedural-macros.html [Rust Analyzer extension]: https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer [rustdoc-annotation]: ../../rustdoc/documentation-tests.html#attributes -[rustfix-examples]: https://github.com/rust-lang/rustfix/tree/master/examples +[rustfix-examples]: https://github.com/rust-lang/cargo/tree/master/crates/rustfix/examples [Visual Studio Code]: https://code.visualstudio.com/ diff --git a/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md b/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md index 25da6d71c..b4a405880 100644 --- a/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md +++ b/src/doc/edition-guide/src/rust-2021/disjoint-capture-in-closures.md @@ -32,7 +32,7 @@ Disjoint capture was proposed as part of [RFC 2229](https://github.com/rust-lang As a part of the 2021 edition a migration lint, `rust_2021_incompatible_closure_captures`, has been added in order to aid in automatic migration of Rust 2018 codebases to Rust 2021. -In order to have `rustfix` migrate your code to be Rust 2021 Edition compatible, run: +In order to migrate your code to be Rust 2021 Edition compatible, run: ```sh cargo fix --edition diff --git a/src/doc/edition-guide/src/rust-2021/prelude.md b/src/doc/edition-guide/src/rust-2021/prelude.md index be1fbf111..7b05ecc09 100644 --- a/src/doc/edition-guide/src/rust-2021/prelude.md +++ b/src/doc/edition-guide/src/rust-2021/prelude.md @@ -36,7 +36,7 @@ The tracking issue [can be found here](https://github.com/rust-lang/rust/issues/ As a part of the 2021 edition a migration lint, `rust_2021_prelude_collisions`, has been added in order to aid in automatic migration of Rust 2018 codebases to Rust 2021. -In order to have `rustfix` migrate your code to be Rust 2021 Edition compatible, run: +In order to migrate your code to be Rust 2021 Edition compatible, run: ```sh cargo fix --edition @@ -44,7 +44,7 @@ cargo fix --edition The lint detects cases where functions or methods are called that have the same name as the methods defined in one of the new prelude traits. In some cases, it may rewrite your calls in various ways to ensure that you continue to call the same function you did before. -If you'd like to migrate your code manually or better understand what `rustfix` is doing, below we've outlined the situations where a migration is needed along with a counter example of when it's not needed. +If you'd like to migrate your code manually or better understand what `cargo fix` is doing, below we've outlined the situations where a migration is needed along with a counter example of when it's not needed. ### Migration needed diff --git a/src/doc/edition-guide/src/rust-2021/reserving-syntax.md b/src/doc/edition-guide/src/rust-2021/reserving-syntax.md index a4a7114a6..d49a46ab3 100644 --- a/src/doc/edition-guide/src/rust-2021/reserving-syntax.md +++ b/src/doc/edition-guide/src/rust-2021/reserving-syntax.md @@ -56,7 +56,7 @@ committed to any of them yet): As a part of the 2021 edition a migration lint, `rust_2021_prefixes_incompatible_syntax`, has been added in order to aid in automatic migration of Rust 2018 codebases to Rust 2021. -In order to have `rustfix` migrate your code to be Rust 2021 Edition compatible, run: +In order to migrate your code to be Rust 2021 Edition compatible, run: ```sh cargo fix --edition diff --git a/src/doc/embedded-book/src/start/panicking.md b/src/doc/embedded-book/src/start/panicking.md index 10f7318bb..a1365fa88 100644 --- a/src/doc/embedded-book/src/start/panicking.md +++ b/src/doc/embedded-book/src/start/panicking.md @@ -87,7 +87,7 @@ use cortex_m_rt::entry; #[entry] fn main() -> ! { let xs = [0, 1, 2]; - let i = xs.len() + 1; + let i = xs.len(); let _y = xs[i]; // out of bounds access loop {} diff --git a/src/doc/index.md b/src/doc/index.md index 7c97c16c2..8ad5b427b 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -4,12 +4,6 @@ nav { display: none; } -body { - font-family: serif; -} -h1, h2, h3, h4, h5, h6 { - font-family: sans-serif; -} h3 { font-size: 1.35rem; } @@ -119,10 +113,14 @@ 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 Edition Guide +### Rust Version History + +[The Release Notes](releases.html) describes the change history of the Rust +toolchain and language. [The Edition Guide](edition-guide/index.html) describes the Rust editions and -their differences. +their differences. The latest version of the toolchain supports all +historical editions. ### The `rustc` Book diff --git a/src/doc/nomicon/src/phantom-data.md b/src/doc/nomicon/src/phantom-data.md index 449d9e774..cd2428d96 100644 --- a/src/doc/nomicon/src/phantom-data.md +++ b/src/doc/nomicon/src/phantom-data.md @@ -106,7 +106,14 @@ that that `Vec<T>` _owns_ values of type `T` (more precisely: may use values of in its `Drop` implementation), and Rust will thus not allow them to _dangle_ should a `Vec<T>` be dropped. -**Adding an extra `_owns_T: PhantomData<T>` field is thus _superfluous_ and accomplishes nothing**. +When a type already has a `Drop impl`, **adding an extra `_owns_T: PhantomData<T>` field +is thus _superfluous_ and accomplishes nothing**, dropck-wise (it still affects variance +and auto-traits). + + - (advanced edge case: if the type containing the `PhantomData` has no `Drop` impl at all, + but still has drop glue (by having _another_ field with drop glue), then the + dropck/`#[may_dangle]` considerations mentioned herein do apply as well: a `PhantomData<T>` + field will then require `T` to be droppable whenever the containing type goes out of scope). ___ @@ -234,14 +241,18 @@ standard library made a utility for itself called `Unique<T>` which: Here’s a table of all the wonderful ways `PhantomData` could be used: -| Phantom type | `'a` | `T` | `Send` | `Sync` | -|-----------------------------|-----------|-----------------------------|-----------|-----------| -| `PhantomData<T>` | - | covariant (with drop check) | `T: Send` | `T: Sync` | -| `PhantomData<&'a T>` | covariant | covariant | `T: Sync` | `T: Sync` | -| `PhantomData<&'a mut T>` | covariant | invariant | `T: Send` | `T: Sync` | -| `PhantomData<*const T>` | - | covariant | - | - | -| `PhantomData<*mut T>` | - | invariant | - | - | -| `PhantomData<fn(T)>` | - | contravariant | `Send` | `Sync` | -| `PhantomData<fn() -> T>` | - | covariant | `Send` | `Sync` | -| `PhantomData<fn(T) -> T>` | - | invariant | `Send` | `Sync` | -| `PhantomData<Cell<&'a ()>>` | invariant | - | `Send` | - | +| Phantom type | variance of `'a` | variance of `T` | `Send`/`Sync`<br/>(or lack thereof) | dangling `'a` or `T` in drop glue<br/>(_e.g._, `#[may_dangle] Drop`) | +|-----------------------------|:----------------:|:-----------------:|:-----------------------------------------:|:------------------------------------------------:| +| `PhantomData<T>` | - | **cov**ariant | inherited | disallowed ("owns `T`") | +| `PhantomData<&'a T>` | **cov**ariant | **cov**ariant | `Send + Sync`<br/>requires<br/>`T : Sync` | allowed | +| `PhantomData<&'a mut T>` | **cov**ariant | **inv**ariant | inherited | allowed | +| `PhantomData<*const T>` | - | **cov**ariant | `!Send + !Sync` | allowed | +| `PhantomData<*mut T>` | - | **inv**ariant | `!Send + !Sync` | allowed | +| `PhantomData<fn(T)>` | - | **contra**variant | `Send + Sync` | allowed | +| `PhantomData<fn() -> T>` | - | **cov**ariant | `Send + Sync` | allowed | +| `PhantomData<fn(T) -> T>` | - | **inv**ariant | `Send + Sync` | allowed | +| `PhantomData<Cell<&'a ()>>` | **inv**ariant | - | `Send + !Sync` | allowed | + + - Note: opting out of the `Unpin` auto-trait requires the dedicated [`PhantomPinned`] type instead. + +[`PhantomPinned`]: ../core/marker/struct.PhantomPinned.html diff --git a/src/doc/nomicon/src/races.md b/src/doc/nomicon/src/races.md index cb78ac652..d5f1ea0d3 100644 --- a/src/doc/nomicon/src/races.md +++ b/src/doc/nomicon/src/races.md @@ -6,26 +6,28 @@ Safe Rust guarantees an absence of data races, which are defined as: * one or more of them is a write * one or more of them is unsynchronized -A data race has Undefined Behavior, and is therefore impossible to perform -in Safe Rust. Data races are *mostly* prevented through Rust's ownership system: +A data race has Undefined Behavior, and is therefore impossible to perform in +Safe Rust. Data races are *mostly* prevented through Rust's ownership system: it's impossible to alias a mutable reference, so it's impossible to perform a data race. Interior mutability makes this more complicated, which is largely why -we have the Send and Sync traits (see below). +we have the Send and Sync traits (see the next section for more on this). **However Rust does not prevent general race conditions.** -This is pretty fundamentally impossible, and probably honestly undesirable. Your -hardware is racy, your OS is racy, the other programs on your computer are racy, -and the world this all runs in is racy. Any system that could genuinely claim to -prevent *all* race conditions would be pretty awful to use, if not just -incorrect. +This is mathematically impossible in situations where you do not control the +scheduler, which is true for the normal OS environment. If you do control +preemption, it _can be_ possible to prevent general races - this technique is +used by frameworks such as [RTIC](https://github.com/rtic-rs/rtic). However, +actually having control over scheduling is a very uncommon case. -So it's perfectly "fine" for a Safe Rust program to get deadlocked or do -something nonsensical with incorrect synchronization. Obviously such a program -isn't very good, but Rust can only hold your hand so far. Still, a race -condition can't violate memory safety in a Rust program on its own. Only in -conjunction with some other unsafe code can a race condition actually violate -memory safety. For instance: +For this reason, it is considered "safe" for Rust to get deadlocked or do +something nonsensical with incorrect synchronization: this is known as a general +race condition or resource race. Obviously such a program isn't very good, but +Rust of course cannot prevent all logic errors. + +In any case, a race condition cannot violate memory safety in a Rust program on +its own. Only in conjunction with some other unsafe code can a race condition +actually violate memory safety. For instance, a correct program looks like this: ```rust,no_run use std::thread; @@ -58,6 +60,9 @@ thread::spawn(move || { println!("{}", data[idx.load(Ordering::SeqCst)]); ``` +We can cause a data race if we instead do the bound check in advance, and then +unsafely access the data with an unchecked value: + ```rust,no_run use std::thread; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/src/doc/nomicon/src/vec/vec-drain.md b/src/doc/nomicon/src/vec/vec-drain.md index 7a0e7f81a..763c82ae6 100644 --- a/src/doc/nomicon/src/vec/vec-drain.md +++ b/src/doc/nomicon/src/vec/vec-drain.md @@ -93,7 +93,7 @@ impl<T> IntoIterator for Vec<T> { mem::forget(self); IntoIter { - iter: iter, + iter, _buf: buf, } } @@ -135,18 +135,16 @@ impl<'a, T> Drop for Drain<'a, T> { impl<T> Vec<T> { pub fn drain(&mut self) -> Drain<T> { - unsafe { - let iter = RawValIter::new(&self); + let iter = unsafe { RawValIter::new(&self) }; - // this is a mem::forget safety thing. If Drain is forgotten, we just - // leak the whole Vec's contents. Also we need to do this *eventually* - // anyway, so why not do it now? - self.len = 0; + // this is a mem::forget safety thing. If Drain is forgotten, we just + // leak the whole Vec's contents. Also we need to do this *eventually* + // anyway, so why not do it now? + self.len = 0; - Drain { - iter: iter, - vec: PhantomData, - } + Drain { + iter, + vec: PhantomData, } } } diff --git a/src/doc/nomicon/src/vec/vec-final.md b/src/doc/nomicon/src/vec/vec-final.md index e680e0d65..1f73036d8 100644 --- a/src/doc/nomicon/src/vec/vec-final.md +++ b/src/doc/nomicon/src/vec/vec-final.md @@ -127,7 +127,7 @@ impl<T> Vec<T> { pub fn insert(&mut self, index: usize, elem: T) { assert!(index <= self.len, "index out of bounds"); - if self.cap() == self.len { + if self.len == self.cap() { self.buf.grow(); } @@ -138,14 +138,17 @@ impl<T> Vec<T> { self.len - index, ); ptr::write(self.ptr().add(index), elem); - self.len += 1; } + + self.len += 1; } pub fn remove(&mut self, index: usize) -> T { assert!(index < self.len, "index out of bounds"); + + self.len -= 1; + unsafe { - self.len -= 1; let result = ptr::read(self.ptr().add(index)); ptr::copy( self.ptr().add(index + 1), @@ -157,18 +160,16 @@ impl<T> Vec<T> { } pub fn drain(&mut self) -> Drain<T> { - unsafe { - let iter = RawValIter::new(&self); + let iter = unsafe { RawValIter::new(&self) }; - // this is a mem::forget safety thing. If Drain is forgotten, we just - // leak the whole Vec's contents. Also we need to do this *eventually* - // anyway, so why not do it now? - self.len = 0; + // this is a mem::forget safety thing. If Drain is forgotten, we just + // leak the whole Vec's contents. Also we need to do this *eventually* + // anyway, so why not do it now? + self.len = 0; - Drain { - iter: iter, - vec: PhantomData, - } + Drain { + iter, + vec: PhantomData, } } } @@ -197,15 +198,15 @@ impl<T> IntoIterator for Vec<T> { type Item = T; type IntoIter = IntoIter<T>; fn into_iter(self) -> IntoIter<T> { - unsafe { - let iter = RawValIter::new(&self); - let buf = ptr::read(&self.buf); - mem::forget(self); + let (iter, buf) = unsafe { + (RawValIter::new(&self), ptr::read(&self.buf)) + }; - IntoIter { - iter: iter, - _buf: buf, - } + mem::forget(self); + + IntoIter { + iter, + _buf: buf, } } } diff --git a/src/doc/nomicon/src/vec/vec-insert-remove.md b/src/doc/nomicon/src/vec/vec-insert-remove.md index 722e20c45..2acee65ee 100644 --- a/src/doc/nomicon/src/vec/vec-insert-remove.md +++ b/src/doc/nomicon/src/vec/vec-insert-remove.md @@ -18,7 +18,7 @@ pub fn insert(&mut self, index: usize, elem: T) { // Note: `<=` because it's valid to insert after everything // which would be equivalent to push. assert!(index <= self.len, "index out of bounds"); - if self.cap == self.len { self.grow(); } + if self.len == self.cap { self.grow(); } unsafe { // ptr::copy(src, dest, len): "copy from src to dest len elems" @@ -28,8 +28,9 @@ pub fn insert(&mut self, index: usize, elem: T) { self.len - index, ); ptr::write(self.ptr.as_ptr().add(index), elem); - self.len += 1; } + + self.len += 1; } ``` diff --git a/src/doc/nomicon/src/vec/vec-into-iter.md b/src/doc/nomicon/src/vec/vec-into-iter.md index a3a3c8cb9..ad22ff985 100644 --- a/src/doc/nomicon/src/vec/vec-into-iter.md +++ b/src/doc/nomicon/src/vec/vec-into-iter.md @@ -68,18 +68,16 @@ impl<T> IntoIterator for Vec<T> { let cap = vec.cap; let len = vec.len; - unsafe { - IntoIter { - buf: ptr, - cap: cap, - start: ptr.as_ptr(), - end: if cap == 0 { - // can't offset off this pointer, it's not allocated! - ptr.as_ptr() - } else { - ptr.as_ptr().add(len) - }, - } + IntoIter { + buf: ptr, + cap, + start: ptr.as_ptr(), + end: if cap == 0 { + // can't offset off this pointer, it's not allocated! + ptr.as_ptr() + } else { + unsafe { ptr.as_ptr().add(len) } + }, } } } diff --git a/src/doc/nomicon/src/vec/vec-layout.md b/src/doc/nomicon/src/vec/vec-layout.md index 9129952a5..695485f34 100644 --- a/src/doc/nomicon/src/vec/vec-layout.md +++ b/src/doc/nomicon/src/vec/vec-layout.md @@ -40,7 +40,6 @@ we get the same results as using `Unique<T>`: ```rust use std::ptr::NonNull; -use std::marker::PhantomData; pub struct Vec<T> { ptr: NonNull<T>, diff --git a/src/doc/nomicon/src/vec/vec-raw.md b/src/doc/nomicon/src/vec/vec-raw.md index 0bca2daf8..a251b4af3 100644 --- a/src/doc/nomicon/src/vec/vec-raw.md +++ b/src/doc/nomicon/src/vec/vec-raw.md @@ -131,23 +131,21 @@ impl<T> IntoIterator for Vec<T> { type Item = T; type IntoIter = IntoIter<T>; fn into_iter(self) -> IntoIter<T> { - unsafe { - // need to use ptr::read to unsafely move the buf out since it's - // not Copy, and Vec implements Drop (so we can't destructure it). - let buf = ptr::read(&self.buf); - let len = self.len; - mem::forget(self); - - IntoIter { - start: buf.ptr.as_ptr(), - end: if buf.cap == 0 { - // can't offset off of a pointer unless it's part of an allocation - buf.ptr.as_ptr() - } else { - buf.ptr.as_ptr().add(len) - }, - _buf: buf, - } + // need to use ptr::read to unsafely move the buf out since it's + // not Copy, and Vec implements Drop (so we can't destructure it). + let buf = unsafe { ptr::read(&self.buf) }; + let len = self.len; + mem::forget(self); + + IntoIter { + start: buf.ptr.as_ptr(), + end: if buf.cap == 0 { + // can't offset off of a pointer unless it's part of an allocation + buf.ptr.as_ptr() + } else { + unsafe { buf.ptr.as_ptr().add(len) } + }, + _buf: buf, } } } diff --git a/src/doc/reference/src/expressions/underscore-expr.md b/src/doc/reference/src/expressions/underscore-expr.md index 069f227e9..3d170408b 100644 --- a/src/doc/reference/src/expressions/underscore-expr.md +++ b/src/doc/reference/src/expressions/underscore-expr.md @@ -8,6 +8,8 @@ Underscore expressions, denoted with the symbol `_`, are used to signify a placeholder in a destructuring assignment. They may only appear in the left-hand side of an assignment. +Note that this is distinct from the [wildcard pattern](../patterns.md#wildcard-pattern). + An example of an `_` expression: ```rust diff --git a/src/doc/reference/src/items/traits.md b/src/doc/reference/src/items/traits.md index 828a8a35f..a74d7cb84 100644 --- a/src/doc/reference/src/items/traits.md +++ b/src/doc/reference/src/items/traits.md @@ -72,8 +72,8 @@ Object safe traits can be the base trait of a [trait object]. A trait is * It must not have any associated constants. * It must not have any associated types with generics. * All associated functions must either be dispatchable from a trait object or be explicitly non-dispatchable: - * Dispatchable functions require: - * Not have any type parameters (although lifetime parameters are allowed), + * Dispatchable functions must: + * Not have any type parameters (although lifetime parameters are allowed). * Be a [method] that does not use `Self` except in the type of the receiver. * Have a receiver with one of the following types: * `&Self` (i.e. `&self`) @@ -82,7 +82,10 @@ Object safe traits can be the base trait of a [trait object]. A trait is * [`Rc<Self>`] * [`Arc<Self>`] * [`Pin<P>`] where `P` is one of the types above - * Does not have a `where Self: Sized` bound (receiver type of `Self` (i.e. `self`) implies this). + * Not have an opaque return type; that is, + * Not be an `async fn` (which has a hidden `Future` type). + * Not have a return position `impl Trait` type (`fn example(&self) -> impl Trait`). + * Not have a `where Self: Sized` bound (receiver type of `Self` (i.e. `self`) implies this). * Explicitly non-dispatchable functions require: * Have a `where Self: Sized` bound (receiver type of `Self` (i.e. `self`) implies this). diff --git a/src/doc/reference/src/paths.md b/src/doc/reference/src/paths.md index 9efbda701..30c076143 100644 --- a/src/doc/reference/src/paths.md +++ b/src/doc/reference/src/paths.md @@ -202,11 +202,20 @@ mod b { `self` resolves the path relative to the current module. `self` can only be used as the first segment, without a preceding `::`. +In a method body, a path which consists of a single `self` segment resolves to the method's self parameter. + + ```rust fn foo() {} fn bar() { self::foo(); } +struct S(bool); +impl S { + fn baz(self) { + self.0; + } +} # fn main() {} ``` diff --git a/src/doc/reference/src/type-coercions.md b/src/doc/reference/src/type-coercions.md index 45d81d386..2bdbb5349 100644 --- a/src/doc/reference/src/type-coercions.md +++ b/src/doc/reference/src/type-coercions.md @@ -41,8 +41,8 @@ sites are: } ``` - For method calls, the receiver (`self` parameter) can only take advantage - of [unsized coercions](#unsized-coercions). + For method calls, the receiver (`self` parameter) type is coerced + differently, see the documentation on [method-call expressions] for details. * Instantiations of struct, union, or enum variant fields @@ -273,3 +273,4 @@ precisely. [type cast operator]: expressions/operator-expr.md#type-cast-expressions [`Unsize`]: ../std/marker/trait.Unsize.html [`CoerceUnsized`]: ../std/ops/trait.CoerceUnsized.html +[method-call expressions]: expressions/method-call-expr.md diff --git a/src/doc/reference/src/type-layout.md b/src/doc/reference/src/type-layout.md index aae3577f5..d338eb7bc 100644 --- a/src/doc/reference/src/type-layout.md +++ b/src/doc/reference/src/type-layout.md @@ -524,6 +524,10 @@ assert_eq!(std::mem::size_of::<Enum16>(), 4); The `align` and `packed` modifiers can be used to respectively raise or lower the alignment of `struct`s and `union`s. `packed` may also alter the padding between fields (although it will not alter the padding inside of any field). +On their own, `align` and `packed` do not provide guarantees about the order +of fields in the layout of a struct or the layout of an enum variant, although +they may be combined with representations (such as `C`) which do provide such +guarantees. The alignment is specified as an integer parameter in the form of `#[repr(align(x))]` or `#[repr(packed(x))]`. The alignment value must be a diff --git a/src/doc/rust-by-example/.github/workflows/rbe.yml b/src/doc/rust-by-example/.github/workflows/rbe.yml index 76b127b96..e93054547 100644 --- a/src/doc/rust-by-example/.github/workflows/rbe.yml +++ b/src/doc/rust-by-example/.github/workflows/rbe.yml @@ -1,12 +1,19 @@ name: CI on: [push, pull_request] +env: + # Update the language picker in index.hbs to link new languages. + LANGUAGES: + jobs: test: name: Run tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 + with: + # We need the full history below. + fetch-depth: 0 - name: Update rustup run: rustup self update @@ -23,6 +30,10 @@ jobs: curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.15/mdbook-v0.4.15-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin echo "$(pwd)/bin" >> ${GITHUB_PATH} + - name: Install mdbook-i18n-helpers + run: | + cargo install mdbook-i18n-helpers --locked --version 0.3.0 + - name: Report versions run: | rustup --version @@ -41,6 +52,28 @@ jobs: https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh sh linkcheck.sh --all rust-by-example + - name: Build all translations + run: | + for po_lang in ${{ env.LANGUAGES }}; do + POT_CREATION_DATE=$(grep --max-count 1 '^"POT-Creation-Date:' po/$po_lang.po | sed -E 's/".*: (.*)\\n"/\1/') + if [[ $POT_CREATION_DATE == "" ]]; then + POT_CREATION_DATE=now + fi + + echo "::group::Building $po_lang translation as of $POT_CREATION_DATE" + rm -r src/ + git restore --source "$(git rev-list -n 1 --before "$POT_CREATION_DATE" @)" src/ + + # Set language and adjust site URL. Clear the redirects + # since they are in sync with the source files, not the + # translation. + MDBOOK_BOOK__LANGUAGE=$po_lang \ + MDBOOK_OUTPUT__HTML__SITE_URL=/rust-by-example/$po_lang/ \ + MDBOOK_OUTPUT__HTML__REDIRECT='{}' \ + mdbook build -d book/$po_lang + echo "::endgroup::" + done + - name: Upload Artifact uses: actions/upload-artifact@v3 with: diff --git a/src/doc/rust-by-example/README.md b/src/doc/rust-by-example/README.md index 2529a3fad..16b849f0b 100644 --- a/src/doc/rust-by-example/README.md +++ b/src/doc/rust-by-example/README.md @@ -27,14 +27,40 @@ mdbook serve To be able to run the examples, you must be connected to the internet; you can read all content offline, however! +The following warnings can be ignored safely. + +``` +[WARN] (mdbook::preprocess::cmd): The command wasn't found, is the "gettext" preprocessor installed? +[WARN] (mdbook::preprocess::cmd): Command: mdbook-gettext +``` + +### Using translated version + +If there is a translated resource in `po/` directory, it can be specified through `MDBOOK_BOOK__LANGUAGE` like below: + +```bash +git clone https://github.com/rust-lang/rust-by-example +cd rust-by-example +cargo install mdbook +MDBOOK_BOOK__LANGUAGE=ja mdbook build +MDBOOK_BOOK__LANGUAGE=ja mdbook serve +``` + ## Contributing Please see the [CONTRIBUTING.md] file for more details. [CONTRIBUTING.md]: https://github.com/rust-lang/rust-by-example/blob/master/CONTRIBUTING.md +## Translating + +Please see the [TRANSLATING.md] file for more details. + +[TRANSLATING.md]: https://github.com/rust-lang/rust-by-example/blob/master/TRANSLATING.md + ## Translations to other languages +* [Bulgarian](https://github.com/kberov/rust-by-example-bg) * [Chinese](https://github.com/rust-lang-cn/rust-by-example-cn) * [Japanese](https://github.com/rust-lang-ja/rust-by-example-ja) * [French](https://github.com/Songbird0/FR_RBE) diff --git a/src/doc/rust-by-example/TRANSLATING.md b/src/doc/rust-by-example/TRANSLATING.md new file mode 100644 index 000000000..c2a39f51b --- /dev/null +++ b/src/doc/rust-by-example/TRANSLATING.md @@ -0,0 +1,85 @@ +# Rust by Example translation guidelines + +Please see the [CONTRIBUTING.md] file for general contribution guidelines. +This file describes about the translation workflow. + +[CONTRIBUTING.md]: https://github.com/rust-lang/rust-by-example/blob/master/CONTRIBUTING.md + +## Translation workflow + +### Preparation + +RBE uses [mdbook-i18n-helpers](https://github.com/google/mdbook-i18n-helpers) as a translation framework. +The following tools are required. + +* GNU gettext utilities ( `msgmerge` and `msgcat` ) +* mdbook-i18n-helpers ( `cargo install mdbook-i18n-helpers` ) + +### Creating and Updating Translations + +Please see the [mdbook-i18n-helpers USAGE](https://github.com/google/mdbook-i18n-helpers/blob/main/i18n-helpers/USAGE.md) file for the detailed usage of mdbook-i18n-helpers. +The summarized command list is below: + +#### Generating a message template + +The generated message templete `po/messages.pot` is required to create or update translations. + +```bash +MDBOOK_OUTPUT='{"xgettext": {"pot-file": "messages.pot"}}' \ + mdbook build -d po +``` + +#### Creating a new translation resource + +`xx` is [ISO 639](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code. + +```bash +msginit -i po/messages.pot -l xx -o po/xx.po +``` + +#### Updating the exising translation resource + +```bash +msgmerge --update po/xx.po po/messages.pot +``` + +### Editing translation resources + +After generating a translation resource `po/xx.po`, you can write translation messages in `msgstr` entry of `po/xx.po`. +To build a translated book, the following command can be used. + +```bash +MDBOOK_BOOK__LANGUAGE=xx mdbook build +MDBOOK_BOOK__LANGUAGE=xx mdbook serve +``` + +### Add a language entry + +Please add a language entry in `.github/workflows/rbe.yml` and `theme/index.hbs` like below: + +* `rbe.yml` + +```yml +env: + # Update the language picker in index.hbs to link new languages. + LANGUAGES: xx yy zz +``` + +* `index.hbs` + +```html +<ul id="language-list" class="theme-popup" aria-label="Languages" role="menu"> + <li role="none"><button role="menuitem" class="theme"> + <a id="en">English</a> + </button></li> + <li role="none"><button role="menuitem" class="theme"> + <a id="xx">XX language</a> + </button></li> + <li role="none"><button role="menuitem" class="theme"> + <a id="yy">YY language</a> + </button></li> + <li role="none"><button role="menuitem" class="theme"> + <a id="zz">ZZ language</a> + </button></li> +</ul> +``` diff --git a/src/doc/rust-by-example/book.toml b/src/doc/rust-by-example/book.toml index 61fb4057f..e8364161b 100644 --- a/src/doc/rust-by-example/book.toml +++ b/src/doc/rust-by-example/book.toml @@ -13,6 +13,15 @@ enable = true [output.html] git-repository-url = "https://github.com/rust-lang/rust-by-example" +additional-css = [ + "theme/css/language-picker.css", +] [rust] edition = "2021" + +[build] +extra-watch-dirs = ["po"] + +[preprocessor.gettext] +after = ["links"] diff --git a/src/doc/rust-by-example/src/attribute.md b/src/doc/rust-by-example/src/attribute.md index d6a49dc01..870beb1ee 100644 --- a/src/doc/rust-by-example/src/attribute.md +++ b/src/doc/rust-by-example/src/attribute.md @@ -31,7 +31,7 @@ with the difference between them being where they apply. ``` - `#![inner_attribute]` applies to the enclosing [item][item] (typically a - module or a crate). In other words, this attribute is intepreted as + module or a crate). In other words, this attribute is interpreted as applying to the entire scope in which it's place. Here is an example where `#![allow(unusude_variables)]` applies to the whole crate (if placed in `main.rs`): diff --git a/src/doc/rust-by-example/src/cargo/test.md b/src/doc/rust-by-example/src/cargo/test.md index f2af48db5..a86b8f831 100644 --- a/src/doc/rust-by-example/src/cargo/test.md +++ b/src/doc/rust-by-example/src/cargo/test.md @@ -42,13 +42,13 @@ $ cargo test Finished dev [unoptimized + debuginfo] target(s) in 0.89 secs Running target/debug/deps/blah-d3b32b97275ec472 -running 3 tests +running 4 tests test test_bar ... ok test test_baz ... ok test test_foo_bar ... ok test test_foo ... ok -test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out +test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ``` You can also run tests whose name matches a pattern: @@ -135,7 +135,7 @@ Corro ``` What actually gets put into `ferris.txt` is this: ```shell -$ cargo test test_foo +$ cargo test test_file && cat ferris.txt Corro Ferris Corro diff --git a/src/doc/rust-by-example/src/conversion/string.md b/src/doc/rust-by-example/src/conversion/string.md index edadaaa51..9a17a2ce6 100644 --- a/src/doc/rust-by-example/src/conversion/string.md +++ b/src/doc/rust-by-example/src/conversion/string.md @@ -28,7 +28,7 @@ fn main() { ## Parsing a String -One of the more common types to convert a string into a number. The idiomatic +One of the more common types to convert a string into is a number. The idiomatic approach to this is to use the [`parse`] function and either to arrange for type inference or to specify the type to parse using the 'turbofish' syntax. Both alternatives are shown in the following example. diff --git a/src/doc/rust-by-example/src/error/abort_unwind.md b/src/doc/rust-by-example/src/error/abort_unwind.md index d38af3ce1..2afae9882 100644 --- a/src/doc/rust-by-example/src/error/abort_unwind.md +++ b/src/doc/rust-by-example/src/error/abort_unwind.md @@ -6,14 +6,17 @@ The previous section illustrates the error handling mechanism `panic`. Differen Building on the prior lemonade example, we explicitly use the panic strategy to exercise different lines of code. ```rust,editable,mdbook-runnable - fn drink(beverage: &str) { - // You shouldn't drink too much sugary beverages. + // You shouldn't drink too much sugary beverages. if beverage == "lemonade" { - if cfg!(panic="abort"){ println!("This is not your party. Run!!!!");} - else{ println!("Spit it out!!!!");} + if cfg!(panic = "abort") { + println!("This is not your party. Run!!!!"); + } else { + println!("Spit it out!!!!"); + } + } else { + println!("Some refreshing {} is all I need.", beverage); } - else{ println!("Some refreshing {} is all I need.", beverage); } } fn main() { @@ -25,16 +28,22 @@ fn main() { Here is another example focusing on rewriting `drink()` and explicitly use the `unwind` keyword. ```rust,editable - #[cfg(panic = "unwind")] -fn ah(){ println!("Spit it out!!!!");} +fn ah() { + println!("Spit it out!!!!"); +} -#[cfg(not(panic="unwind"))] -fn ah(){ println!("This is not your party. Run!!!!");} +#[cfg(not(panic = "unwind"))] +fn ah() { + println!("This is not your party. Run!!!!"); +} -fn drink(beverage: &str){ - if beverage == "lemonade"{ ah();} - else{println!("Some refreshing {} is all I need.", beverage);} +fn drink(beverage: &str) { + if beverage == "lemonade" { + ah(); + } else { + println!("Some refreshing {} is all I need.", beverage); + } } fn main() { diff --git a/src/doc/rust-by-example/src/error/multiple_error_types/boxing_errors.md b/src/doc/rust-by-example/src/error/multiple_error_types/boxing_errors.md index 84b0c41e5..ca506d413 100644 --- a/src/doc/rust-by-example/src/error/multiple_error_types/boxing_errors.md +++ b/src/doc/rust-by-example/src/error/multiple_error_types/boxing_errors.md @@ -12,7 +12,7 @@ via [`From`][from]. use std::error; use std::fmt; -// Change the alias to `Box<error::Error>`. +// Change the alias to use `Box<dyn error::Error>`. type Result<T> = std::result::Result<T, Box<dyn error::Error>>; #[derive(Debug, Clone)] diff --git a/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md b/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md index 998b741e7..e00146462 100644 --- a/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md +++ b/src/doc/rust-by-example/src/error/multiple_error_types/reenter_question_mark.md @@ -26,7 +26,7 @@ Here, we rewrite the previous example using `?`. As a result, the use std::error; use std::fmt; -// Change the alias to `Box<dyn error::Error>`. +// Change the alias to use `Box<dyn error::Error>`. type Result<T> = std::result::Result<T, Box<dyn error::Error>>; #[derive(Debug)] diff --git a/src/doc/rust-by-example/src/error/option_unwrap/defaults.md b/src/doc/rust-by-example/src/error/option_unwrap/defaults.md index 513bb1df7..e439f5cd4 100644 --- a/src/doc/rust-by-example/src/error/option_unwrap/defaults.md +++ b/src/doc/rust-by-example/src/error/option_unwrap/defaults.md @@ -38,7 +38,6 @@ Another alternative is to use `or_else`, which is also chainable, and evaluates enum Fruit { Apple, Orange, Banana, Kiwi, Lemon } fn main() { - let apple = Some(Fruit::Apple); let no_fruit: Option<Fruit> = None; let get_kiwi_as_fallback = || { println!("Providing kiwi as fallback"); diff --git a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md index 252104fef..96b24368f 100644 --- a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md +++ b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_structures.md @@ -30,6 +30,15 @@ fn main() { // You do not need a match block to destructure structs: let Foo { x : x0, y: y0 } = faa; println!("Outside: x0 = {x0:?}, y0 = {y0}"); + + // Destructuring works with nested structs as well: + struct Bar { + foo: Foo, + } + + let bar = Bar { foo: faa }; + let Bar { foo: Foo { x: nested_x, y: nested_y } } = bar; + println!("Nested: nested_x = {nested_x:?}, nested_y = {nested_y:?}"); } ``` diff --git a/src/doc/rust-by-example/src/flow_control/match/guard.md b/src/doc/rust-by-example/src/flow_control/match/guard.md index af81f64c9..df9fb2c9a 100644 --- a/src/doc/rust-by-example/src/flow_control/match/guard.md +++ b/src/doc/rust-by-example/src/flow_control/match/guard.md @@ -16,10 +16,10 @@ fn main() { match temperature { Temperature::Celsius(t) if t > 30 => println!("{}C is above 30 Celsius", t), // The `if condition` part ^ is a guard - Temperature::Celsius(t) => println!("{}C is below 30 Celsius", t), + Temperature::Celsius(t) => println!("{}C is equal to or below 30 Celsius", t), Temperature::Fahrenheit(t) if t > 86 => println!("{}F is above 86 Fahrenheit", t), - Temperature::Fahrenheit(t) => println!("{}F is below 86 Fahrenheit", t), + Temperature::Fahrenheit(t) => println!("{}F is equal to or below 86 Fahrenheit", t), } } ``` diff --git a/src/doc/rust-by-example/src/fn/closures.md b/src/doc/rust-by-example/src/fn/closures.md index e7b8c9867..379a52e43 100644 --- a/src/doc/rust-by-example/src/fn/closures.md +++ b/src/doc/rust-by-example/src/fn/closures.md @@ -14,7 +14,7 @@ variable names *must* be specified. Other characteristics of closures include: * using `||` instead of `()` around input variables. -* optional body delimitation (`{}`) for a single expression (mandatory otherwise). +* optional body delimitation (`{}`) for a single line expression (mandatory otherwise). * the ability to capture the outer environment variables. ```rust,editable diff --git a/src/doc/rust-by-example/src/fn/closures/capture.md b/src/doc/rust-by-example/src/fn/closures/capture.md index 061ef1c7b..c2f0c62ac 100644 --- a/src/doc/rust-by-example/src/fn/closures/capture.md +++ b/src/doc/rust-by-example/src/fn/closures/capture.md @@ -44,7 +44,7 @@ fn main() { // borrows `count`. // // A `mut` is required on `inc` because a `&mut` is stored inside. Thus, - // calling the closure mutates the closure which requires a `mut`. + // calling the closure mutates `count` which requires a `mut`. let mut inc = || { count += 1; println!("`count`: {}", count); diff --git a/src/doc/rust-by-example/src/index.md b/src/doc/rust-by-example/src/index.md index ecadff4cc..e42c196d1 100644 --- a/src/doc/rust-by-example/src/index.md +++ b/src/doc/rust-by-example/src/index.md @@ -21,9 +21,9 @@ Now let's begin! - [Types](types.md) - Learn about changing and defining types. -- [Conversion](conversion.md) +- [Conversion](conversion.md) - Convert between different types, such as strings, integers, and floats. -- [Expressions](expression.md) +- [Expressions](expression.md) - Learn about Expressions & how to use them. - [Flow of Control](flow_control.md) - `if`/`else`, `for`, and others. @@ -43,7 +43,7 @@ Now let's begin! - [Traits](trait.md) - A trait is a collection of methods defined for an unknown type: `Self` -- [Macros](macros.md) +- [Macros](macros.md) - Macros are a way of writing code that writes other code, which is known as metaprogramming. - [Error handling](error.md) - Learn Rust way of handling failures. @@ -53,9 +53,9 @@ Now let's begin! - [Testing](testing.md) - All sorts of testing in Rust. -- [Unsafe Operations](unsafe.md) +- [Unsafe Operations](unsafe.md) - Learn about entering a block of unsafe operations. -- [Compatibility](compatibility.md) +- [Compatibility](compatibility.md) - Handling Rust's evolution and potential compatibility issues. - [Meta](meta.md) - Documentation, Benchmarking. diff --git a/src/doc/rust-by-example/src/macros/dsl.md b/src/doc/rust-by-example/src/macros/dsl.md index 9aaeda34c..d83885a4d 100644 --- a/src/doc/rust-by-example/src/macros/dsl.md +++ b/src/doc/rust-by-example/src/macros/dsl.md @@ -12,7 +12,7 @@ an expression and have the output printed to console. macro_rules! calculate { (eval $e:expr) => { { - let val: usize = $e; // Force types to be integers + let val: usize = $e; // Force types to be unsigned integers println!("{} = {}", stringify!{$e}, val); } }; diff --git a/src/doc/rust-by-example/src/meta/doc.md b/src/doc/rust-by-example/src/meta/doc.md index b1732f837..f6978a9f4 100644 --- a/src/doc/rust-by-example/src/meta/doc.md +++ b/src/doc/rust-by-example/src/meta/doc.md @@ -46,7 +46,7 @@ impl Person { /// Gives a friendly hello! /// /// Says "Hello, [name](Person::name)" to the `Person` it is called on. - pub fn hello(& self) { + pub fn hello(&self) { println!("Hello, {}!", self.name); } } @@ -80,7 +80,7 @@ Used to inline docs, instead of linking out to separate page. pub use bar::Bar; /// bar docs -mod bar { +pub mod bar { /// the docs for Bar pub struct Bar; } diff --git a/src/doc/rust-by-example/src/meta/playground.md b/src/doc/rust-by-example/src/meta/playground.md index e78552d29..5fc488c78 100644 --- a/src/doc/rust-by-example/src/meta/playground.md +++ b/src/doc/rust-by-example/src/meta/playground.md @@ -14,7 +14,7 @@ fn main() { ``` This allows the reader to both run your code sample, but also modify and tweak -it. The key here is the adding the word `editable` to your codefence block +it. The key here is the adding of the word `editable` to your codefence block separated by a comma. ````markdown @@ -39,15 +39,22 @@ button that says "Run", which opens the code sample up in a new tab in Rust Playground. This feature is enabled if you use the `#[doc]` attribute called [`html_playground_url`][html-playground-url]. +``` +#![doc(html_playground_url = "https://play.rust-lang.org/")] +//! ``` +//! println!("Hello Wolrd"); +//! ``` +``` + ### See also: - [The Rust Playground][rust-playground] -- [rust-playground][rust-playground] +- [The Rust Playground On Github][rust-playground-github] - [The rustdoc Book][rustdoc-book] [rust-playground]: https://play.rust-lang.org/ -[rust-playground]: https://github.com/integer32llc/rust-playground/ +[rust-playground-github]: https://github.com/integer32llc/rust-playground/ [mdbook]: https://github.com/rust-lang/mdBook [official-rust-docs]: https://doc.rust-lang.org/core/ [rustdoc-book]: https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html -[html-playground-url]: https://doc.rust-lang.org/rustdoc/the-doc-attribute.html#html_playground_url +[html-playground-url]: https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html#html_playground_url diff --git a/src/doc/rust-by-example/src/scope/lifetime/explicit.md b/src/doc/rust-by-example/src/scope/lifetime/explicit.md index f0ecdf5fc..68d144a82 100644 --- a/src/doc/rust-by-example/src/scope/lifetime/explicit.md +++ b/src/doc/rust-by-example/src/scope/lifetime/explicit.md @@ -40,10 +40,10 @@ fn failed_borrow<'a>() { let _x = 12; // ERROR: `_x` does not live long enough - let y: &'a i32 = &_x; + let _y: &'a i32 = &_x; // Attempting to use the lifetime `'a` as an explicit type annotation // inside the function will fail because the lifetime of `&_x` is shorter - // than that of `y`. A short lifetime cannot be coerced into a longer one. + // than that of `_y`. A short lifetime cannot be coerced into a longer one. } fn main() { diff --git a/src/doc/rust-by-example/src/std_misc/arg.md b/src/doc/rust-by-example/src/std_misc/arg.md index b5dd89ce6..1cf8cf7ef 100644 --- a/src/doc/rust-by-example/src/std_misc/arg.md +++ b/src/doc/rust-by-example/src/std_misc/arg.md @@ -30,8 +30,7 @@ I got 3 arguments: ["1", "2", "3"]. ## Crates Alternatively, there are numerous crates that can provide extra functionality -when creating command-line applications. The [Rust Cookbook] exhibits best -practices on how to use one of the more popular command line argument crates, -`clap`. +when creating command-line applications. One of the more popular command line +argument crates being [`clap`]. -[Rust Cookbook]: https://rust-lang-nursery.github.io/rust-cookbook/cli/arguments.html +[`clap`]: https://rust-cli.github.io/book/tutorial/cli-args.html#parsing-cli-arguments-with-clap diff --git a/src/doc/rust-by-example/src/std_misc/ffi.md b/src/doc/rust-by-example/src/std_misc/ffi.md index 71977e66f..272873600 100644 --- a/src/doc/rust-by-example/src/std_misc/ffi.md +++ b/src/doc/rust-by-example/src/std_misc/ffi.md @@ -8,6 +8,16 @@ attribute containing the name of the foreign library. use std::fmt; // this extern block links to the libm library +#[cfg(target_family = "windows")] +#[link(name = "msvcrt")] +extern { + // this is a foreign function + // that computes the square root of a single precision complex number + fn csqrtf(z: Complex) -> Complex; + + fn ccosf(z: Complex) -> Complex; +} +#[cfg(target_family = "unix")] #[link(name = "m")] extern { // this is a foreign function diff --git a/src/doc/rust-by-example/src/std_misc/fs.md b/src/doc/rust-by-example/src/std_misc/fs.md index 48e4d4d66..ba2d4b4fa 100644 --- a/src/doc/rust-by-example/src/std_misc/fs.md +++ b/src/doc/rust-by-example/src/std_misc/fs.md @@ -7,7 +7,10 @@ use std::fs; use std::fs::{File, OpenOptions}; use std::io; use std::io::prelude::*; +#[cfg(target_family = "unix")] use std::os::unix; +#[cfg(target_family = "windows")] +use std::os::windows; use std::path::Path; // A simple implementation of `% cat path` @@ -62,11 +65,16 @@ fn main() { println!("`ln -s ../b.txt a/c/b.txt`"); // Create a symbolic link, returns `io::Result<()>` - if cfg!(target_family = "unix") { + #[cfg(target_family = "unix")] { unix::fs::symlink("../b.txt", "a/c/b.txt").unwrap_or_else(|why| { println!("! {:?}", why.kind()); }); } + #[cfg(target_family = "windows")] { + windows::fs::symlink_file("../b.txt", "a/c/b.txt").unwrap_or_else(|why| { + println!("! {:?}", why.to_string()); + }); + } println!("`cat a/c/b.txt`"); match cat(&Path::new("a/c/b.txt")) { diff --git a/src/doc/rust-by-example/src/std_misc/process/pipe.md b/src/doc/rust-by-example/src/std_misc/process/pipe.md index fb0be0ea1..1b1973718 100644 --- a/src/doc/rust-by-example/src/std_misc/process/pipe.md +++ b/src/doc/rust-by-example/src/std_misc/process/pipe.md @@ -6,14 +6,21 @@ process via pipes. ```rust,ignore use std::io::prelude::*; -use std::process::{Command, Stdio}; +use std::process::Stdio; static PANGRAM: &'static str = "the quick brown fox jumped over the lazy dog\n"; fn main() { // Spawn the `wc` command - let process = match Command::new("wc") + let mut cmd = if cfg!(target_family = "windows") { + let mut cmd = Command::new("powershell"); + cmd.arg("-Command").arg("$input | Measure-Object -Line -Word -Character"); + cmd + } else { + Command::new("wc") + }; + let process = match cmd .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn() { diff --git a/src/doc/rust-by-example/src/testing/unit_testing.md b/src/doc/rust-by-example/src/testing/unit_testing.md index cd8770664..bdce96334 100644 --- a/src/doc/rust-by-example/src/testing/unit_testing.md +++ b/src/doc/rust-by-example/src/testing/unit_testing.md @@ -199,7 +199,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Tests can be marked with the `#[ignore]` attribute to exclude some tests. Or to run them with command `cargo test -- --ignored` -```rust +```rust,ignore pub fn add(a: i32, b: i32) -> i32 { a + b } diff --git a/src/doc/rust-by-example/src/trait/clone.md b/src/doc/rust-by-example/src/trait/clone.md index 5d6747a47..8e04f5a2a 100644 --- a/src/doc/rust-by-example/src/trait/clone.md +++ b/src/doc/rust-by-example/src/trait/clone.md @@ -40,11 +40,11 @@ fn main() { // Clone `moved_pair` into `cloned_pair` (resources are included) let cloned_pair = moved_pair.clone(); - // Drop the original pair using std::mem::drop + // Drop the moved original pair using std::mem::drop drop(moved_pair); // Error! `moved_pair` has been dropped - //println!("copy: {:?}", moved_pair); + //println!("moved and dropped: {:?}", moved_pair); // TODO ^ Try uncommenting this line // The result from .clone() can still be used! diff --git a/src/doc/rust-by-example/src/trait/disambiguating.md b/src/doc/rust-by-example/src/trait/disambiguating.md index ae80d4acb..6fca4b032 100644 --- a/src/doc/rust-by-example/src/trait/disambiguating.md +++ b/src/doc/rust-by-example/src/trait/disambiguating.md @@ -1,8 +1,8 @@ # Disambiguating overlapping traits A type can implement many different traits. What if two traits both require -the same name? For example, many traits might have a method named `get()`. -They might even have different return types! +the same name for a function? For example, many traits might have a method +named `get()`. They might even have different return types! Good news: because each trait implementation gets its own `impl` block, it's clear which trait's `get` method you're implementing. diff --git a/src/doc/rust-by-example/src/unsafe/asm.md b/src/doc/rust-by-example/src/unsafe/asm.md index cbe52c840..a2b5b079c 100644 --- a/src/doc/rust-by-example/src/unsafe/asm.md +++ b/src/doc/rust-by-example/src/unsafe/asm.md @@ -139,8 +139,8 @@ can be written at any time, and can therefore not share its location with any ot However, to guarantee optimal performance it is important to use as few registers as possible, so they won't have to be saved and reloaded around the inline assembly block. To achieve this Rust provides a `lateout` specifier. This can be used on any output that is -written only after all inputs have been consumed. -There is also a `inlateout` variant of this specifier. +written only after all inputs have been consumed. There is also an `inlateout` variant of this +specifier. Here is an example where `inlateout` *cannot* be used in `release` mode or other optimized cases: @@ -163,11 +163,12 @@ unsafe { assert_eq!(a, 12); # } ``` -The above could work well in unoptimized cases (`Debug` mode), but if you want optimized performance (`release` mode or other optimized cases), it could not work. -That is because in optimized cases, the compiler is free to allocate the same register for inputs `b` and `c` since it knows they have the same value. However it must allocate a separate register for `a` since it uses `inout` and not `inlateout`. If `inlateout` was used, then `a` and `c` could be allocated to the same register, in which case the first instruction to overwrite the value of `c` and cause the assembly code to produce the wrong result. +In unoptimized cases (e.g. `Debug` mode), replacing `inout(reg) a` with `inlateout(reg) a` in the above example can continue to give the expected result. However, with `release` mode or other optimized cases, using `inlateout(reg) a` can instead lead to the final value `a = 16`, causing the assertion to fail. -However the following example can use `inlateout` since the output is only modified after all input registers have been read: +This is because in optimized cases, the compiler is free to allocate the same register for inputs `b` and `c` since it knows that they have the same value. Furthermore, when `inlateout` is used, `a` and `c` could be allocated to the same register, in which case the first `add` instruction would overwrite the initial load from variable `c`. This is in contrast to how using `inout(reg) a` ensures a separate register is allocated for `a`. + +However, the following example can use `inlateout` since the output is only modified after all input registers have been read: ```rust # #[cfg(target_arch = "x86_64")] { diff --git a/src/doc/rust-by-example/theme/css/language-picker.css b/src/doc/rust-by-example/theme/css/language-picker.css new file mode 100644 index 000000000..1553ed68f --- /dev/null +++ b/src/doc/rust-by-example/theme/css/language-picker.css @@ -0,0 +1,13 @@ +#language-list { + left: auto; + right: 10px; +} + +[dir="rtl"] #language-list { + left: 10px; + right: auto; +} + +#language-list a { + color: inherit; +} diff --git a/src/doc/rust-by-example/theme/index.hbs b/src/doc/rust-by-example/theme/index.hbs new file mode 100644 index 000000000..1ae579f39 --- /dev/null +++ b/src/doc/rust-by-example/theme/index.hbs @@ -0,0 +1,386 @@ +<!DOCTYPE HTML> +<html lang="{{ language }}" class="{{ default_theme }}" dir="{{ text_direction }}"> + <head> + <!-- Book generated using mdBook --> + <meta charset="UTF-8"> + <title>{{ title }}</title> + {{#if is_print }} + <meta name="robots" content="noindex"> + {{/if}} + {{#if base_url}} + <base href="{{ base_url }}"> + {{/if}} + + + <!-- Custom HTML head --> + {{> head}} + + <meta name="description" content="{{ description }}"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="theme-color" content="#ffffff"> + + {{#if favicon_svg}} + <link rel="icon" href="{{ path_to_root }}favicon.svg"> + {{/if}} + {{#if favicon_png}} + <link rel="shortcut icon" href="{{ path_to_root }}favicon.png"> + {{/if}} + <link rel="stylesheet" href="{{ path_to_root }}css/variables.css"> + <link rel="stylesheet" href="{{ path_to_root }}css/general.css"> + <link rel="stylesheet" href="{{ path_to_root }}css/chrome.css"> + {{#if print_enable}} + <link rel="stylesheet" href="{{ path_to_root }}css/print.css" media="print"> + {{/if}} + + <!-- Fonts --> + <link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css"> + {{#if copy_fonts}} + <link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css"> + {{/if}} + + <!-- Highlight.js Stylesheets --> + <link rel="stylesheet" href="{{ path_to_root }}highlight.css"> + <link rel="stylesheet" href="{{ path_to_root }}tomorrow-night.css"> + <link rel="stylesheet" href="{{ path_to_root }}ayu-highlight.css"> + + <!-- Custom theme stylesheets --> + {{#each additional_css}} + <link rel="stylesheet" href="{{ ../path_to_root }}{{ this }}"> + {{/each}} + + {{#if mathjax_support}} + <!-- MathJax --> + <script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> + {{/if}} + </head> + <body class="sidebar-visible no-js"> + <div id="body-container"> + <!-- Provide site root to javascript --> + <script> + var path_to_root = "{{ path_to_root }}"; + var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "{{ preferred_dark_theme }}" : "{{ default_theme }}"; + </script> + + <!-- Work around some values being stored in localStorage wrapped in quotes --> + <script> + try { + var theme = localStorage.getItem('mdbook-theme'); + var sidebar = localStorage.getItem('mdbook-sidebar'); + + if (theme.startsWith('"') && theme.endsWith('"')) { + localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1)); + } + + if (sidebar.startsWith('"') && sidebar.endsWith('"')) { + localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1)); + } + } catch (e) { } + </script> + + <!-- Set the theme before any content is loaded, prevents flash --> + <script> + var theme; + try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } + if (theme === null || theme === undefined) { theme = default_theme; } + var html = document.querySelector('html'); + html.classList.remove('{{ default_theme }}') + html.classList.add(theme); + var body = document.querySelector('body'); + body.classList.remove('no-js') + body.classList.add('js'); + </script> + + <input type="checkbox" id="sidebar-toggle-anchor" class="hidden"> + + <!-- Hide / unhide sidebar before it is displayed --> + <script> + var body = document.querySelector('body'); + var sidebar = null; + var sidebar_toggle = document.getElementById("sidebar-toggle-anchor"); + if (document.body.clientWidth >= 1080) { + try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } + sidebar = sidebar || 'visible'; + } else { + sidebar = 'hidden'; + } + sidebar_toggle.checked = sidebar === 'visible'; + body.classList.remove('sidebar-visible'); + body.classList.add("sidebar-" + sidebar); + </script> + + <nav id="sidebar" class="sidebar" aria-label="Table of contents"> + <div class="sidebar-scrollbox"> + {{#toc}}{{/toc}} + </div> + <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div> + </nav> + + <!-- Track and set sidebar scroll position --> + <script> + var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox'); + sidebarScrollbox.addEventListener('click', function(e) { + if (e.target.tagName === 'A') { + sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop); + } + }, { passive: true }); + var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll'); + sessionStorage.removeItem('sidebar-scroll'); + if (sidebarScrollTop) { + // preserve sidebar scroll position when navigating via links within sidebar + sidebarScrollbox.scrollTop = sidebarScrollTop; + } else { + // scroll sidebar to current active section when navigating via "next/previous chapter" buttons + var activeSection = document.querySelector('#sidebar .active'); + if (activeSection) { + activeSection.scrollIntoView({ block: 'center' }); + } + } + </script> + + <div id="page-wrapper" class="page-wrapper"> + + <div class="page"> + {{> header}} + <div id="menu-bar-hover-placeholder"></div> + <div id="menu-bar" class="menu-bar sticky"> + <div class="left-buttons"> + <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> + <i class="fa fa-bars"></i> + </label> + <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list"> + <i class="fa fa-paint-brush"></i> + </button> + <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu"> + <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li> + <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li> + <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li> + <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li> + <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li> + </ul> + {{#if search_enabled}} + <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar"> + <i class="fa fa-search"></i> + </button> + {{/if}} + </div> + + <h1 class="menu-title">{{ book_title }}</h1> + + <div class="right-buttons"> + <button id="language-toggle" class="icon-button" type="button" + title="Change language" aria-label="Change language" + aria-haspopup="true" aria-expanded="false" + aria-controls="language-list"> + <i class="fa fa-globe"></i> + </button> + <ul id="language-list" class="theme-popup" aria-label="Languages" role="menu"> + <li role="none"><button role="menuitem" class="theme"> + <a id="en">English</a> + </button></li> + </ul> + + <script> + let langToggle = document.getElementById("language-toggle"); + let langList = document.getElementById("language-list"); + langToggle.addEventListener("click", (event) => { + langList.style.display = langList.style.display == "block" ? "none" : "block"; + }); + let selectedLang = document.getElementById("{{ language }}"); + if (selectedLang) { + selectedLang.parentNode.classList.add("theme-selected"); + } + + // The path to the root, taking the current + // language into account. + {{#if (eq language "en")}} + let full_path_to_root = "{{ path_to_root }}"; + {{else}} + let full_path_to_root = "{{ path_to_root }}../"; + {{/if}} + // The page path (mdbook only gives us + // access to the path to the Markdown file). + let path = "{{ path }}".replace(/\.md$/, ".html"); + for (let lang of langList.querySelectorAll("a")) { + if (lang.id == "en") { + lang.href = `${full_path_to_root}${path}`; + } else { + lang.href = `${full_path_to_root}${lang.id}/${path}`; + } + } + </script> + + {{#if print_enable}} + <a href="{{ path_to_root }}print.html" title="Print this book" aria-label="Print this book"> + <i id="print-button" class="fa fa-print"></i> + </a> + {{/if}} + {{#if git_repository_url}} + <a href="{{git_repository_url}}" title="Git repository" aria-label="Git repository"> + <i id="git-repository-button" class="fa {{git_repository_icon}}"></i> + </a> + {{/if}} + {{#if git_repository_edit_url}} + <a href="{{git_repository_edit_url}}" title="Suggest an edit" aria-label="Suggest an edit"> + <i id="git-edit-button" class="fa fa-edit"></i> + </a> + {{/if}} + + </div> + </div> + + {{#if search_enabled}} + <div id="search-wrapper" class="hidden"> + <form id="searchbar-outer" class="searchbar-outer"> + <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header"> + </form> + <div id="searchresults-outer" class="searchresults-outer hidden"> + <div id="searchresults-header" class="searchresults-header"></div> + <ul id="searchresults"> + </ul> + </div> + </div> + {{/if}} + + <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM --> + <script> + document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible'); + document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible'); + Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) { + link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1); + }); + </script> + + <div id="content" class="content"> + <main> + {{{ content }}} + </main> + + <nav class="nav-wrapper" aria-label="Page navigation"> + <!-- Mobile navigation buttons --> + {{#previous}} + <a rel="prev" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> + <i class="fa fa-angle-left"></i> + </a> + {{/previous}} + + {{#next}} + <a rel="next prefetch" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> + <i class="fa fa-angle-right"></i> + </a> + {{/next}} + + <div style="clear: both"></div> + </nav> + </div> + </div> + + <nav class="nav-wide-wrapper" aria-label="Page navigation"> + {{#previous}} + <a rel="prev" href="{{ path_to_root }}{{link}}" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left"> + <i class="fa fa-angle-left"></i> + </a> + {{/previous}} + + {{#next}} + <a rel="next prefetch" href="{{ path_to_root }}{{link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> + <i class="fa fa-angle-right"></i> + </a> + {{/next}} + </nav> + + </div> + + {{#if live_reload_endpoint}} + <!-- Livereload script (if served using the cli tool) --> + <script> + const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:'; + const wsAddress = wsProtocol + "//" + location.host + "/" + "{{{live_reload_endpoint}}}"; + const socket = new WebSocket(wsAddress); + socket.onmessage = function (event) { + if (event.data === "reload") { + socket.close(); + location.reload(); + } + }; + + window.onbeforeunload = function() { + socket.close(); + } + </script> + {{/if}} + + {{#if google_analytics}} + <!-- Google Analytics Tag --> + <script> + var localAddrs = ["localhost", "127.0.0.1", ""]; + + // make sure we don't activate google analytics if the developer is + // inspecting the book locally... + if (localAddrs.indexOf(document.location.hostname) === -1) { + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) + })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); + + ga('create', '{{google_analytics}}', 'auto'); + ga('send', 'pageview'); + } + </script> + {{/if}} + + {{#if playground_line_numbers}} + <script> + window.playground_line_numbers = true; + </script> + {{/if}} + + {{#if playground_copyable}} + <script> + window.playground_copyable = true; + </script> + {{/if}} + + {{#if playground_js}} + <script src="{{ path_to_root }}ace.js"></script> + <script src="{{ path_to_root }}editor.js"></script> + <script src="{{ path_to_root }}mode-rust.js"></script> + <script src="{{ path_to_root }}theme-dawn.js"></script> + <script src="{{ path_to_root }}theme-tomorrow_night.js"></script> + {{/if}} + + {{#if search_js}} + <script src="{{ path_to_root }}elasticlunr.min.js"></script> + <script src="{{ path_to_root }}mark.min.js"></script> + <script src="{{ path_to_root }}searcher.js"></script> + {{/if}} + + <script src="{{ path_to_root }}clipboard.min.js"></script> + <script src="{{ path_to_root }}highlight.js"></script> + <script src="{{ path_to_root }}book.js"></script> + + <!-- Custom JS scripts --> + {{#each additional_js}} + <script src="{{ ../path_to_root }}{{this}}"></script> + {{/each}} + + {{#if is_print}} + {{#if mathjax_support}} + <script> + window.addEventListener('load', function() { + MathJax.Hub.Register.StartupHook('End', function() { + window.setTimeout(window.print, 100); + }); + }); + </script> + {{else}} + <script> + window.addEventListener('load', function() { + window.setTimeout(window.print, 100); + }); + </script> + {{/if}} + {{/if}} + + </div> + </body> +</html> diff --git a/src/doc/rust.css b/src/doc/rust.css index d33ab0326..e0bf64c33 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -1,6 +1,7 @@ /* General structure */ body { + font-family: serif; margin: 0 auto; padding: 0 15px; font-size: 18px; @@ -17,6 +18,9 @@ body { } } +h1, h2, h3, h4, h5, h6 { + font-family: sans-serif; +} h2, h3, h4, h5, h6 { font-weight: 400; line-height: 1.1; diff --git a/src/doc/rustc-dev-guide/.mailmap b/src/doc/rustc-dev-guide/.mailmap new file mode 100644 index 000000000..1a1f6ffb6 --- /dev/null +++ b/src/doc/rustc-dev-guide/.mailmap @@ -0,0 +1,5 @@ +Jynn Nelson <github@jyn.dev> <jyn514@gmail.com> +Jynn Nelson <github@jyn.dev> <joshua@yottadb.com> +Jynn Nelson <github@jyn.dev> <jyn.nelson@redjack.com> +Jynn Nelson <github@jyn.dev> <jnelson@cloudflare.com> +Jynn Nelson <github@jyn.dev> diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 4a7fd2b77..e484b6af6 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -56,6 +56,7 @@ - [RISC-V](notification-groups/risc-v.md) - [Windows](notification-groups/windows.md) - [Licenses](./licenses.md) +- [Editions](guides/editions.md) # High-level Compiler Architecture @@ -123,6 +124,7 @@ - [Lowering to logic](./traits/lowering-to-logic.md) - [Goals and clauses](./traits/goals-and-clauses.md) - [Canonical queries](./traits/canonical-queries.md) + - [Canonicalization](./traits/canonicalization.md) - [Next-gen trait solving](./solve/trait-solving.md) - [Invariants of the type system](./solve/invariants.md) - [The solver](./solve/the-solver.md) @@ -130,6 +132,7 @@ - [Coinduction](./solve/coinduction.md) - [Proof trees](./solve/proof-trees.md) - [Normalization](./solve/normalization.md) + - [`Unsize` and `CoerceUnsized` traits](./traits/unsize.md) - [Type checking](./type-checking.md) - [Method Lookup](./method-lookup.md) - [Variance](./variance.md) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping.md b/src/doc/rustc-dev-guide/src/building/bootstrapping.md index 936c75f36..1f66f08f3 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping.md @@ -29,7 +29,7 @@ Note that this documentation mostly covers user-facing information. See - Stage 2: the truly current compiler - Stage 3: the same-result test -Compiling `rustc` is done in stages. Here's a diagram, adapted from Joshua Nelson's +Compiling `rustc` is done in stages. Here's a diagram, adapted from Jynn Nelson's [talk on bootstrapping][rustconf22-talk] at RustConf 2022, with detailed explanations below. The `A`, `B`, `C`, and `D` show the ordering of the stages of bootstrapping. 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 1012e94fd..253a94956 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 @@ -293,7 +293,7 @@ For example, if your host platform is `x86_64-unknown-linux-gnu` and your cross-compilation target is `wasm32-wasi`, you can build with: ```bash -./x build --target x86_64-unknown-linux-gnu --target wasm32-wasi +./x build --target x86_64-unknown-linux-gnu,wasm32-wasi ``` Note that if you want the resulting compiler to be able to build crates that diff --git a/src/doc/rustc-dev-guide/src/compiler-team.md b/src/doc/rustc-dev-guide/src/compiler-team.md index d5ba78c77..9922ee7dd 100644 --- a/src/doc/rustc-dev-guide/src/compiler-team.md +++ b/src/doc/rustc-dev-guide/src/compiler-team.md @@ -17,15 +17,15 @@ Currently the compiler team chats in Zulip: with rustc development, or [`t-compiler/meetings`][zulip-meetings], where the team holds their weekly triage and steering meetings. -## Expert map +## Reviewers If you're interested in figuring out who can answer questions about a particular part of the compiler, or you'd just like to know who works on what, -check out our [experts directory][experts]. +check out [triagebot.toml's assign section][map]. It contains a listing of the various parts of the compiler and a list of people -who are experts on each one. +who are reviewers of each part. -[experts]: https://github.com/rust-lang/compiler-team/blob/master/content/experts/map.toml +[map]: https://github.com/rust-lang/rust/blob/master/triagebot.toml ## Rust compiler meeting diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index 9f4245f28..f21bae40f 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -523,7 +523,7 @@ are: - Early lint pass: Works on [AST nodes] after [macro expansion] and name resolution, just before [HIR lowering]. These lints are for purely syntactical lints. - - Example: The [`unsued_parens`] lint checks for parenthesized-expressions + - Example: The [`unused_parens`] lint checks for parenthesized-expressions in situations where they are not needed, like an `if` condition. - Late lint pass: Works on [HIR nodes], towards the end of [analysis] (after @@ -558,7 +558,7 @@ compiler](#linting-early-in-the-compiler). [macro expansion]: macro-expansion.md [analysis]: part-4-intro.md [`keyword_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#keyword-idents -[`unsued_parens`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unused-parens +[`unused_parens`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unused-parens [`invalid_value`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#invalid-value [`arithmetic_overflow`]: https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#arithmetic-overflow [`unused_mut`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unused-mut @@ -572,7 +572,6 @@ generally based on how they are registered. - *Built-in* lints are defined inside the compiler source. - *Driver-registered* lints are registered when the compiler driver is created by an external driver. This is the mechanism used by Clippy, for example. -- *Plugin* lints are registered by the [deprecated plugin system]. - *Tool* lints are lints with a path prefix like `clippy::` or `rustdoc::`. - *Internal* lints are the `rustc::` scoped tool lints that only run on the rustc source tree itself and are defined in the compiler source like a @@ -581,7 +580,6 @@ generally based on how they are registered. More information about lint registration can be found in the [LintStore] chapter. -[deprecated plugin system]: https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html [LintStore]: diagnostics/lintstore.md ### Declaring a lint @@ -691,6 +689,8 @@ declare_lint! { This makes the `ANONYMOUS_PARAMETERS` lint allow-by-default in the 2015 edition but warn-by-default in the 2018 edition. +See [Edition-specific lints](../guides/editions.md#edition-specific-lints) for more information. + ### Feature-gated lints Lints belonging to a feature should only be usable if the feature is enabled in the @@ -722,6 +722,7 @@ meaning that rustc exclusively exposes to users as "future incompatible". 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. +See [migration lints](guides/editions.md#migration-lints) for more details. A future-incompatible lint should be declared with the `@future_incompatible` additional "field": diff --git a/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md b/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md index 603c9ed65..54dd841ad 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md @@ -4,9 +4,8 @@ This page documents some of the machinery around lint registration and how we run lints in the compiler. The [`LintStore`] is the central piece of infrastructure, around which -everything rotates. It's not available during the early parts of compilation -(i.e., before TyCtxt) in most code, as we need to fill it in with all of the -lints, which can only happen after plugin registration. +everything rotates. The `LintStore` is held as part of the [`Session`], and it +gets populated with the list of lints shortly after the `Session` is created. ## Lints vs. lint passes @@ -39,16 +38,15 @@ lints are emitted as part of other work (e.g., type checking, etc.). ### High-level overview -In [`rustc_interface::register_plugins`], +In [`rustc_interface::run_compiler`], the [`LintStore`] is created, and all lints are registered. -There are four 'sources' of lints: +There are three 'sources' of lints: * internal lints: lints only used by the rustc codebase * builtin lints: lints built into the compiler and not provided by some outside source -* plugin lints: lints created by plugins through the plugin system. * `rustc_interface::Config`[`register_lints`]: lints passed into the compiler during construction @@ -56,8 +54,7 @@ Lints are registered via the [`LintStore::register_lint`] function. This should happen just once for any lint, or an ICE will occur. Once the registration is complete, we "freeze" the lint store by placing it in -an `Lrc`. Later in the driver, it's passed into the `GlobalCtxt` constructor -where it lives in an immutable form from then on. +an `Lrc`. Lint passes are registered separately into one of the categories (pre-expansion, early, late, late module). Passes are registered as a closure @@ -68,8 +65,8 @@ they can keep track of state internally. #### Internal lints -These are lints used just by the compiler or plugins like `clippy`. They can be -found in `rustc_lint::internal`. +These are lints used just by the compiler or drivers like `clippy`. They can be +found in [`rustc_lint::internal`]. An example of such a lint is the check that lint passes are implemented using the `declare_lint_pass!` macro and not by hand. This is accomplished with the @@ -92,18 +89,6 @@ the [`rustc_lint::register_builtins`] function. Just like with internal lints, this happens inside of [`rustc_lint::new_lint_store`]. -#### Plugin lints - -This is one of the primary use cases remaining for plugins/drivers. Plugins are -given access to the mutable `LintStore` during registration (which happens -inside of [`rustc_interface::register_plugins`]) and they can call any -functions they need on the `LintStore`, just like rustc code. - -Plugins are intended to declare lints with the `plugin` field set to true -(e.g., by way of the [`declare_tool_lint!`] macro), but this is purely for -diagnostics and help text; otherwise plugin lints are mostly just as first -class as rustc builtin lints. - #### Driver lints These are the lints provided by drivers via the `rustc_interface::Config` @@ -127,7 +112,6 @@ approach, it is beneficial to do so for performance reasons. [`LintStore`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html [`LintStore::register_lint`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LintStore.html#method.register_lints -[`rustc_interface::register_plugins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.register_plugins.html [`rustc_lint::register_builtins`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_builtins.html [`rustc_lint::register_internals`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.register_internals.html [`rustc_lint::new_lint_store`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/fn.new_lint_store.html @@ -135,3 +119,6 @@ approach, it is beneficial to do so for performance reasons. [`declare_tool_lint!`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/macro.declare_tool_lint.html [`register_lints`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Config.html#structfield.register_lints [`&rustc_lint_defs::Lint`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/struct.Lint.html +[`Session`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html +[`rustc_interface::run_compiler`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html#reexport.run_compiler +[`rustc_lint::internal`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/internal/index.html diff --git a/src/doc/rustc-dev-guide/src/feature-gates.md b/src/doc/rustc-dev-guide/src/feature-gates.md index 788f93d66..24ce9bb71 100644 --- a/src/doc/rustc-dev-guide/src/feature-gates.md +++ b/src/doc/rustc-dev-guide/src/feature-gates.md @@ -25,7 +25,7 @@ To remove a feature gate, follow these steps: ```rust,ignore /// description of feature - (unstable, $feature_name, "$version", Some($tracking_issue_number), $edition) + (unstable, $feature_name, "$version", Some($tracking_issue_number)) ``` 2. Add a modified version of the feature gate declaration that you just @@ -33,7 +33,7 @@ To remove a feature gate, follow these steps: ```rust,ignore /// description of feature - (removed, $old_feature_name, "$version", Some($tracking_issue_number), $edition, + (removed, $old_feature_name, "$version", Some($tracking_issue_number), Some("$why_it_was_removed")) ``` @@ -50,7 +50,7 @@ to follow when [removing a feature gate][removing]): ```rust,ignore /// description of feature - (unstable, $old_feature_name, "$version", Some($tracking_issue_number), $edition) + (unstable, $old_feature_name, "$version", Some($tracking_issue_number)) ``` 2. Add a modified version of the old feature gate declaration that you just @@ -59,7 +59,7 @@ to follow when [removing a feature gate][removing]): ```rust,ignore /// description of feature /// Renamed to `$new_feature_name` - (removed, $old_feature_name, "$version", Some($tracking_issue_number), $edition, + (removed, $old_feature_name, "$version", Some($tracking_issue_number), Some("renamed to `$new_feature_name`")) ``` @@ -69,7 +69,7 @@ to follow when [removing a feature gate][removing]): ```rust,ignore /// description of feature - (unstable, $new_feature_name, "$version", Some($tracking_issue_number), $edition) + (unstable, $new_feature_name, "$version", Some($tracking_issue_number)) ``` diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index a12cb068c..ef54a3009 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -47,12 +47,11 @@ guide :) ### Experts -Not all `t-compiler` members are experts on all parts of `rustc`; it's a pretty -large project. To find out who has expertise on different parts of the -compiler, [consult this "experts map"][map]. - -It's not perfectly complete, though, so please also feel free to ask questions -even if you can't figure out who to ping. +Not all `t-compiler` members are experts on all parts of `rustc`; it's a +pretty large project. To find out who could have some expertise on +different parts of the compiler, [consult traigebot assign groups][map]. +The sections that start with `[assign*` in `triagebot.toml` file. +But also, feel free to ask questions even if you can't figure out who to ping. Another way to find experts for a given part of the compiler is to see who has made recent commits. For example, to find people who have recently worked on name resolution since the 1.68.2 release, @@ -60,7 +59,7 @@ you could run `git shortlog -n 1.68.2.. compiler/rustc_resolve/`. Ignore any com "Rollup merge" or commits by `@bors` (see [CI contribution procedures](./contributing.md#ci) for more information about these commits). -[map]: https://github.com/rust-lang/compiler-team/blob/master/content/experts/map.toml +[map]: https://github.com/rust-lang/rust/blob/master/triagebot.toml ### Etiquette @@ -165,7 +164,6 @@ incredibly helpful: [users]: https://users.rust-lang.org/ [so]: http://stackoverflow.com/questions/tagged/rust [community-library]: https://github.com/rust-lang/rfcs/labels/A-community-library - [iceb]: ./notification-groups/cleanup-crew.md [wd]: ./contributing.md#writing-documentation [wg]: https://rust-lang.github.io/compiler-team/working-groups/ diff --git a/src/doc/rustc-dev-guide/src/guides/editions.md b/src/doc/rustc-dev-guide/src/guides/editions.md new file mode 100644 index 000000000..336e391df --- /dev/null +++ b/src/doc/rustc-dev-guide/src/guides/editions.md @@ -0,0 +1,336 @@ +# Editions + +<!-- toc --> + +This chapter gives an overview of how Edition support works in rustc. +This assumes that you are familiar with what Editions are (see the [Edition Guide]). + +[Edition Guide]: https://doc.rust-lang.org/edition-guide/ + +## Edition definition + +The `--edition` CLI flag specifies the edition to use for a crate. +This can be accessed from [`Session::edition`]. +There are convenience functions like [`Session::at_least_rust_2021`] for checking the crate's +edition, though you should be careful about whether you check the global session or the span, see +[Edition hygiene] below. + +As an alternative to the `at_least_rust_20xx` convenience methods, the [`Edition`] type also +supports comparisons for doing range checks, such as `span.edition() >= Edition::Edition2021`. + +[`Session::edition`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html#method.edition +[`Session::at_least_rust_2021`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html#method.at_least_rust_2021 +[`Edition`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/edition/enum.Edition.html + +### Adding a new edition + +Adding a new edition mainly involves adding a variant to the [`Edition`] enum and then fixing +everything that is broken. See [#94461](https://github.com/rust-lang/rust/pull/94461) for an +example. + +### Features and Edition stability + +The [`Edition`] enum defines whether or not an edition is stable. +If it is not stable, then the `-Zunstable-options` CLI option must be passed to enable it. + +When adding a new feature, there are two options you can choose for how to handle stability with a +future edition: + +- Just check the edition of the span like `span.at_least_rust_20xx()` (see [Edition hygiene]) or the + [`Session::edition`]. This will implicitly depend on the stability of the edition itself to + indicate that your feature is available. +- Place your new behavior behind a [feature gate]. + +It may be sufficient to only check the current edition for relatively simple changes. +However, for larger language changes, you should consider creating a feature gate. +There are several benefits to using a feature gate: + +- A feature gate makes it easier to work on and experiment with a new feature. +- It makes the intent clear when the `#![feature(…)]` attribute is used that your new feature is + being enabled. +- It makes testing of editions easier so that features that are not yet complete do not interfere + with testing of edition-specific features that are complete and ready. +- It decouples the feature from an edition, which makes it easier for the team to make a deliberate + decision of whether or not a feature should be added to the next edition when the feature is + ready. + +When a feature is complete and ready, the feature gate can be removed (and the code should just +check the span or `Session` edition to determine if it is enabled). + +There are a few different options for doing feature checks: + +- For highly experimental features, that may or may not be involved in an edition, they can + implement regular feature gates like `tcx.features().my_feature`, and ignore editions for the time + being. + +- For experimental features that *might* be involved in an edition, they should implement gates with + `tcx.features().my_feature && span.at_least_rust_20xx()`. + This requires the user to still specify `#![feature(my_feature)]`, to avoid disrupting testing of + other edition features which are ready and have been accepted within the edition. + +- For experimental features that have graduated to definitely be part of an edition, + they should implement gates with `tcx.features().my_feature || span.at_least_rust_20xx()`, + or just remove the feature check altogether and just check `span.at_least_rust_20xx()`. + +If you need to do the feature gating in multiple places, consider placing the check in a single +function so that there will only be a single place to update. For example: + +```rust,ignore +// An example from Edition 2021 disjoint closure captures. + +fn enable_precise_capture(tcx: TyCtxt<'_>, span: Span) -> bool { + tcx.features().capture_disjoint_fields || span.rust_2021() +} +``` + +See [Lints and stability](#lints-and-stability) below for more information about how lints handle +stability. + +[feature gate]: ../feature-gates.md + +## Edition parsing + +For the most part, the lexer is edition-agnostic. +Within [`StringReader`], tokens can be modified based on edition-specific behavior. +For example, C-String literals like `c"foo"` are split into multiple tokens in editions before 2021. +This is also where things like reserved prefixes are handled for the 2021 edition. + +Edition-specific parsing is relatively rare. One example is `async fn` which checks the span of the +token to determine if it is the 2015 edition, and emits an error in that case. +This can only be done if the syntax was already invalid. + +If you need to do edition checking in the parser, you will normally want to look at the edition of +the token, see [Edition hygiene]. +In some rare cases you may instead need to check the global edition from [`ParseSess::edition`]. + +Most edition-specific parsing behavior is handled with [migration lints] instead of in the parser. +This is appropriate when there is a *change* in syntax (as opposed to new syntax). +This allows the old syntax to continue to work on previous editions. +The lint then checks for the change in behavior. +On older editions, the lint pass should emit the migration lint to help with migrating to new +editions. +On newer editions, your code should emit a hard error with `emit_err` instead. +For example, the deprecated `start...end` pattern syntax emits the +[`ellipsis_inclusive_range_patterns`] lint on editions before 2021, and in 2021 is an hard error via +the `emit_err` method. + +[`StringReader`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/lexer/struct.StringReader.html +[`ParseSess::edition`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/parse/struct.ParseSess.html#structfield.edition +[`ellipsis_inclusive_range_patterns`]: https://doc.rust-lang.org/nightly/rustc/lints/listing/warn-by-default.html#ellipsis-inclusive-range-patterns + +### Keywords + +New keywords can be introduced across an edition boundary. +This is implemented by functions like [`Symbol::is_used_keyword_conditional`], which rely on the +ordering of how the keywords are defined. + +When new keywords are introduced, the [`keyword_idents`] lint should be updated so that automatic +migrations can transition code that might be using the keyword as an identifier (see +[`KeywordIdents`]). +An alternative to consider is to implement the keyword as a weak keyword if the position it is used +is sufficient to distinguish it. + +An additional option to consider is the `k#` prefix which was introduced in [RFC 3101]. +This allows the use of a keyword in editions *before* the edition where the keyword is introduced. +This is currently not implemented. + +[`Symbol::is_used_keyword_conditional`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html#method.is_used_keyword_conditional +[`keyword_idents`]: https://doc.rust-lang.org/nightly/rustc/lints/listing/allowed-by-default.html#keyword-idents +[`KeywordIdents`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/builtin/struct.KeywordIdents.html +[RFC 3101]: https://rust-lang.github.io/rfcs/3101-reserved_prefixes.html + +### Edition hygiene +[edition hygiene]: #edition-hygiene + +Spans are marked with the edition of the crate that the span came from. +See [Macro hygiene] in the Edition Guide for a user-centric description of what this means. + +You should normally use the edition from the token span instead of looking at the global `Session` +edition. +For example, use `span.edition().at_least_rust_2021()` instead of `sess.at_least_rust_2021()`. +This helps ensure that macros behave correctly when used across crates. + +[Macro hygiene]: https://doc.rust-lang.org/nightly/edition-guide/editions/advanced-migrations.html#macro-hygiene + +## Lints + +Lints support a few different options for interacting with editions. +Lints can be *future incompatible edition migration lints*, which are used to support +[migrations][migration lints] to newer editions. +Alternatively, lints can be [edition-specific](#edition-specific-lints), where they change their +default level starting in a specific edition. + +### Migration lints +[migration lints]: #migration-lints +[migration lint]: #migration-lints + +*Migration lints* are used to migrate projects from one edition to the next. +They are implemented with a `MachineApplicable` [suggestion](../diagnostics.md#suggestions) which +will rewrite code so that it will **successfully compile in both the previous and the next +edition**. +For example, the [`keyword_idents`] lint will take identifiers that conflict with a new keyword to +use the raw identifier syntax to avoid the conflict (for example changing `async` to `r#async`). + +Migration lints must be declared with the [`FutureIncompatibilityReason::EditionError`] or +[`FutureIncompatibilityReason::EditionSemanticsChange`] [future-incompatible +option](../diagnostics.md#future-incompatible-lints) in the lint declaration: + +```rust,ignore +declare_lint! { + pub KEYWORD_IDENTS, + Allow, + "detects edition keywords being used as an identifier", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018), + reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>", + }; +} +``` + +When declared like this, the lint is automatically added to the appropriate +`rust-20xx-compatibility` lint group. +When a user runs `cargo fix --edition`, cargo will pass the `--force-warn rust-20xx-compatibility` +flag to force all of these lints to appear during the edition migration. +Cargo also passes `--cap-lints=allow` so that no other lints interfere with the edition migration. + +Migration lints can be either `Allow` or `Warn` by default. +If it is `Allow`, users usually won't see this warning unless they are doing an edition migration +manually or there is a problem during the migration. +Most migration lints are `Allow`. + +If it is `Warn` by default, users on all editions will see this warning. +Only use `Warn` if you think it is important for everyone to be aware of the change, and to +encourage people to update their code on all editions. +Beware that new warn-by-default lint that hit many projects can be very disruptive and frustrating +for users. +You may consider switching an `Allow` to `Warn` several years after the edition stabilizes. +This will only show up for the relatively small number of stragglers who have not updated to the new +edition. + +[`keyword_idents`]: https://doc.rust-lang.org/nightly/rustc/lints/listing/allowed-by-default.html#keyword-idents +[`FutureIncompatibilityReason::EditionError`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/enum.FutureIncompatibilityReason.html#variant.EditionError +[`FutureIncompatibilityReason::EditionSemanticsChange`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/enum.FutureIncompatibilityReason.html#variant.EditionSemanticsChange + +### Edition-specific lints + +Lints can be marked so that they have a different level starting in a specific edition. +In the lint declaration, use the `@edition` marker: + +```rust,ignore +declare_lint! { + pub SOME_LINT_NAME, + Allow, + "my lint description", + @edition Edition2024 => Warn; +} +``` + +Here, `SOME_LINT_NAME` defaults to `Allow` on all editions before 2024, and then becomes `Warn` +afterwards. + +This should generally be used sparingly, as there are other options: + +- Small impact stylistic changes unrelated to an edition can just make the lint `Warn` on all + editions. If you want people to adopt a different way to write things, then go ahead and commit to + having it show up for all projects. + + Beware that if a new warn-by-default lint hits many projects, it can be very disruptive and + frustrating for users. + +- Change the new style to be a hard error in the new edition, and use a [migration lint] to + automatically convert projects to the new style. For example, + [`ellipsis_inclusive_range_patterns`] is a hard error in 2021, and warns in all previous editions. + + Beware that these cannot be added after the edition stabilizes. + +- Migration lints can also change over time. + For example, the migration lint can start out as `Allow` by default. + For people performing the migration, they will automatically get updated to the new code. + Then, after some years, the lint can be made to `Warn` in previous editions. + + For example [`anonymous_parameters`] was a 2018 Edition migration lint (and a hard-error in 2018) + that was `Allow` by default in previous editions. + Then, three years later, it was changed to `Warn` for all previous editions, so that all users got + a warning that the style was being phased out. + If this was a warning from the start, it would have impacted many projects and be very disruptive. + By making it part of the edition, most users eventually updated to the new edition and were + handled by the migration. + Switching to `Warn` only impacted a few stragglers who did not update. + +[`ellipsis_inclusive_range_patterns`]: https://doc.rust-lang.org/nightly/rustc/lints/listing/warn-by-default.html#ellipsis-inclusive-range-patterns +[`anonymous_parameters`]: https://doc.rust-lang.org/nightly/rustc/lints/listing/warn-by-default.html#anonymous-parameters + +### Lints and stability + +Lints can be marked as being unstable, which can be helpful when developing a new edition feature, +and you want to test out a migration lint. +The feature gate can be specified in the lint's declaration like this: + +```rust,ignore +declare_lint! { + pub SOME_LINT_NAME, + Allow, + "my cool lint", + @feature_gate = sym::my_feature_name; +} +``` + +Then, the lint will only fire if the user has the appropriate `#![feature(my_feature_name)]`. +Just beware that when it comes time to do crater runs testing the migration that the feature gate +will need to be removed. + +Alternatively, you can implement an allow-by-default [migration lint] for an upcoming unstable +edition without a feature gate. +Although users may technically be able to enable the lint before the edition is stabilized, most +will not notice the new lint exists, and it should not disrupt anything or cause any breakage. + +### Idiom lints + +In the 2018 edition, there was a concept of "idiom lints" under the `rust-2018-idioms` lint group. +The concept was to have new idiomatic styles under a different lint group separate from the forced +migrations under the `rust-2018-compatibility` lint group, giving some flexibility as to how people +opt-in to certain edition changes. + +Overall this approach did not seem to work very well, +and it is unlikely that we will use the idiom groups in the future. + +## Standard library changes + +### Preludes + +Each edition comes with a specific prelude of the standard library. +These are implemented as regular modules in [`core::prelude`] and [`std::prelude`]. +New items can be added to the prelude, just beware that this can conflict with user's pre-existing +code. +Usually a [migration lint] should be used to migrate existing code to avoid the conflict. +For example, [`rust_2021_prelude_collisions`] is used to handle the collisions with the new traits +in 2021. + +[`core::prelude`]: https://doc.rust-lang.org/core/prelude/index.html +[`std::prelude`]: https://doc.rust-lang.org/std/prelude/index.html +[`rust_2021_prelude_collisions`]: https://doc.rust-lang.org/nightly/rustc/lints/listing/allowed-by-default.html#rust-2021-prelude-collisions + +### Customized language behavior + +Usually it is not possible to make breaking changes to the standard library. +In some rare cases, the teams may decide that the behavior change is important enough to break this +rule. +The downside is that this requires special handling in the compiler to be able to distinguish when +the old and new signatures or behaviors should be used. + +One example is the change in method resolution for [`into_iter()` of arrays][into-iter]. +This was implemented with the `#[rustc_skip_array_during_method_dispatch]` attribute on the +`IntoIterator` trait which then tells the compiler to consider an alternate trait resolution choice +based on the edition. + +Another example is the [`panic!` macro changes][panic-macro]. +This required defining multiple panic macros, and having the built-in panic macro implementation +determine the appropriate way to expand it. +This also included the [`non_fmt_panics`] [migration lint] to adjust old code to the new form, which +required the `rustc_diagnostic_item` attribute to detect the usage of the panic macro. + +In general it is recommended to avoid these special cases except for very high value situations. + +[into-iter]: https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html +[panic-macro]: https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html +[`non_fmt_panics`]: https://doc.rust-lang.org/nightly/rustc/lints/listing/warn-by-default.html#non-fmt-panics 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 427589dab..0140c09bb 100644 --- a/src/doc/rustc-dev-guide/src/implementing_new_features.md +++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md @@ -128,10 +128,10 @@ a new unstable feature: ```rust ignore /// description of feature - (unstable, $feature_name, "CURRENT_RUSTC_VERSION", Some($tracking_issue_number), $edition) + (unstable, $feature_name, "CURRENT_RUSTC_VERSION", Some($tracking_issue_number)) ``` - where `$edition` has the type `Option<Edition>`, and is typically just `None`. If you haven't yet + If you haven't yet opened a tracking issue (e.g. because you want initial feedback on whether the feature is likely to be accepted), you can temporarily use `None` - but make sure to update it before the PR is merged! 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 fd215e3e9..a21254946 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -273,20 +273,22 @@ since it will not be called), and adds a new `FunctionCoverage`, with ## Testing LLVM Coverage -[(See also the compiletest documentation for the `tests/coverage-map` and -`tests/run-coverage` test suites.)](./tests/compiletest.md#coverage-tests) +[(See also the compiletest documentation for the `tests/coverage` +test suite.)](./tests/compiletest.md#coverage-tests) Coverage instrumentation in the MIR is validated by a `mir-opt` test: [`tests/mir-opt/instrument_coverage.rs`]. -Coverage instrumentation in LLVM IR is validated by the [`tests/coverage-map`] -test suite. These tests compile a test program to LLVM IR assembly, and then +Coverage instrumentation in LLVM IR is validated by the [`tests/coverage`] +test suite in `coverage-map` mode. +These tests compile a test program to LLVM IR assembly, and then use the [`src/tools/coverage-dump`] tool to extract and pretty-print the coverage mappings that would be embedded in the final binary. End-to-end testing of coverage instrumentation and coverage reporting is -performed by the [`tests/run-coverage`] and [`tests/run-coverage-rustdoc`] -test suites. These tests compile and run a test program with coverage +performed by the [`tests/coverage`] test suite in `coverage-run` mode, +and by the [`tests/coverage-run-rustdoc`] test suite. +These tests compile and run a test program with coverage instrumentation, then use LLVM tools to convert the coverage data into a human-readable coverage report. @@ -296,19 +298,19 @@ expected LLVM IR instructions and structured data for a coverage-enabled program, including various checks for Coverage Map-related metadata and the LLVM intrinsic calls to increment the runtime counters. -Expected results for the `coverage-map`, `run-coverage`, `run-coverage-rustdoc`, +Expected results for the `coverage`, `coverage-run-rustdoc`, and `mir-opt` tests can be refreshed by running: ```shell -./x test tests/*coverage* --bless +./x test coverage --bless +./x test coverage-run-rustdoc --bless ./x test tests/mir-opt --bless ``` [`tests/mir-opt/instrument_coverage.rs`]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/instrument_coverage.rs -[`tests/coverage-map`]: https://github.com/rust-lang/rust/tree/master/tests/coverage-map +[`tests/coverage`]: https://github.com/rust-lang/rust/tree/master/tests/coverage [`src/tools/coverage-dump`]: https://github.com/rust-lang/rust/tree/master/src/tools/coverage-dump -[`tests/run-coverage`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage -[`tests/run-coverage-rustdoc`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage-rustdoc +[`tests/coverage-run-rustdoc`]: https://github.com/rust-lang/rust/tree/master/tests/coverage-run-rustdoc [`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/notification-groups/arm.md b/src/doc/rustc-dev-guide/src/notification-groups/arm.md index 4514f8ef3..3abc32c68 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/arm.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/arm.md @@ -1,6 +1,7 @@ # ARM notification group -**Github Label:** [O-ARM] +**Github Label:** [O-ARM] <br> +**Ping command:** `@rustbot ping arm` [O-ARM]: https://github.com/rust-lang/rust/labels/O-ARM diff --git a/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md b/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md index 707334304..9cf4e512c 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md @@ -1,6 +1,7 @@ # Cleanup Crew -**Github Label:** [ICEBreaker-Cleanup-Crew] +**Github Label:** [ICEBreaker-Cleanup-Crew] <br> +**Ping command:** `@rustbot ping cleanup-crew` [ICEBreaker-Cleanup-Crew]: https://github.com/rust-lang/rust/labels/ICEBreaker-Cleanup-Crew diff --git a/src/doc/rustc-dev-guide/src/notification-groups/llvm.md b/src/doc/rustc-dev-guide/src/notification-groups/llvm.md index 69edd8b54..2eff63713 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/llvm.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/llvm.md @@ -1,6 +1,7 @@ # LLVM Notification group -**Github Label:** [A-LLVM] +**Github Label:** [A-LLVM] <br> +**Ping command:** `@rustbot ping llvm` [A-LLVM]: https://github.com/rust-lang/rust/labels/A-LLVM diff --git a/src/doc/rustc-dev-guide/src/notification-groups/risc-v.md b/src/doc/rustc-dev-guide/src/notification-groups/risc-v.md index 15ce1cfc6..1b31297b6 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/risc-v.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/risc-v.md @@ -1,6 +1,7 @@ # RISC-V notification group -**Github Label:** [O-riscv] +**Github Label:** [O-riscv] <br> +**Ping command:** `@rustbot ping risc-v` [O-riscv]: https://github.com/rust-lang/rust/labels/O-riscv diff --git a/src/doc/rustc-dev-guide/src/notification-groups/windows.md b/src/doc/rustc-dev-guide/src/notification-groups/windows.md index 0483babd8..e615a2cbd 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/windows.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/windows.md @@ -1,6 +1,7 @@ # Windows notification group -**Github Label:** [O-Windows] +**Github Label:** [O-Windows] <br> +**Ping command:** `@rustbot ping windows` [O-Windows]: https://github.com/rust-lang/rust/labels/O-Windows diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 5cacb3013..7b6ed435d 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -67,11 +67,8 @@ The following test suites are available, with links for more information: - `run-make-fulldeps` — `run-make` tests which require a linkable build of `rustc`, or the rust demangler - [`run-pass-valgrind`](#valgrind-tests) — tests run with Valgrind -- [`coverage-map`](#coverage-tests) - tests for coverage maps produced by - coverage instrumentation -- [`run-coverage`](#coverage-tests) - tests that run an instrumented program - and check its coverage report -- [`run-coverage-rustdoc`](#coverage-tests) - coverage tests that also run +- [`coverage`](#coverage-tests) - tests for coverage instrumentation +- [`coverage-run-rustdoc`](#coverage-tests) - coverage tests that also run instrumented doctests - [Rustdoc tests](../rustdoc.md#tests): - `rustdoc` — tests for rustdoc, making sure that the generated files @@ -402,7 +399,28 @@ These may be removed in the future. ### Coverage tests -The tests in [`tests/coverage-map`] test the mappings between source code +The tests in [`tests/coverage`] are shared by multiple test modes that test +coverage instrumentation in different ways. +Running the `coverage` test suite will automatically run each test in all of +the different coverage modes. + +Each mode also has an alias to run the coverage tests in just that mode: + +```bash +./x test coverage # runs all of tests/coverage in all coverage modes +./x test tests/coverage # same as above + +./x test tests/coverage/if.rs # runs the specified test in all coverage modes + +./x test coverage-map # runs all of tests/coverage in "coverage-map" mode only +./x test coverage-run # runs all of tests/coverage in "coverage-run" mode only + +./x test coverage-map -- tests/coverage/if.rs # runs the specified test in "coverage-map" mode only +``` + +--- + +In `coverage-map` mode, these tests verify the mappings between source code regions and coverage counters that are emitted by LLVM. They compile the test with `--emit=llvm-ir`, then use a custom tool ([`src/tools/coverage-dump`]) @@ -416,18 +434,18 @@ coverage reports. As a rule of thumb, any PR that doesn't change coverage-specific code should **feel free to re-bless** the `coverage-map` tests as necessary, -without worrying about the actual changes, as long as the `run-coverage` tests +without worrying about the actual changes, as long as the `coverage-run` tests still pass. --- -The tests in [`tests/run-coverage`] perform an end-to-end test of coverage reporting. +In `coverage-run` mode, these tests perform an end-to-end test of coverage reporting. They compile a test program with coverage instrumentation, run that program to produce raw coverage data, and then use LLVM tools to process that data into a human-readable code coverage report. Instrumented binaries need to be linked against the LLVM profiler runtime, -so `run-coverage` tests are **automatically skipped** +so `coverage-run` tests are **automatically skipped** unless the profiler runtime is enabled in `config.toml`: ```toml @@ -439,14 +457,15 @@ profiler = true This also means that they typically don't run in PR CI jobs, though they do run as part of the full set of CI jobs used for merging. -The tests in [`tests/run-coverage-rustdoc`] also run instrumented doctests and +--- + +The tests in [`tests/coverage-run-rustdoc`] also run instrumented doctests and include them in the coverage report. This avoids having to build rustdoc when -only running the main `run-coverage` suite. +only running the main `coverage` suite. -[`tests/coverage-map`]: https://github.com/rust-lang/rust/tree/master/tests/coverage-map +[`tests/coverage`]: https://github.com/rust-lang/rust/tree/master/tests/coverage [`src/tools/coverage-dump`]: https://github.com/rust-lang/rust/tree/master/src/tools/coverage-dump -[`tests/run-coverage`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage -[`tests/run-coverage-rustdoc`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage-rustdoc +[`tests/coverage-run-rustdoc`]: https://github.com/rust-lang/rust/tree/master/tests/coverage-run-rustdoc ## Building auxiliary crates diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md index 71fb82b68..7c68dd03f 100644 --- a/src/doc/rustc-dev-guide/src/tests/running.md +++ b/src/doc/rustc-dev-guide/src/tests/running.md @@ -320,3 +320,36 @@ communicate with the server to coordinate running tests (see [remote-test-server]: https://github.com/rust-lang/rust/tree/master/src/tools/remote-test-server [src/bootstrap/test.rs]: https://github.com/rust-lang/rust/tree/master/src/bootstrap/test.rs +## Running rustc_codegen_gcc tests + +First thing to know is that it only supports linux x86_64 at the moment. We will +extend its support later on. + +You need to update `codegen-backends` value in your `config.toml` file in the +`[rust]` section and add "gcc" in the array: + +```toml +codegen-backends = ["llvm", "gcc"] +``` + +Then you need to install libgccjit 12. For example with `apt`: + +```bash +$ apt install libgccjit-12-dev +``` + +Now you can run the following command: + +```bash +$ ./x.py test compiler/rustc_codegen_gcc/ +``` + +If it cannot find the `.so` library (if you installed it with `apt` for example), you +need to pass the library file path with `LIBRARY_PATH`: + +```bash +$ LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12/ ./x.py test compiler/rustc_codegen_gcc/ +``` + +If you encounter bugs or problems, don't hesitate to open issues on +[rustc_codegen_gcc repository](github.com/rust-lang/rustc_codegen_gcc/). diff --git a/src/doc/rustc-dev-guide/src/traits/canonicalization.md b/src/doc/rustc-dev-guide/src/traits/canonicalization.md new file mode 100644 index 000000000..4c7575f62 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/traits/canonicalization.md @@ -0,0 +1,260 @@ +# Canonicalization + +> **NOTE**: FIXME: The content of this chapter has some overlap with +> [Next-gen trait solving Canonicalization chapter](../solve/canonicalization.html). +> It is suggested to reorganize these contents in the future. + +Canonicalization is the process of **isolating** an inference value +from its context. It is a key part of implementing +[canonical queries][cq], and you may wish to read the parent chapter +to get more context. + +Canonicalization is really based on a very simple concept: every +[inference variable](../type-inference.html#vars) is always in one of +two states: either it is **unbound**, in which case we don't know yet +what type it is, or it is **bound**, in which case we do. So to +isolate some data-structure T that contains types/regions from its +environment, we just walk down and find the unbound variables that +appear in T; those variables get replaced with "canonical variables", +starting from zero and numbered in a fixed order (left to right, for +the most part, but really it doesn't matter as long as it is +consistent). + +[cq]: ./canonical-queries.html + +So, for example, if we have the type `X = (?T, ?U)`, where `?T` and +`?U` are distinct, unbound inference variables, then the canonical +form of `X` would be `(?0, ?1)`, where `?0` and `?1` represent these +**canonical placeholders**. Note that the type `Y = (?U, ?T)` also +canonicalizes to `(?0, ?1)`. But the type `Z = (?T, ?T)` would +canonicalize to `(?0, ?0)` (as would `(?U, ?U)`). In other words, the +exact identity of the inference variables is not important – unless +they are repeated. + +We use this to improve caching as well as to detect cycles and other +things during trait resolution. Roughly speaking, the idea is that if +two trait queries have the same canonical form, then they will get +the same answer. That answer will be expressed in terms of the +canonical variables (`?0`, `?1`), which we can then map back to the +original variables (`?T`, `?U`). + +## Canonicalizing the query + +To see how it works, imagine that we are asking to solve the following +trait query: `?A: Foo<'static, ?B>`, where `?A` and `?B` are unbound. +This query contains two unbound variables, but it also contains the +lifetime `'static`. The trait system generally ignores all lifetimes +and treats them equally, so when canonicalizing, we will *also* +replace any [free lifetime](../appendix/background.html#free-vs-bound) with a +canonical variable (Note that `'static` is actually a _free_ lifetime +variable here. We are not considering it in the typing context of the whole +program but only in the context of this trait reference. Mathematically, we +are not quantifying over the whole program, but only this obligation). +Therefore, we get the following result: + +```text +?0: Foo<'?1, ?2> +``` + +Sometimes we write this differently, like so: + +```text +for<T,L,T> { ?0: Foo<'?1, ?2> } +``` + +This `for<>` gives some information about each of the canonical +variables within. In this case, each `T` indicates a type variable, +so `?0` and `?2` are types; the `L` indicates a lifetime variable, so +`?1` is a lifetime. The `canonicalize` method *also* gives back a +`CanonicalVarValues` array OV with the "original values" for each +canonicalized variable: + +```text +[?A, 'static, ?B] +``` + +We'll need this vector OV later, when we process the query response. + +## Executing the query + +Once we've constructed the canonical query, we can try to solve it. +To do so, we will wind up creating a fresh inference context and +**instantiating** the canonical query in that context. The idea is that +we create a substitution S from the canonical form containing a fresh +inference variable (of suitable kind) for each canonical variable. +So, for our example query: + +```text +for<T,L,T> { ?0: Foo<'?1, ?2> } +``` + +the substitution S might be: + +```text +S = [?A, '?B, ?C] +``` + +We can then replace the bound canonical variables (`?0`, etc) with +these inference variables, yielding the following fully instantiated +query: + +```text +?A: Foo<'?B, ?C> +``` + +Remember that substitution S though! We're going to need it later. + +OK, now that we have a fresh inference context and an instantiated +query, we can go ahead and try to solve it. The trait solver itself is +explained in more detail in [another section](./slg.html), but +suffice to say that it will compute a [certainty value][cqqr] (`Proven` or +`Ambiguous`) and have side-effects on the inference variables we've +created. For example, if there were only one impl of `Foo`, like so: + +[cqqr]: ./canonical-queries.html#query-response + +```rust,ignore +impl<'a, X> Foo<'a, X> for Vec<X> +where X: 'a +{ ... } +``` + +then we might wind up with a certainty value of `Proven`, as well as +creating fresh inference variables `'?D` and `?E` (to represent the +parameters on the impl) and unifying as follows: + +- `'?B = '?D` +- `?A = Vec<?E>` +- `?C = ?E` + +We would also accumulate the region constraint `?E: '?D`, due to the +where clause. + +In order to create our final query result, we have to "lift" these +values out of the query's inference context and into something that +can be reapplied in our original inference context. We do that by +**re-applying canonicalization**, but to the **query result**. + +## Canonicalizing the query result + +As discussed in [the parent section][cqqr], most trait queries wind up +with a result that brings together a "certainty value" `certainty`, a +result substitution `var_values`, and some region constraints. To +create this, we wind up re-using the substitution S that we created +when first instantiating our query. To refresh your memory, we had a query + +```text +for<T,L,T> { ?0: Foo<'?1, ?2> } +``` + +for which we made a substutition S: + +```text +S = [?A, '?B, ?C] +``` + +We then did some work which unified some of those variables with other things. +If we "refresh" S with the latest results, we get: + +```text +S = [Vec<?E>, '?D, ?E] +``` + +These are precisely the new values for the three input variables from +our original query. Note though that they include some new variables +(like `?E`). We can make those go away by canonicalizing again! We don't +just canonicalize S, though, we canonicalize the whole query response QR: + +```text +QR = { + certainty: Proven, // or whatever + var_values: [Vec<?E>, '?D, ?E] // this is S + region_constraints: [?E: '?D], // from the impl + value: (), // for our purposes, just (), but + // in some cases this might have + // a type or other info +} +``` + +The result would be as follows: + +```text +Canonical(QR) = for<T, L> { + certainty: Proven, + var_values: [Vec<?0>, '?1, ?0] + region_constraints: [?0: '?1], + value: (), +} +``` + +(One subtle point: when we canonicalize the query **result**, we do not +use any special treatment for free lifetimes. Note that both +references to `'?D`, for example, were converted into the same +canonical variable (`?1`). This is in contrast to the original query, +where we canonicalized every free lifetime into a fresh canonical +variable.) + +Now, this result must be reapplied in each context where needed. + +## Processing the canonicalized query result + +In the previous section we produced a canonical query result. We now have +to apply that result in our original context. If you recall, way back in the +beginning, we were trying to prove this query: + +```text +?A: Foo<'static, ?B> +``` + +We canonicalized that into this: + +```text +for<T,L,T> { ?0: Foo<'?1, ?2> } +``` + +and now we got back a canonical response: + +```text +for<T, L> { + certainty: Proven, + var_values: [Vec<?0>, '?1, ?0] + region_constraints: [?0: '?1], + value: (), +} +``` + +We now want to apply that response to our context. Conceptually, how +we do that is to (a) instantiate each of the canonical variables in +the result with a fresh inference variable, (b) unify the values in +the result with the original values, and then (c) record the region +constraints for later. Doing step (a) would yield a result of + +```text +{ + certainty: Proven, + var_values: [Vec<?C>, '?D, ?C] + ^^ ^^^ fresh inference variables + region_constraints: [?C: '?D], + value: (), +} +``` + +Step (b) would then unify: + +```text +?A with Vec<?C> +'static with '?D +?B with ?C +``` + +And finally the region constraint of `?C: 'static` would be recorded +for later verification. + +(What we *actually* do is a mildly optimized variant of that: Rather +than eagerly instantiating all of the canonical values in the result +with variables, we instead walk the vector of values, looking for +cases where the value is just a canonical variable. In our example, +`values[2]` is `?C`, so that means we can deduce that `?C := ?B` and +`'?D := 'static`. This gives us a partial set of values. Anything for +which we do not find a value, we create an inference variable.) + diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index 5e22f10e4..b8311b19a 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -181,7 +181,7 @@ gate is removed when the feature is stabilized. make your changes/improvements. When you open a PR on the [rust-lang/rust], a bot will assign your PR to a -review. If there is a particular Rust team member you are working with, you can +reviewer. If there is a particular Rust team member you are working with, you can request that reviewer by leaving a comment on the thread with `r? @reviewer-github-id` (e.g. `r? @eddyb`). If you don't know who to request, don't request anyone; the bot will assign someone automatically based on which files you changed. diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 1b27b77b3..fadd64a03 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -15,13 +15,17 @@ - [Platform Support](platform-support.md) - [Target Tier Policy](target-tier-policy.md) - [Template for Target-specific Documentation](platform-support/TEMPLATE.md) + - [arm64e-apple-ios.md](platform-support/arm64e-apple-ios.md) + - [arm64e-apple-darwin.md](platform-support/arm64e-apple-darwin.md) - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) - [\*-apple-tvos](platform-support/apple-tvos.md) - [\*-apple-watchos\*](platform-support/apple-watchos.md) - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md) - [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md) + - [arm-none-eabi](platform-support/arm-none-eabi.md) - [armv4t-none-eabi](platform-support/armv4t-none-eabi.md) - [armv5te-none-eabi](platform-support/armv5te-none-eabi.md) + - [armv7r-none-eabi](platform-support/armv7r-none-eabi.md) - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) - [armv7-sony-vita-newlibeabihf](platform-support/armv7-sony-vita-newlibeabihf.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) @@ -43,6 +47,7 @@ - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md) - [powerpc64-ibm-aix](platform-support/aix.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) + - [riscv32*-unknown-none-elf](platform-support/riscv32imac-unknown-none-elf.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) @@ -53,6 +58,7 @@ - [\*-unknown-uefi](platform-support/unknown-uefi.md) - [wasm32-wasi-preview1-threads](platform-support/wasm32-wasi-preview1-threads.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) + - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) - [x86_64h-apple-darwin](platform-support/x86_64h-apple-darwin.md) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index cfbe1e09c..4a4f1ae98 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -221,7 +221,7 @@ metrics. ## link-self-contained On `windows-gnu`, `linux-musl`, and `wasi` targets, this flag controls whether the -linker will use libraries and objects shipped with Rust instead or those in the system. +linker will use libraries and objects shipped with Rust instead of those in the system. It takes one of the following values: * no value: rustc will use heuristic to disable self-contained mode if system has necessary tools. @@ -249,9 +249,6 @@ flavor. Valid options are: * `gcc`: use the `cc` executable, which is typically gcc or clang on many systems. * `ld`: use the `ld` executable. * `msvc`: use the `link.exe` executable from Microsoft Visual Studio MSVC. -* `ptx`: use [`rust-ptx-linker`](https://github.com/denzp/rust-ptx-linker) - for Nvidia NVPTX GPGPU support. -* `bpf`: use [`bpf-linker`](https://github.com/alessandrod/bpf-linker) for eBPF support. * `wasm-ld`: use the [`wasm-ld`](https://lld.llvm.org/WebAssembly.html) executable, a port of LLVM `lld` for WebAssembly. * `ld64.lld`: use the LLVM `lld` executable with the [`-flavor darwin` diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md index 11d7b5b59..9daa08101 100644 --- a/src/doc/rustc/src/json.md +++ b/src/doc/rustc/src/json.md @@ -11,9 +11,11 @@ If parsing the output with Rust, the [`cargo_metadata`](https://crates.io/crates/cargo_metadata) crate provides some support for parsing the messages. -When parsing, care should be taken to be forwards-compatible with future changes -to the format. Optional values may be `null`. New fields may be added. Enumerated -fields like "level" or "suggestion_applicability" may add new values. +Each type of message has a `$message_type` field which can be used to +distinguish the different formats. When parsing, care should be taken +to be forwards-compatible with future changes to the format. Optional +values may be `null`. New fields may be added. Enumerated fields like +"level" or "suggestion_applicability" may add new values. ## Diagnostics @@ -29,6 +31,8 @@ Diagnostics have the following format: ```javascript { + /* Type of this message */ + "$message_type": "diagnostic", /* The primary message. */ "message": "unused variable: `x`", /* The diagnostic code. @@ -217,6 +221,8 @@ flag][option-emit] documentation. ```javascript { + /* Type of this message */ + "$message_type": "artifact", /* The filename that was generated. */ "artifact": "libfoo.rlib", /* The kind of artifact that was generated. Possible values: @@ -239,6 +245,8 @@ information, even if the diagnostics have been suppressed (such as with an ```javascript { + /* Type of this message */ + "$message_type": "future_incompat", /* An array of objects describing a warning that will become a hard error in the future. */ diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index 858b7bc79..ff80f1404 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -136,6 +136,7 @@ able to get around this problem by setting `-Clinker=lld-link` in RUSTFLAGS ```python from collections import defaultdict import subprocess +import sys def minor_version(version): return int(version.split('.')[1]) @@ -143,7 +144,7 @@ def minor_version(version): INSTALL_TOOLCHAIN = ["rustup", "toolchain", "install", "--profile", "minimal"] subprocess.run(INSTALL_TOOLCHAIN + ["nightly"]) -LOWER_BOUND = 65 +LOWER_BOUND = 73 NIGHTLY_VERSION = minor_version(subprocess.run( ["rustc", "+nightly", "--version"], capture_output=True, @@ -159,6 +160,7 @@ def llvm_version(toolchain): version_map = defaultdict(lambda: []) for version in range(LOWER_BOUND, NIGHTLY_VERSION - 1): toolchain = "1.{}.0".format(version) + print("Checking", toolchain, file=sys.stderr) subprocess.run( INSTALL_TOOLCHAIN + ["--no-self-update", toolchain], capture_output=True) @@ -196,6 +198,8 @@ The following table shows known good combinations of toolchain versions. | 1.52 - 1.55 | 12 | | 1.56 - 1.59 | 13 | | 1.60 - 1.64 | 14 | -| 1.65 | 15 | +| 1.65 - 1.69 | 15 | +| 1.70 - 1.72 | 16 | +| 1.73 - 1.74 | 17 | Note that the compatibility policy for this feature might change in the future. diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 907e9c59f..59ef74410 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -137,18 +137,17 @@ target | std | notes [`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv6 Android `arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL `arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with MUSL, hardfloat -`armebv7r-none-eabi` | * | Bare ARMv7-R, Big Endian -`armebv7r-none-eabihf` | * | Bare ARMv7-R, Big Endian, hardfloat +[`armebv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R, Big Endian +[`armebv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R, Big Endian, hardfloat `armv5te-unknown-linux-gnueabi` | ✓ | ARMv5TE Linux (kernel 4.4, glibc 2.23) `armv5te-unknown-linux-musleabi` | ✓ | ARMv5TE Linux with MUSL [`armv7-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7-A Android `armv7-unknown-linux-gnueabi` | ✓ | ARMv7-A Linux (kernel 4.15, glibc 2.27) `armv7-unknown-linux-musleabi` | ✓ | ARMv7-A Linux with MUSL `armv7-unknown-linux-musleabihf` | ✓ | ARMv7-A Linux with MUSL, hardfloat -`armv7a-none-eabi` | * | Bare ARMv7-A -`armv7r-none-eabi` | * | Bare ARMv7-R -`armv7r-none-eabihf` | * | Bare ARMv7-R, hardfloat -`asmjs-unknown-emscripten` | ✓ | asm.js via Emscripten +[`armv7a-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv7-A +[`armv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R +[`armv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare ARMv7-R, hardfloat `i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE [^x86_32-floats-x87] `i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17) [^x86_32-floats-x87] `i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL [^x86_32-floats-x87] @@ -160,22 +159,22 @@ target | std | notes [`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64D ABI) [`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch64 Bare-metal (LP64S ABI) [`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs] -`riscv32i-unknown-none-elf` | * | Bare RISC-V (RV32I ISA) -`riscv32imac-unknown-none-elf` | * | Bare RISC-V (RV32IMAC ISA) -`riscv32imc-unknown-none-elf` | * | Bare RISC-V (RV32IMC ISA) +[`riscv32imac-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA) +[`riscv32i-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32I ISA) +[`riscv32imc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA) `riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA) `riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA) `sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23) -`sparcv9-sun-solaris` | ✓ | SPARC Solaris 10/11, illumos -`thumbv6m-none-eabi` | * | Bare ARMv6-M -`thumbv7em-none-eabi` | * | Bare ARMv7E-M -`thumbv7em-none-eabihf` | * | Bare ARMV7E-M, hardfloat -`thumbv7m-none-eabi` | * | Bare ARMv7-M +`sparcv9-sun-solaris` | ✓ | SPARC Solaris 11, illumos +[`thumbv6m-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv6-M +[`thumbv7em-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv7E-M +[`thumbv7em-none-eabihf`](platform-support/arm-none-eabi.md) | * | Bare ARMV7E-M, hardfloat +[`thumbv7m-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv7-M [`thumbv7neon-linux-androideabi`](platform-support/android.md) | ✓ | Thumb2-mode ARMv7-A Android with NEON `thumbv7neon-unknown-linux-gnueabihf` | ✓ | Thumb2-mode ARMv7-A Linux with NEON (kernel 4.4, glibc 2.23) -`thumbv8m.base-none-eabi` | * | Bare ARMv8-M Baseline -`thumbv8m.main-none-eabi` | * | Bare ARMv8-M Mainline -`thumbv8m.main-none-eabihf` | * | Bare ARMv8-M Mainline, hardfloat +[`thumbv8m.base-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv8-M Baseline +[`thumbv8m.main-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv8-M Mainline +[`thumbv8m.main-none-eabihf`](platform-support/arm-none-eabi.md) | * | Bare ARMv8-M Mainline, hardfloat `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI @@ -185,7 +184,7 @@ target | std | notes `x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia` [`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia [`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android -`x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos +`x86_64-pc-solaris` | ✓ | 64-bit Solaris 11, illumos `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat `x86_64-unknown-redox` | ✓ | Redox OS @@ -216,9 +215,12 @@ host tools. target | std | host | notes -------|:---:|:----:|------- +[`arm64e-apple-ios`](platform-support/arm64e-apple-ios.md) | ✓ | | ARM64e Apple iOS +[`arm64e-apple-darwin`](platform-support/arm64e-apple-darwin.md) | ✓ | ✓ | ARM64e Apple Darwin `aarch64-apple-ios-macabi` | ? | | Apple Catalyst on ARM64 [`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS [`aarch64-apple-tvos-sim`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS Simulator +[`aarch64-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM64 Apple WatchOS [`aarch64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | ARM64 Apple WatchOS Simulator [`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 @@ -237,11 +239,11 @@ target | std | host | notes `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI) `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian) [`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian) -[`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS 64-bit with 32-bit pointers +[`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS 64-bit with 32-bit pointers [`armeb-unknown-linux-gnueabi`](platform-support/armeb-unknown-linux-gnueabi.md) | ✓ | ? | ARM BE8 the default ARM big-endian architecture since [ARMv6](https://developer.arm.com/documentation/101754/0616/armlink-Reference/armlink-Command-line-Options/--be8?lang=en). -`armv4t-none-eabi` | * | | Bare ARMv4T +[`armv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * | | Bare ARMv4T `armv4t-unknown-linux-gnueabi` | ? | | ARMv4T Linux -[`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Bare ARMv5TE +[`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Bare ARMv5TE `armv5te-unknown-linux-uclibceabi` | ? | | ARMv5TE Linux with uClibc `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD [`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | ARMv6 NetBSD w/hard-float @@ -255,8 +257,8 @@ target | std | host | notes `armv7-wrs-vxworks-eabihf` | ? | | ARMv7-A for VxWorks [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat -`armv7a-none-eabihf` | * | | Bare ARMv7-A, hardfloat -[`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARMv7-A Apple WatchOS +[`armv7a-none-eabihf`](platform-support/arm-none-eabi.md) | * | | Bare ARMv7-A, hardfloat +[`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARMv7-A Apple WatchOS `armv7s-apple-ios` | ✓ | | ARMv7-A Apple-A6 Apple iOS `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` `bpfeb-unknown-none` | * | | BPF (big endian) @@ -275,6 +277,7 @@ target | std | host | notes [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD [^x86_32-floats-return-ABI] `i686-uwp-windows-gnu` | ? | | [^x86_32-floats-return-ABI] `i686-uwp-windows-msvc` | ? | | [^x86_32-floats-return-ABI] +[`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI] `i686-wrs-vxworks` | ? | | [^x86_32-floats-return-ABI] [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux `mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23) @@ -313,7 +316,8 @@ target | std | host | notes [`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer) `riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33) `riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches) -`riscv32im-unknown-none-elf` | * | | Bare RISC-V (RV32IM ISA) +[`riscv32imafc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA) +[`riscv32im-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | | Bare RISC-V (RV32IM ISA) [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA) [`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF @@ -329,19 +333,18 @@ target | std | host | notes [`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+ [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64 [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64 -`thumbv4t-none-eabi` | * | | Thumb-mode Bare ARMv4T -[`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Thumb-mode Bare ARMv5TE +[`thumbv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * | | Thumb-mode Bare ARMv4T +[`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Thumb-mode Bare ARMv5TE `thumbv7a-pc-windows-msvc` | ? | | `thumbv7a-uwp-windows-msvc` | ✓ | | `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7-A Linux with NEON, MUSL [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 -[`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS -[`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator +[`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | 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-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 [`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku @@ -351,6 +354,7 @@ target | std | host | notes [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD `x86_64-uwp-windows-gnu` | ✓ | | `x86_64-uwp-windows-msvc` | ✓ | | +[`x86_64-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 64-bit Windows 7 support `x86_64-wrs-vxworks` | ? | | [`x86_64h-apple-darwin`](platform-support/x86_64h-apple-darwin.md) | ✓ | ✓ | macOS with late-gen Intel (at least Haswell) diff --git a/src/doc/rustc/src/platform-support/TEMPLATE.md b/src/doc/rustc/src/platform-support/TEMPLATE.md index e64783fcf..87dde7225 100644 --- a/src/doc/rustc/src/platform-support/TEMPLATE.md +++ b/src/doc/rustc/src/platform-support/TEMPLATE.md @@ -6,7 +6,7 @@ One-sentence description of the target (e.g. CPU, OS) ## Target maintainers -- Some Person, `email@example.org`, https://github.com/... +- Some Person, https://github.com/... ## Requirements diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md index 9233a36db..7a6609b2d 100644 --- a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md +++ b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md @@ -39,7 +39,7 @@ Create the following shell scripts that wrap Clang from the OpenHarmony SDK: ```sh #!/bin/sh exec /path/to/ohos-sdk/linux/native/llvm/bin/clang \ - --target aarch64-linux-gnu \ + -target aarch64-linux-gnu \ "$@" ``` @@ -48,7 +48,7 @@ exec /path/to/ohos-sdk/linux/native/llvm/bin/clang \ ```sh #!/bin/sh exec /path/to/ohos-sdk/linux/native/llvm/bin/clang++ \ - --target aarch64-linux-gnu \ + -target aarch64-linux-gnu \ "$@" ``` @@ -81,6 +81,13 @@ ranlib = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ranlib" llvm-config = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-config" ``` +```text +note: You need to insert "/usr/include/x86_64-linux-gnu/" into environment variable: $C_INCLUDE_PATH + if some header files like bits/xxx.h not found. +note: You can install gcc-aarch64-linux-gnu,g++-aarch64-linux-gnu if some files like crti.o not found. +note: You may need to install libc6-dev-i386 libc6-dev if "gnu/stubs-32.h" not found. +``` + ## Building Rust programs Rust does not yet ship pre-compiled artifacts for this target. To compile for @@ -91,7 +98,7 @@ this target, you will either need to build Rust with the target enabled (see You will need to configure the linker to use in `~/.cargo/config`: ```toml [target.aarch64-unknown-teeos] -linker = "/path/to/aarch64-unknown-teeos-clang.sh" +linker = "/path/to/aarch64-unknown-teeos-clang.sh" # or aarch64-linux-gnu-ld ``` ## Testing diff --git a/src/doc/rustc/src/platform-support/apple-watchos.md b/src/doc/rustc/src/platform-support/apple-watchos.md index fe4c7c0c8..7be246735 100644 --- a/src/doc/rustc/src/platform-support/apple-watchos.md +++ b/src/doc/rustc/src/platform-support/apple-watchos.md @@ -1,6 +1,7 @@ # *-apple-watchos - arm64_32-apple-watchos - armv7k-apple-watchos +- aarch64-apple-watchos - aarch64-apple-watchos-sim - x86_64-apple-watchos-sim @@ -9,6 +10,7 @@ Apple WatchOS targets: - Apple WatchOS on Arm 64_32 - Apple WatchOS on Arm v7k +- Apple WatchOS on Arm 64 - Apple WatchOS Simulator on arm64 - Apple WatchOS Simulator on x86_64 @@ -16,6 +18,7 @@ Apple WatchOS targets: * [@deg4uss3r](https://github.com/deg4uss3r) * [@vladimir-ea](https://github.com/vladimir-ea) +* [@leohowell](https://github.com/leohowell) ## Requirements diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md new file mode 100644 index 000000000..4f76d0d7b --- /dev/null +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -0,0 +1,96 @@ +# `{arm,thumb}*-none-eabi(hf)?` + +**Tier: 2** +- [arm(eb)?v7r-none-eabi(hf)?](armv7r-none-eabi.md) +- armv7a-none-eabi +- thumbv6m-none-eabi +- thumbv7m-none-eabi +- thumbv7em-none-eabi(hf)? +- thumbv8m.base-none-eabi +- thumbv8m.main-none-eabi(hf)? + +**Tier: 3** +- [{arm,thumb}v4t-none-eabi](armv4t-none-eabi.md) +- [{arm,thumb}v5te-none-eabi](armv5te-none-eabi.md) +- armv7a-none-eabihf + +Bare-metal target for 32-bit ARM CPUs. + +If a target has a `*hf` variant, that variant uses the hardware floating-point +ABI and enables some minimum set of floating-point features based on the FPU(s) +available in that processor family. + +## Requirements + +These targets are cross-compiled and use static linking. + +By default, the `lld` linker included with Rust will be used; however, you may +want to use the GNU linker instead. This can be obtained for Windows/Mac/Linux +from the [Arm Developer Website][arm-gnu-toolchain], or possibly from your OS's +package manager. To use it, add the following to your `.cargo/config.toml`: + +```toml +[target.<your-target>] +linker = "arm-none-eabi-ld" +``` + +The GNU linker can also be used by specifying `arm-none-eabi-gcc` as the +linker. This is needed when using GCC's link time optimization. + +[arm-gnu-toolchain]: https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain + +These targets don't provide a linker script, so you'll need to bring your own +according to the specific device you are using. Pass +`-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use +`your_script.ld` during linking. + +Targets named `thumb*` instead of `arm*` +generate Thumb-mode code by default. M-profile processors (`thumbv*m*-*` +targets) only support Thumb-mode code. +For the `arm*` targets, Thumb-mode code generation can be enabled by using +`-C target-feature=+thumb-mode`. Using the unstable +`#![feature(arm_target_feature)]`, the attribute +`#[target_feature(enable = "thumb-mode")]` can be applied to individual +`unsafe` functions to cause those functions to be compiled to Thumb-mode code. + +## Building Rust Programs + +For the Tier 3 targets in this family, rust does not ship pre-compiled +artifacts. + +Just use the `build-std` nightly cargo feature to build the `core` library. You +can pass this as a command line argument to cargo, or your `.cargo/config.toml` +file might include the following lines: + +```toml +[unstable] +build-std = ["core"] +``` + +Most of `core` should work as expected, with the following notes: +* If the target is not `*hf`, then floating-point operations are emulated in + software. +* Integer division is also emulated in software on some targets, depending on + the CPU. +* Architectures prior to ARMv7 don't have atomic instructions. + +`alloc` is also supported, as long as you provide your own global allocator. + +Rust programs are output as ELF files. + +## Testing + +This is a cross-compiled target that you will need to emulate during testing. + +The exact emulator that you'll need depends on the specific device you want to +run your code on. + +## Cross-compilation toolchains and C code + +The target supports C code compiled with the `arm-none-eabi` target triple and +a suitable `-march` or `-mcpu` flag. + +`gcc` or `clang` can be used, but note that `gcc` uses `-fshort-enums` by +default for `arm-none*` targets, while `clang` does not. `rustc` matches the +`gcc` behavior, i.e., the size of a `#[repr(C)] enum` in Rust can be as little +as 1 byte, rather than 4, as they are on `arm-linux` targets. diff --git a/src/doc/rustc/src/platform-support/arm64e-apple-darwin.md b/src/doc/rustc/src/platform-support/arm64e-apple-darwin.md new file mode 100644 index 000000000..f93555129 --- /dev/null +++ b/src/doc/rustc/src/platform-support/arm64e-apple-darwin.md @@ -0,0 +1,36 @@ +# `arm64e-apple-darwin` + +**Tier: 3 (with Host Tools)** + +ARM64e macOS (11.0+, Big Sur+) + +## Target maintainers + +- Artyom Tetyukhin ([@arttet](https://github.com/https://github.com/arttet)) + +## Requirements + +Target for `macOS` on late-generation `M` series Apple chips. + +## Building the target + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: + +```toml +[build] +target = [ "arm64e-apple-darwin" ] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. +To compile for this target, you will need to build Rust with the target enabled (see [Building the target](#building-the-target) above). + +## Testing + +The target does support running binaries on macOS platforms with `arm64e` architecture. + +## Cross-compilation toolchains and C code + +The targets do support `C` code. +To build compatible `C` code, you have to use XCode with the same compiler and flags. diff --git a/src/doc/rustc/src/platform-support/arm64e-apple-ios.md b/src/doc/rustc/src/platform-support/arm64e-apple-ios.md new file mode 100644 index 000000000..2b2e02899 --- /dev/null +++ b/src/doc/rustc/src/platform-support/arm64e-apple-ios.md @@ -0,0 +1,37 @@ +# `arm64e-apple-ios` + +**Tier: 3** + +ARM64e iOS (12.0+) + +## Target maintainers + +- Artyom Tetyukhin ([@arttet](https://github.com/https://github.com/arttet)) + +## Requirements + +These targets only support cross-compilation. +The targets do support `std`. + +## Building the target + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: + +```toml +[build] +target = [ "arm64e-apple-ios" ] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. +To compile for this target, you will need to build Rust with the target enabled (see [Building the target](#building-the-target) above). + +## Testing + +The target does support running binaries on iOS platforms with `arm64e` architecture. + +## Cross-compilation toolchains and C code + +The targets do support `C` code. +To build compatible `C` code, you have to use XCode with the same compiler and flags. diff --git a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md index a230eba6b..29c47db83 100644 --- a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md @@ -6,51 +6,16 @@ Bare-metal target for any cpu in the ARMv4T architecture family, supporting ARM/Thumb code interworking (aka `a32`/`t32`), with ARM code as the default code generation. -In particular this supports the Gameboy Advance (GBA), but there's nothing GBA -specific with this target, so any ARMv4T device should work fine. +In particular this supports the Game Boy Advance (GBA), but there's nothing +GBA-specific with this target, so any ARMv4T device should work fine. + +See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all +`arm-none-eabi` targets. ## Target Maintainers * [@Lokathor](https://github.com/lokathor) -## Requirements - -The target is cross-compiled, and uses static linking. - -This target doesn't provide a linker script, you'll need to bring your own -according to the specific device you want to target. Pass -`-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use -`your_script.ld` during linking. - -## Building Rust Programs - -Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target. - -Just use the `build-std` nightly cargo feature to build the `core` library. You -can pass this as a command line argument to cargo, or your `.cargo/config.toml` -file might include the following lines: - -```toml -[unstable] -build-std = ["core"] -``` - -Most of `core` should work as expected, with the following notes: -* the target is "soft float", so `f32` and `f64` operations are emulated in - software. -* integer division is also emulated in software. -* the target is old enough that it doesn't have atomic instructions. - -Rust programs are output as ELF files. - -For running on hardware, you'll generally need to extract the "raw" program code -out of the ELF and into a file of its own. The `objcopy` program provided as -part of the GNU Binutils can do this: - -```shell -arm-none-eabi-objcopy --output-target binary [in_file] [out_file] -``` - ## Testing This is a cross-compiled target that you will need to emulate during testing. diff --git a/src/doc/rustc/src/platform-support/armv5te-none-eabi.md b/src/doc/rustc/src/platform-support/armv5te-none-eabi.md index f469dab1c..37284ba72 100644 --- a/src/doc/rustc/src/platform-support/armv5te-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv5te-none-eabi.md @@ -8,54 +8,13 @@ generation. The `thumbv5te-none-eabi` target is the same as this one, but the instruction set defaults to `t32`. +See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all +`arm-none-eabi` targets. + ## Target Maintainers * [@QuinnPainter](https://github.com/QuinnPainter) -## Requirements - -The target is cross-compiled, and uses static linking. - -By default, the `lld` linker included with Rust will be used. - -However, you may want to use the `arm-none-eabi-ld` linker instead. This can be obtained for Windows/Mac/Linux from the [ARM -Developer Website][arm-dev], or possibly from your OS's package manager. To use it, add the following to your `.cargo/config.toml`: - -```toml -[target.armv5te-none-eabi] -linker = "arm-none-eabi-ld" -``` - -[arm-dev]: https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain - -This target doesn't provide a linker script, you'll need to bring your own -according to the specific device you want to target. Pass -`-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use -`your_script.ld` during linking. - -## Building Rust Programs - -Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target. - -Just use the `build-std` nightly cargo feature to build the `core` library. You -can pass this as a command line argument to cargo, or your `.cargo/config.toml` -file might include the following lines: - -```toml -[unstable] -build-std = ["core"] -``` - -Most of `core` should work as expected, with the following notes: -* the target is "soft float", so `f32` and `f64` operations are emulated in - software. -* integer division is also emulated in software. -* the target is old enough that it doesn't have atomic instructions. - -`alloc` is also supported, as long as you provide your own global allocator. - -Rust programs are output as ELF files. - ## Testing This is a cross-compiled target that you will need to emulate during testing. @@ -63,4 +22,5 @@ This is a cross-compiled target that you will need to emulate during testing. Because this is a device-agnostic target, and the exact emulator that you'll need depends on the specific device you want to run your code on. -For example, when programming for the DS, you can use one of the several available DS emulators, such as [melonDS](https://melonds.kuribo64.net/). +For example, when programming for the DS, you can use one of the several +available DS emulators, such as [melonDS](https://melonds.kuribo64.net/). diff --git a/src/doc/rustc/src/platform-support/armv7r-none-eabi.md b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md new file mode 100644 index 000000000..670cead9e --- /dev/null +++ b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md @@ -0,0 +1,47 @@ +# `arm(eb)?v7r-none-eabi(hf)?` + +**Tier: 2** + +Bare-metal target for CPUs in the ARMv7-R architecture family, supporting +dual ARM/Thumb mode, with ARM mode as the default. + +Processors in this family include the [Arm Cortex-R4, 5, 7, and 8][cortex-r]. + +The `eb` versions of this target generate code for big-endian processors. + +See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all +`arm-none-eabi` targets. + +[cortex-r]: https://en.wikipedia.org/wiki/ARM_Cortex-R + +## Target maintainers + +- [Chris Copeland](https://github.com/chrisnc), `chris@chrisnc.net` + +## Requirements + +When using the big-endian version of this target, note that some variants of +the Cortex-R have both big-endian instructions and data. This configuration is +known as BE-32, while data-only big-endianness is known as BE-8. To build +programs for BE-32 processors, the GNU linker must be used with the `-mbe32` +option. See [ARM Cortex-R Series Programmer's Guide: Endianness][endianness] +for more details about different endian modes. + +When using the hardfloat targets, the minimum floating-point features assumed +are those of the `vfpv3-d16`, which includes single- and double-precision, with +16 double-precision registers. This floating-point unit appears in Cortex-R4F +and Cortex-R5F processors. See [VFP in the Cortex-R processors][vfp] +for more details on the possible FPU variants. + +If your processor supports a different set of floating-point features than the +default expectations of `vfpv3-d16`, then these should also be enabled or +disabled as needed with `-C target-feature=(+/-)`. + +[endianness]: https://developer.arm.com/documentation/den0042/a/Coding-for-Cortex-R-Processors/Endianness + +[vfp]: https://developer.arm.com/documentation/den0042/a/Floating-Point/Floating-point-basics-and-the-IEEE-754-standard/VFP-in-the-Cortex-R-processors + +## Cross-compilation toolchains and C code + +This target supports C code compiled with the `arm-none-eabi` target triple and +`-march=armv7-r` or a suitable `-mcpu` flag. diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 9f0662783..2a741fa3d 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -121,10 +121,8 @@ export build_env=' 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 + --target aarch64-unknown-nto-qnx710,x86_64-pc-nto-qnx710,x86_64-unknown-linux-gnu \ + rustc library/core library/alloc library/std ``` ## Running the Rust test suite diff --git a/src/doc/rustc/src/platform-support/riscv32i-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32i-unknown-none-elf.md new file mode 100644 index 000000000..edfe07fc0 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32i-unknown-none-elf.md @@ -0,0 +1 @@ +riscv32imac-unknown-none-elf.md diff --git a/src/doc/rustc/src/platform-support/riscv32im-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32im-unknown-none-elf.md new file mode 100644 index 000000000..edfe07fc0 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32im-unknown-none-elf.md @@ -0,0 +1 @@ +riscv32imac-unknown-none-elf.md diff --git a/src/doc/rustc/src/platform-support/riscv32imac-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32imac-unknown-none-elf.md new file mode 100644 index 000000000..a069f3d3a --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32imac-unknown-none-elf.md @@ -0,0 +1,34 @@ +# `riscv32{i,im,imc,imac,imafc}-unknown-none-elf` + +**Tier: 2/3** + +Bare-metal target for RISC-V CPUs with the RV32I, RV32IM, RV32IMC, RV32IMAFC and RV32IMAC ISAs. + +## Target maintainers + +* Rust Embedded Working Group, [RISC-V team](https://github.com/rust-embedded/wg#the-risc-v-team) + +## Requirements + +The target is cross-compiled, and uses static linking. No external toolchain +is required and the default `rust-lld` linker works, but you must specify +a linker script. The [`riscv-rt`] crate provides a suitable one. The +[`riscv-rust-quickstart`] repository gives an example of an RV32 project. + +[`riscv-rt`]: https://crates.io/crates/riscv-rt +[`riscv-rust-quickstart`]: https://github.com/riscv-rust/riscv-rust-quickstart + +## Building the target + +This target is included in Rust and can be installed via `rustup`. + +## Testing + +This is a cross-compiled no-std target, which must be run either in a simulator +or by programming them onto suitable hardware. It is not possible to run the +Rust testsuite on this target. + +## Cross-compilation toolchains and C code + +This target supports C code. If interlinking with C or C++, you may need to use +riscv64-unknown-elf-gcc as a linker instead of rust-lld. diff --git a/src/doc/rustc/src/platform-support/riscv32imafc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32imafc-unknown-none-elf.md new file mode 100644 index 000000000..edfe07fc0 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32imafc-unknown-none-elf.md @@ -0,0 +1 @@ +riscv32imac-unknown-none-elf.md diff --git a/src/doc/rustc/src/platform-support/riscv32imc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32imc-unknown-none-elf.md new file mode 100644 index 000000000..edfe07fc0 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv32imc-unknown-none-elf.md @@ -0,0 +1 @@ +riscv32imac-unknown-none-elf.md diff --git a/src/doc/rustc/src/platform-support/win7-windows-msvc.md b/src/doc/rustc/src/platform-support/win7-windows-msvc.md new file mode 100644 index 000000000..96613fb9b --- /dev/null +++ b/src/doc/rustc/src/platform-support/win7-windows-msvc.md @@ -0,0 +1,80 @@ +# *-win7-windows-msvc + +**Tier: 3** + +Windows targets continuing support of windows7. + +## Target maintainers + +- @roblabla + +## Requirements + +This target supports all of core, alloc, std and test. This is automatically +tested every night on private infrastructure hosted by the maintainer. Host +tools may also work, though those are not currently tested. + +Those targets follow Windows calling convention for extern "C". + +Like any other Windows target, the created binaries are in PE format. + +## Building the target + +You can build Rust with support for the targets by adding it to the target list in config.toml: + +```toml +[build] +build-stage = 1 +target = [ "x86_64-win7-windows-msvc" ] +``` + +## Building Rust programs + +Rust does not ship pre-compiled artifacts for this target. To compile for this +target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy by using `build-std` or +similar. + +## Testing + +Created binaries work fine on Windows or Wine using native hardware. Remote +testing is possible using the `remote-test-server` described [here](https://rustc-dev-guide.rust-lang.org/tests/running.html#running-tests-on-a-remote-machine). + +## Cross-compilation toolchains and C code + +Compatible C code can be built with either MSVC's `cl.exe` or LLVM's clang-cl. + +Cross-compilation is possible using clang-cl/lld-link. It also requires the +Windows SDK, which can be acquired using [`xwin`](https://github.com/Jake-Shadle/xwin). + +- Install `clang-cl` and `lld-link` on your machine, and make sure they are in + your $PATH. +- Install `xwin`: `cargo install xwin` +- Use `xwin` to install the Windows SDK: `xwin splat --output winsdk` +- Create an `xwin-lld-link` script with the following content: + + ```bash + #!/usr/bin/env bash + set -e + XWIN=/path/to/winsdk + lld-link "$@" /libpath:$XWIN/crt/lib/x86_64 /libpath:$XWIN/sdk/lib/um/x86_64 /libpath:$XWIN/sdk/lib/ucrt/x86_64 + ``` + +- Create an `xwin-clang-cl` script with the following content: + + ```bash + #!/usr/bin/env bash + set -e + XWIN=/path/to/winsdk + clang-cl /imsvc "$XWIN/crt/include" /imsvc "$XWIN/sdk/include/ucrt" /imsvc "$XWIN/sdk/include/um" /imsvc "$XWIN/sdk/include/shared" --target="x86_64-pc-windows-msvc" "$@" + ``` + +- In your config.toml, add the following lines: + + ```toml + [target.x86_64-win7-windows-msvc] + linker = "path/to/xwin-lld-link" + cc = "path/to/xwin-clang-cl" + ``` + +You should now be able to cross-compile the Rust std, and any rust program. diff --git a/src/doc/rustdoc/src/read-documentation/search.md b/src/doc/rustdoc/src/read-documentation/search.md index 56a5016d0..1f45bd6c6 100644 --- a/src/doc/rustdoc/src/read-documentation/search.md +++ b/src/doc/rustdoc/src/read-documentation/search.md @@ -72,6 +72,7 @@ the standard library and functions that are included in the results list: | [`stdout, [u8]`][stdoutu8] | `Stdout::write` | | [`any -> !`][] | `panic::panic_any` | | [`vec::intoiter<T> -> [T]`][iterasslice] | `IntoIter::as_slice` and `IntoIter::next_chunk` | +| [`iterator<T>, fnmut -> T`][iterreduce] | `Iterator::reduce` and `Iterator::find` | [`usize -> vec`]: ../../std/vec/struct.Vec.html?search=usize%20-%3E%20vec&filter-crate=std [`vec, vec -> bool`]: ../../std/vec/struct.Vec.html?search=vec,%20vec%20-%3E%20bool&filter-crate=std @@ -81,6 +82,7 @@ the standard library and functions that are included in the results list: [`any -> !`]: ../../std/vec/struct.Vec.html?search=any%20-%3E%20!&filter-crate=std [stdoutu8]: ../../std/vec/struct.Vec.html?search=stdout%2C%20[u8]&filter-crate=std [iterasslice]: ../../std/vec/struct.Vec.html?search=vec%3A%3Aintoiter<T>%20->%20[T]&filter-crate=std +[iterreduce]: ../../std/index.html?search=iterator<T>%2C%20fnmut%20->%20T&filter-crate=std ### How type-based search works @@ -95,7 +97,9 @@ After deciding which items are type parameters and which are actual types, it then searches by matching up the function parameters (written before the `->`) and the return types (written after the `->`). Type matching is order-agnostic, and allows items to be left out of the query, but items that are present in the -query must be present in the function for it to match. +query must be present in the function for it to match. The `self` parameter is +treated the same as any other parameter, and `Self` is resolved to the +underlying type's name. Function signature searches can query generics, wrapped in angle brackets, and traits will be normalized like types in the search engine if no type parameters @@ -103,8 +107,37 @@ match them. For example, a function with the signature `fn my_function<I: Iterator<Item=u32>>(input: I) -> usize` can be matched with the following queries: -* `Iterator<u32> -> usize` -* `Iterator -> usize` +* `Iterator<Item=u32> -> usize` +* `Iterator<u32> -> usize` (you can leave out the `Item=` part) +* `Iterator -> usize` (you can leave out iterator's generic entirely) +* `T -> usize` (you can match with a generic parameter) + +Each of the above queries is progressively looser, except the last one +would not match `dyn Iterator`, since that's not a type parameter. + +If a bound has multiple associated types, specifying the name allows you to +pick which one gets matched. If no name is specified, then the query will +match of any of them. For example, + +```rust +pub trait MyTrait { + type First; + type Second; +} + +/// This function can be found using the following search queries: +/// +/// MyTrait<First=u8, Second=u32> -> bool +/// MyTrait<u32, First=u8> -> bool +/// MyTrait<Second=u32> -> bool +/// MyTrait<u32, u8> -> bool +/// +/// The following queries, however, will *not* match it: +/// +/// MyTrait<First=u32> -> bool +/// MyTrait<u32, u32> -> bool +pub fn my_fn(x: impl MyTrait<First=u8, Second=u32>) -> bool { true } +``` Generics and function parameters are order-agnostic, but sensitive to nesting and number of matches. For example, a function with the signature @@ -134,6 +167,10 @@ Most of these limitations should be addressed in future version of Rustdoc. with that bound, it'll match, but `option<T> -> T where T: Default` cannot be precisely searched for (use `option<Default> -> Default`). + * Supertraits, type aliases, and Deref are all ignored. Search mostly + operates on type signatures *as written*, and not as they are + represented within the compiler. + * Type parameters match type parameters, such that `Option<A>` matches `Option<T>`, but never match concrete types in function signatures. A trait named as if it were a type, such as `Option<Read>`, will match @@ -183,7 +220,8 @@ slice = OPEN-SQUARE-BRACKET [ nonempty-arg-list ] CLOSE-SQUARE-BRACKET arg = [type-filter *WS COLON *WS] (path [generics] / slice / [!]) type-sep = COMMA/WS *(COMMA/WS) nonempty-arg-list = *(type-sep) arg *(type-sep arg) *(type-sep) -generics = OPEN-ANGLE-BRACKET [ nonempty-arg-list ] *(type-sep) +generic-arg-list = *(type-sep) arg [ EQUAL arg ] *(type-sep arg [ EQUAL arg ]) *(type-sep) +generics = OPEN-ANGLE-BRACKET [ generic-arg-list ] *(type-sep) CLOSE-ANGLE-BRACKET return-args = RETURN-ARROW *(type-sep) nonempty-arg-list @@ -230,6 +268,7 @@ DOUBLE-COLON = "::" QUOTE = %x22 COMMA = "," RETURN-ARROW = "->" +EQUAL = "=" ALPHA = %x41-5A / %x61-7A ; A-Z / a-z DIGIT = %x30-39 diff --git a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md index 046d01854..669dc9358 100644 --- a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md +++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md @@ -201,7 +201,7 @@ mod bar { # fn main() {} ``` -Here, because `bar` is not public, `Bar` wouldn't have its own page, so there's nowhere +Here, because `bar` is not public, `bar` wouldn't have its own page, so there's nowhere to link to. `rustdoc` will inline these definitions, and so we end up in the same case as the `#[doc(inline)]` above; `Bar` is in a `Structs` section, as if it were defined at the top level. If we add the `no_inline` form of the attribute: diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md index 0e15c7907..a5b9169c9 100644 --- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md @@ -35,6 +35,9 @@ and `cfg!(name = "value")` call. It will check that the `"value"` specified is p list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs` lint diagnostic. The default diagnostic level for this lint is `Warn`. +The command line `--cfg` arguments are currently *NOT* checked but may very well be checked in +the future. + To enable checking of values, but to provide an empty set of expected values, use these forms: ```bash @@ -187,70 +190,3 @@ fn shoot_lasers() {} // the cfg(feature) list fn write_shakespeare() {} ``` - -## The deprecated `names(...)` form - -The `names(...)` form enables checking the names. This form uses a named list: - -```bash -rustc --check-cfg 'names(name1, name2, ... nameN)' -``` - -where each `name` is a bare identifier (has no quotes). The order of the names is not significant. - -If `--check-cfg names(...)` is specified at least once, then `rustc` will check all references to -condition names. `rustc` will check every `#[cfg]` attribute, `#[cfg_attr]` attribute, `cfg` clause -inside `#[link]` attribute and `cfg!(...)` call against the provided list of expected condition -names. If a name is not present in this list, then `rustc` will report an `unexpected_cfgs` lint -diagnostic. The default diagnostic level for this lint is `Warn`. - -If `--check-cfg names(...)` is not specified, then `rustc` will not check references to condition -names. - -`--check-cfg names(...)` may be specified more than once. The result is that the list of valid -condition names is merged across all options. It is legal for a condition name to be specified -more than once; redundantly specifying a condition name has no effect. - -To enable checking condition names with an empty set of valid condition names, use the following -form. The parentheses are required. - -```bash -rustc --check-cfg 'names()' -``` - -Note that `--check-cfg 'names()'` is _not_ equivalent to omitting the option entirely. -The first form enables checking condition names, while specifying that there are no valid -condition names (outside of the set of well-known names defined by `rustc`). Omitting the -`--check-cfg 'names(...)'` option does not enable checking condition names. - -## The deprecated `values(...)` form - -The `values(...)` form enables checking the values within list-valued conditions. It has this -form: - -```bash -rustc --check-cfg `values(name, "value1", "value2", ... "valueN")' -``` - -where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal -string. `name` specifies the name of the condition, such as `feature` or `target_os`. - -When the `values(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]` -attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]` -and `cfg!(name = "value")` call. It will check that the `"value"` specified is present in the -list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs` -lint diagnostic. The default diagnostic level for this lint is `Warn`. - -To enable checking of values, but to provide an empty set of valid values, use this form: - -```bash -rustc --check-cfg `values(name)` -``` - -The `--check-cfg values(...)` option can be repeated, both for the same condition name and for -different names. If it is repeated for the same condition name, then the sets of values for that -condition are merged together. - -If `values()` is specified, then `rustc` will enable the checking of well-known values defined -by itself. Note that it's necessary to specify the `values()` form to enable the checking of -well known values, specifying the other forms doesn't implicitly enable it. diff --git a/src/doc/unstable-book/src/compiler-flags/codegen-options.md b/src/doc/unstable-book/src/compiler-flags/codegen-options.md new file mode 100644 index 000000000..31dfcdb19 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/codegen-options.md @@ -0,0 +1,56 @@ +# Unstable codegen options + +All of these options are passed to `rustc` via the `-C` flag, short for "codegen". The flags are +stable but some of their values are individually unstable, and also require using `-Z +unstable-options` to be accepted. + +## linker-flavor + +In addition to the stable set of linker flavors, the following unstable values also exist: +- `ptx`: use [`rust-ptx-linker`](https://github.com/denzp/rust-ptx-linker) + for Nvidia NVPTX GPGPU support. +- `bpf`: use [`bpf-linker`](https://github.com/alessandrod/bpf-linker) for eBPF support. + +Additionally, a set of more precise linker flavors also exists, for example allowing targets to +declare that they use the LLD linker by default. The following values are currently unstable, and +the goal is for them to become stable, and preferred in practice over the existing stable values: +- `gnu`: unix-like linker with GNU extensions +- `gnu-lld`: `gnu` using LLD +- `gnu-cc`: `gnu` using a C/C++ compiler as the linker driver +- `gnu-lld-cc`: `gnu` using LLD and a C/C++ compiler as the linker driver +- `darwin`: unix-like linker for Apple targets +- `darwin-lld`: `darwin` using LLD +- `darwin-cc`: `darwin` using a C/C++ compiler as the linker driver +- `darwin-lld-cc`: `darwin` using LLD and a C/C++ compiler as the linker driver +- `wasm-lld`: unix-like linker for Wasm targets, with LLD +- `wasm-lld-cc`: unix-like linker for Wasm targets, with LLD and a C/C++ compiler as the linker + driver +- `unix`: basic unix-like linker for "any other Unix" targets (Solaris/illumos, L4Re, MSP430, etc), + not supported with LLD. +- `unix-cc`: `unix` using a C/C++ compiler as the linker driver +- `msvc-lld`: MSVC-style linker for Windows and UEFI, with LLD +- `em-cc`: emscripten compiler frontend, similar to `wasm-lld-cc` with a different interface + +## link-self-contained + +This flag generally controls whether the linker will use libraries and objects shipped with Rust +instead of those in the system. The stable boolean values for this flag are coarse-grained +(everything or nothing), but there exists a set of unstable values with finer-grained control, +`-Clink-self-contained` can accept a comma-separated list of components, individually enabled +(`+component`) or disabled (`-component`): +- `crto`: CRT objects (e.g. on `windows-gnu`, `musl`, `wasi` targets) +- `libc`: libc static library (e.g. on `musl`, `wasi` targets) +- `unwind`: libgcc/libunwind (e.g. on `windows-gnu`, `fuchsia`, `fortanix`, `gnullvm` targets) +- `linker`: linker, dlltool, and their necessary libraries (e.g. on `windows-gnu` and for + `rust-lld`) +- `sanitizers`: sanitizer runtime libraries +- `mingw`: other MinGW libs and Windows import libs + +Out of the above self-contained linking components, `linker` is the only one currently implemented +(beyond parsing the CLI options). + +It refers to the LLD linker, built from the same LLVM revision used by rustc (named `rust-lld` to +avoid naming conflicts), that is distributed via `rustup` with the compiler (and is used by default +for the wasm targets). One can also opt-in to use it by combining this flag with an appropriate +linker flavor: for example, `-Clinker-flavor=gnu-lld-cc -Clink-self-contained=+linker` will use the +toolchain's `rust-lld` as the linker. diff --git a/src/doc/unstable-book/src/compiler-flags/default-hidden-visibility.md b/src/doc/unstable-book/src/compiler-flags/default-hidden-visibility.md new file mode 100644 index 000000000..579add4a9 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/default-hidden-visibility.md @@ -0,0 +1,12 @@ +# `default-hidden-visibility` + +The tracking issue for this feature is: https://github.com/rust-lang/compiler-team/issues/656 + +------------------------ + +This flag can be used to override the target's +[`default_hidden_visibility`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_target/spec/struct.TargetOptions.html#structfield.default_hidden_visibility) +setting. +Using `-Zdefault_hidden_visibility=yes` is roughly equivalent to Clang's +[`-fvisibility=hidden`](https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fvisibility) +cmdline flag. diff --git a/src/doc/unstable-book/src/compiler-flags/env.md b/src/doc/unstable-book/src/compiler-flags/env.md new file mode 100644 index 000000000..ac6d7474a --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/env.md @@ -0,0 +1,45 @@ +# `env` + +The tracking issue for this feature is: [#118372](https://github.com/rust-lang/rust/issues/118372). + +------------------------ + +This option flag allows to specify environment variables value at compile time to be +used by `env!` and `option_env!` macros. It also impacts `tracked_env::var` function +from the `proc_macro` crate. + +This information will be stored in the dep-info files. For more information about +dep-info files, take a look [here](https://doc.rust-lang.org/cargo/guide/build-cache.html#dep-info-files). + +When retrieving an environment variable value, the one specified by `--env` will take +precedence. For example, if you want have `PATH=a` in your environment and pass: + +```bash +rustc --env PATH=env +``` + +Then you will have: + +```rust,no_run +assert_eq!(env!("PATH"), "env"); +``` + +It will trigger a new compilation if any of the `--env` argument value is different. +So if you first passed: + +```bash +--env A=B --env X=12 +``` + +and then on next compilation: + +```bash +--env A=B +``` + +`X` value is different (not set) so the code will be re-compiled. + +Please note that on Windows, environment variables are case insensitive but case +preserving whereas `rustc`'s environment variables are case sensitive. For example, +having `Path` in your environment (case insensitive) is different than using +`rustc --env Path=...` (case sensitive). diff --git a/src/doc/unstable-book/src/compiler-flags/function-return.md b/src/doc/unstable-book/src/compiler-flags/function-return.md new file mode 100644 index 000000000..d044a6f68 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/function-return.md @@ -0,0 +1,25 @@ +# `function-return` + +The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/116853. + +------------------------ + +Option `-Zfunction-return` controls how function returns are converted. + +It is equivalent to [Clang]'s and [GCC]'s `-mfunction-return`. The Linux kernel +uses it for RETHUNK builds. For details, see [LLVM commit 2240d72f15f3] ("[X86] +initial -mfunction-return=thunk-extern support") which introduces the feature. + +Supported values for this option are: + + - `keep`: do not convert function returns. + - `thunk-extern`: convert function returns (`ret`) to jumps (`jmp`) + to an external symbol called `__x86_return_thunk`. + +Like in Clang, GCC's values `thunk` and `thunk-inline` are not supported. + +Only x86 and non-large code models are supported. + +[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mfunction-return +[GCC]: https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mfunction-return +[LLVM commit 2240d72f15f3]: https://github.com/llvm/llvm-project/commit/2240d72f15f3b7b9d9fb65450f9bf635fd310f6f diff --git a/src/doc/unstable-book/src/compiler-flags/llvm-module-flag.md b/src/doc/unstable-book/src/compiler-flags/llvm-module-flag.md new file mode 100644 index 000000000..454ad0a9a --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/llvm-module-flag.md @@ -0,0 +1,12 @@ +# `llvm-module-flag` + +--------------------- + +This flag allows adding a key/value to the `!llvm.module.flags` metadata in the +LLVM-IR for a compiled Rust module. The syntax is + +`-Z llvm_module_flag=<name>:<type>:<value>:<behavior>` + +Currently only u32 values are supported but the type is required to be specified +for forward compatibility. The `behavior` element must match one of the named +LLVM [metadata behaviors](https://llvm.org/docs/LangRef.html#module-flags-metadata) diff --git a/src/doc/unstable-book/src/compiler-flags/tls-model.md b/src/doc/unstable-book/src/compiler-flags/tls-model.md index 8b19e785c..b7024ba88 100644 --- a/src/doc/unstable-book/src/compiler-flags/tls-model.md +++ b/src/doc/unstable-book/src/compiler-flags/tls-model.md @@ -20,6 +20,8 @@ loaded at program startup. The TLS data must not be in a library loaded after startup (via `dlopen`). - `local-exec` - model usable only if the TLS data is defined directly in the executable, but not in a shared library, and is accessed only from that executable. +- `emulated` - Uses thread-specific data keys to implement emulated TLS. +It is like using a general-dynamic TLS model for all modes. `rustc` and LLVM may use a more optimized model than specified if they know that we are producing an executable rather than a library, or that the `static` item is private enough. diff --git a/src/doc/unstable-book/src/language-features/link-arg-attribute.md b/src/doc/unstable-book/src/language-features/link-arg-attribute.md new file mode 100644 index 000000000..09915a7f2 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/link-arg-attribute.md @@ -0,0 +1,21 @@ +# `link_arg_attribute` + +The tracking issue for this feature is: [#99427] + +------ + +The `link_arg_attribute` feature allows passing arguments into the linker +from inside of the source code. Order is preserved for link attributes as +they were defined on a single extern block: + +```rust,no_run +#![feature(link_arg_attribute)] + +#[link(kind = "link-arg", name = "--start-group")] +#[link(kind = "static", name = "c")] +#[link(kind = "static", name = "gcc")] +#[link(kind = "link-arg", name = "--end-group")] +extern "C" {} +``` + +[#99427]: https://github.com/rust-lang/rust/issues/99427 |