diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml index 76e1d0a8f7cf3..fe92bc876cf71 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml @@ -14,9 +14,9 @@ jobs: if: github.repository == 'rust-lang/rustc-dev-guide' runs-on: ubuntu-latest env: - MDBOOK_VERSION: 0.4.52 - MDBOOK_LINKCHECK2_VERSION: 0.9.1 - MDBOOK_MERMAID_VERSION: 0.12.6 + MDBOOK_VERSION: 0.5.1 + MDBOOK_LINKCHECK2_VERSION: 0.11.0 + MDBOOK_MERMAID_VERSION: 0.17.0 MDBOOK_OUTPUT__LINKCHECK__FOLLOW_WEB_LINKS: ${{ github.event_name != 'pull_request' }} DEPLOY_DIR: book/html BASE_SHA: ${{ github.event.pull_request.base.sha }} diff --git a/src/doc/rustc-dev-guide/README.md b/src/doc/rustc-dev-guide/README.md index 1ad895aeda2e1..fee7cf042e1f8 100644 --- a/src/doc/rustc-dev-guide/README.md +++ b/src/doc/rustc-dev-guide/README.md @@ -65,11 +65,6 @@ following example. ENABLE_LINKCHECK=1 mdbook serve ``` -### Table of Contents - -Each page has a TOC that is automatically generated by `pagetoc.js`. -There is an associated `pagetoc.css`, for styling. - ## Synchronizing josh subtree with rustc This repository is linked to `rust-lang/rust` as a [josh](https://josh-project.github.io/josh/intro.html) subtree. You can use the [rustc-josh-sync](https://github.com/rust-lang/josh-sync) tool to perform synchronization. diff --git a/src/doc/rustc-dev-guide/book.toml b/src/doc/rustc-dev-guide/book.toml index efb13101c8de2..15a597e5addbe 100644 --- a/src/doc/rustc-dev-guide/book.toml +++ b/src/doc/rustc-dev-guide/book.toml @@ -15,9 +15,7 @@ edit-url-template = "https://github.com/rust-lang/rustc-dev-guide/edit/main/{pat additional-js = [ "mermaid.min.js", "mermaid-init.js", - "pagetoc.js", ] -additional-css = ["pagetoc.css"] [output.html.search] use-boolean-and = true diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index b74dbbe56bfe6..7ace34aed984a 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -27,7 +27,7 @@ static REGEX_IGNORE_END: LazyLock = static REGEX_IGNORE_LINK_TARGETS: LazyLock = LazyLock::new(|| Regex::new(r"^\[.+\]: ").unwrap()); static REGEX_SPLIT: LazyLock = - LazyLock::new(|| Regex::new(r"([^\.\d\-\*]\.|[^r]\?|;|!)\s").unwrap()); + LazyLock::new(|| Regex::new(r"([^\.\d\-\*]\.|[^r]\?|!)\s").unwrap()); // list elements, numbered (1.) or not (- and *) static REGEX_LIST_ENTRY: LazyLock = LazyLock::new(|| Regex::new(r"^\s*(\d\.|\-|\*)\s+").unwrap()); @@ -196,7 +196,7 @@ fn lengthen_lines(content: &str, limit: usize) -> String { fn test_sembr() { let original = " # some. heading -must! be; split? +must! be. split? 1. ignore a dot after number. but no further ignore | tables ignore e.g. and @@ -214,7 +214,7 @@ git log main.. compiler let expected = " # some. heading must! -be; +be. split? 1. ignore a dot after number. but no further diff --git a/src/doc/rustc-dev-guide/pagetoc.css b/src/doc/rustc-dev-guide/pagetoc.css deleted file mode 100644 index fa709194f3755..0000000000000 --- a/src/doc/rustc-dev-guide/pagetoc.css +++ /dev/null @@ -1,84 +0,0 @@ -/* Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL) */ - -:root { - --toc-width: 270px; - --center-content-toc-shift: calc(-1 * var(--toc-width) / 2); -} - -.nav-chapters { - /* adjust width of buttons that bring to the previous or the next page */ - min-width: 50px; -} - -@media only screen { - @media (max-width: 1179px) { - .sidebar-hidden #sidetoc { - display: none; - } - } - - @media (max-width: 1439px) { - .sidebar-visible #sidetoc { - display: none; - } - } - - @media (1180px <= width <= 1439px) { - .sidebar-hidden main { - position: relative; - left: var(--center-content-toc-shift); - } - } - - @media (1440px <= width <= 1700px) { - .sidebar-visible main { - position: relative; - left: var(--center-content-toc-shift); - } - } - - #sidetoc { - margin-left: calc(100% + 20px); - } - #pagetoc { - position: fixed; - /* adjust TOC width */ - width: var(--toc-width); - height: calc(100vh - var(--menu-bar-height) - 0.67em * 4); - overflow: auto; - } - #pagetoc a { - border-left: 1px solid var(--sidebar-bg); - color: var(--fg); - display: block; - padding-bottom: 5px; - padding-top: 5px; - padding-left: 10px; - text-align: left; - text-decoration: none; - } - #pagetoc a:hover, - #pagetoc a.active { - background: var(--sidebar-bg); - color: var(--sidebar-active) !important; - } - #pagetoc .active { - background: var(--sidebar-bg); - color: var(--sidebar-active); - } - #pagetoc .pagetoc-H2 { - padding-left: 20px; - } - #pagetoc .pagetoc-H3 { - padding-left: 40px; - } - #pagetoc .pagetoc-H4 { - padding-left: 60px; - } -} - -@media print { - #sidetoc { - display: none; - } -} diff --git a/src/doc/rustc-dev-guide/pagetoc.js b/src/doc/rustc-dev-guide/pagetoc.js deleted file mode 100644 index 927a5b10749b5..0000000000000 --- a/src/doc/rustc-dev-guide/pagetoc.js +++ /dev/null @@ -1,104 +0,0 @@ -// Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL) - -let activeHref = location.href; -function updatePageToc(elem = undefined) { - let selectedPageTocElem = elem; - const pagetoc = document.getElementById("pagetoc"); - - function getRect(element) { - return element.getBoundingClientRect(); - } - - function overflowTop(container, element) { - return getRect(container).top - getRect(element).top; - } - - function overflowBottom(container, element) { - return getRect(container).bottom - getRect(element).bottom; - } - - // We've not selected a heading to highlight, and the URL needs updating - // so we need to find a heading based on the URL - if (selectedPageTocElem === undefined && location.href !== activeHref) { - activeHref = location.href; - for (const pageTocElement of pagetoc.children) { - if (pageTocElement.href === activeHref) { - selectedPageTocElem = pageTocElement; - } - } - } - - // We still don't have a selected heading, let's try and find the most - // suitable heading based on the scroll position - if (selectedPageTocElem === undefined) { - const margin = window.innerHeight / 3; - - const headers = document.getElementsByClassName("header"); - for (let i = 0; i < headers.length; i++) { - const header = headers[i]; - if (selectedPageTocElem === undefined && getRect(header).top >= 0) { - if (getRect(header).top < margin) { - selectedPageTocElem = header; - } else { - selectedPageTocElem = headers[Math.max(0, i - 1)]; - } - } - // a very long last section's heading is over the screen - if (selectedPageTocElem === undefined && i === headers.length - 1) { - selectedPageTocElem = header; - } - } - } - - // Remove the active flag from all pagetoc elements - for (const pageTocElement of pagetoc.children) { - pageTocElement.classList.remove("active"); - } - - // If we have a selected heading, set it to active and scroll to it - if (selectedPageTocElem !== undefined) { - for (const pageTocElement of pagetoc.children) { - if (selectedPageTocElem.href.localeCompare(pageTocElement.href) === 0) { - pageTocElement.classList.add("active"); - if (overflowTop(pagetoc, pageTocElement) > 0) { - pagetoc.scrollTop = pageTocElement.offsetTop; - } - if (overflowBottom(pagetoc, pageTocElement) < 0) { - pagetoc.scrollTop -= overflowBottom(pagetoc, pageTocElement); - } - } - } - } -} - -if (document.getElementById("sidetoc") === null && - document.getElementsByClassName("header").length > 0) { - // The sidetoc element doesn't exist yet, let's create it - - // Create the empty sidetoc and pagetoc elements - const sidetoc = document.createElement("div"); - const pagetoc = document.createElement("div"); - sidetoc.id = "sidetoc"; - pagetoc.id = "pagetoc"; - sidetoc.appendChild(pagetoc); - - // And append them to the current DOM - const main = document.querySelector('main'); - main.insertBefore(sidetoc, main.firstChild); - - // Populate sidebar on load - window.addEventListener("load", () => { - for (const header of document.getElementsByClassName("header")) { - const link = document.createElement("a"); - link.innerHTML = header.innerHTML; - link.href = header.hash; - link.classList.add("pagetoc-" + header.parentElement.tagName); - document.getElementById("pagetoc").appendChild(link); - link.onclick = () => updatePageToc(link); - } - updatePageToc(); - }); - - // Update page table of contents selected heading on scroll - window.addEventListener("scroll", () => updatePageToc()); -} diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 8c841aac8eb60..7a84872f266d1 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -cc328c12382f05d8ddf6ffc8139deb7985270ad8 +dfe1b8c97bcde283102f706d5dcdc3649e5e12e3 diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 249140956c09a..c136d37160c53 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -52,6 +52,7 @@ - [Mastering @rustbot](./rustbot.md) - [Walkthrough: a typical contribution](./walkthrough.md) - [Implementing new language features](./implementing_new_features.md) +- [Stability guarantees](./stability-guarantees.md) - [Stability attributes](./stability.md) - [Stabilizing language features](./stabilization_guide.md) - [Stabilization report template](./stabilization_report_template.md) @@ -185,14 +186,15 @@ - [Opaque types](./solve/opaque-types.md) - [Significant changes and quirks](./solve/significant-changes.md) - [`Unsize` and `CoerceUnsized` traits](./traits/unsize.md) -- [Type checking](./type-checking.md) - - [Method lookup](./method-lookup.md) - - [Variance](./variance.md) - - [Coherence checking](./coherence.md) - - [Opaque types](./opaque-types-type-alias-impl-trait.md) - - [Inference details](./opaque-types-impl-trait-inference.md) - - [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md) - - [Region inference restrictions][opaque-infer] +- [Variance](./variance.md) +- [Coherence checking](./coherence.md) +- [HIR Type checking](./hir-typeck/summary.md) + - [Coercions](./hir-typeck/coercions.md) + - [Method lookup](./hir-typeck/method-lookup.md) +- [Opaque types](./opaque-types-type-alias-impl-trait.md) + - [Inference details](./opaque-types-impl-trait-inference.md) + - [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md) + - [Region inference restrictions][opaque-infer] - [Const condition checking](./effects.md) - [Pattern and exhaustiveness checking](./pat-exhaustive-checking.md) - [Unsafety checking](./unsafety-checking.md) diff --git a/src/doc/rustc-dev-guide/src/appendix/bibliography.md b/src/doc/rustc-dev-guide/src/appendix/bibliography.md index 93426b645a61e..3729194f5fa1a 100644 --- a/src/doc/rustc-dev-guide/src/appendix/bibliography.md +++ b/src/doc/rustc-dev-guide/src/appendix/bibliography.md @@ -32,7 +32,7 @@ Rust, as well as publications about Rust. * [Scheduling techniques for concurrent systems](https://www.stanford.edu/~ouster/cgi-bin/papers/coscheduling.pdf) * [Singularity: rethinking the software stack](https://research.microsoft.com/pubs/69431/osr2007_rethinkingsoftwarestack.pdf) * [The data locality of work stealing](http://www.aladdin.cs.cmu.edu/papers/pdfs/y2000/locality_spaa00.pdf) -* [Thread scheduling for multiprogramming multiprocessors](https://www.eecis.udel.edu/%7Ecavazos/cisc879-spring2008/papers/arora98thread.pdf) +* [Thread scheduling for multiprogramming multiprocessors](https://dl.acm.org/doi/10.1145/277651.277678) * [Three layer cake for shared-memory programming](https://dl.acm.org/doi/10.1145/1953611.1953616) * [Work-first and help-first scheduling policies for async-finish task parallelism](https://dl.acm.org/doi/10.1109/IPDPS.2009.5161079) - More general than fully-strict work stealing diff --git a/src/doc/rustc-dev-guide/src/appendix/code-index.md b/src/doc/rustc-dev-guide/src/appendix/code-index.md index 0795d83b2e9ad..bf9d3bd465645 100644 --- a/src/doc/rustc-dev-guide/src/appendix/code-index.md +++ b/src/doc/rustc-dev-guide/src/appendix/code-index.md @@ -16,7 +16,6 @@ Item | Kind | Short description | Chapter | `HirId` | struct | One of four types of HIR node identifiers | [Identifiers in the HIR] | [compiler/rustc_hir_id/src/lib.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.HirId.html) `Lexer` | struct | This is the lexer used during parsing. It consumes characters from the raw source code being compiled and produces a series of tokens for use by the rest of the parser | [The parser] | [compiler/rustc_parse/src/lexer/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/lexer/struct.Lexer.html) `NodeId` | struct | One of four types of HIR node identifiers. Being phased out | [Identifiers in the HIR] | [compiler/rustc_ast/src/ast.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/node_id/struct.NodeId.html) -`P` | struct | An owned immutable smart pointer. By contrast, `&T` is not owned, and `Box` is not immutable. | None | [compiler/rustc_ast/src/ptr.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ptr/struct.P.html) `ParamEnv` | struct | Information about generic parameters or `Self`, useful for working with associated or generic items | [Parameter Environment] | [compiler/rustc_middle/src/ty/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html) `ParseSess` | struct | This struct contains information about a parsing session | [The parser] | [compiler/rustc_session/src/parse/parse.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/parse/struct.ParseSess.html) `Rib` | struct | Represents a single scope of names | [Name resolution] | [compiler/rustc_resolve/src/lib.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_resolve/late/struct.Rib.html) @@ -34,7 +33,7 @@ Item | Kind | Short description | Chapter | [Identifiers in the HIR]: ../hir.html#hir-id [The parser]: ../the-parser.html [The Rustc Driver and Interface]: ../rustc-driver/intro.html -[Type checking]: ../type-checking.html +[Type checking]: ../hir-typeck/summary.html [The `ty` modules]: ../ty.html [Rustdoc]: ../rustdoc.html [Emitting Diagnostics]: ../diagnostics.html diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index 21162f8ee7d08..901fb68c0513f 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -88,7 +88,7 @@ Term | Meaning trans | Short for _translation_, the code to translate MIR into LLVM IR. Renamed to [codegen](#codegen). `Ty` | The internal representation of a type. ([see more](../ty.md)) `TyCtxt` | The data structure often referred to as [`tcx`](#tcx) in code which provides access to session data and the query system. -UFCS | Short for _universal function call syntax_, this is an unambiguous syntax for calling a method. **Term no longer in use!** Prefer _fully-qualified path/syntax_. ([see more](../type-checking.md), [see the reference](https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls)) +UFCS | Short for _universal function call syntax_, this is an unambiguous syntax for calling a method. **Term no longer in use!** Prefer _fully-qualified path/syntax_. ([see more](../hir-typeck/summary.md), [see the reference](https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls)) uninhabited type | A type which has _no_ values. This is not the same as a ZST, which has exactly 1 value. An example of an uninhabited type is `enum Foo {}`, which has no variants, and so, can never be created. The compiler can treat code that deals with uninhabited types as dead code, since there is no such value to be manipulated. `!` (the never type) is an uninhabited type. Uninhabited types are also called _empty types_. upvar | A variable captured by a closure from outside the closure. variance | Determines how changes to a generic parameter affect subtyping; for example, if `T` is a subtype of `U`, then `Vec` is a subtype `Vec` because `Vec` is _covariant_ in its generic parameter. See [the background chapter](./background.md#variance) for a more general explanation. See the [variance chapter](../variance.md) for an explanation of how type checking handles variance. diff --git a/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md b/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md index aa1d644703a0c..4a0b75c694317 100644 --- a/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md +++ b/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md @@ -1,36 +1,40 @@ # Libraries and metadata When the compiler sees a reference to an external crate, it needs to load some -information about that crate. This chapter gives an overview of that process, +information about that crate. +This chapter gives an overview of that process, and the supported file formats for crate libraries. ## Libraries -A crate dependency can be loaded from an `rlib`, `dylib`, or `rmeta` file. A -key point of these file formats is that they contain `rustc`-specific -[*metadata*](#metadata). This metadata allows the compiler to discover enough +A crate dependency can be loaded from an `rlib`, `dylib`, or `rmeta` file. +A key point of these file formats is that they contain `rustc`-specific +[*metadata*](#metadata). +This metadata allows the compiler to discover enough information about the external crate to understand the items it contains, which macros it exports, and *much* more. ### rlib -An `rlib` is an [archive file], which is similar to a tar file. This file -format is specific to `rustc`, and may change over time. This file contains: +An `rlib` is an [archive file], which is similar to a tar file. +This file format is specific to `rustc`, and may change over time. +This file contains: -* Object code, which is the result of code generation. This is used during - regular linking. There is a separate `.o` file for each [codegen unit]. The - codegen step can be skipped with the [`-C - linker-plugin-lto`][linker-plugin-lto] CLI option, which means each `.o` - file will only contain LLVM bitcode. +* Object code, which is the result of code generation. + This is used during regular linking. + There is a separate `.o` file for each [codegen unit]. + The codegen step can be skipped with the [`-C linker-plugin-lto`][linker-plugin-lto] CLI option, + which means each `.o` file will only contain LLVM bitcode. * [LLVM bitcode], which is a binary representation of LLVM's intermediate - representation, which is embedded as a section in the `.o` files. This can - be used for [Link Time Optimization] (LTO). This can be removed with the + representation, which is embedded as a section in the `.o` files. + This can be used for [Link Time Optimization] (LTO). + This can be removed with the [`-C embed-bitcode=no`][embed-bitcode] CLI option to improve compile times and reduce disk space if LTO is not needed. * `rustc` [metadata], in a file named `lib.rmeta`. * A symbol table, which is essentially a list of symbols with offsets to the - object files that contain that symbol. This is pretty standard for archive - files. + object files that contain that symbol. + This is pretty standard for archive files. [archive file]: https://en.wikipedia.org/wiki/Ar_(Unix) [LLVM bitcode]: https://llvm.org/docs/BitCodeFormat.html @@ -41,46 +45,46 @@ format is specific to `rustc`, and may change over time. This file contains: ### dylib -A `dylib` is a platform-specific shared library. It includes the `rustc` -[metadata] in a special link section called `.rustc`. +A `dylib` is a platform-specific shared library. +It includes the `rustc` [metadata] in a special link section called `.rustc`. ### rmeta -An `rmeta` file is a custom binary format that contains the [metadata] for the -crate. This file can be used for fast "checks" of a project by skipping all code +An `rmeta` file is a custom binary format that contains the [metadata] for the crate. +This file can be used for fast "checks" of a project by skipping all code generation (as is done with `cargo check`), collecting enough information for documentation (as is done with `cargo doc`), or for [pipelining](#pipelining). This file is created if the [`--emit=metadata`][emit] CLI option is used. -`rmeta` files do not support linking, since they do not contain compiled -object files. +`rmeta` files do not support linking, since they do not contain compiled object files. [emit]: https://doc.rust-lang.org/rustc/command-line-arguments.html#option-emit ## Metadata -The metadata contains a wide swath of different elements. This guide will not go -into detail about every field it contains. You are encouraged to browse the +The metadata contains a wide swath of different elements. +This guide will not go into detail about every field it contains. +You are encouraged to browse the [`CrateRoot`] definition to get a sense of the different elements it contains. -Everything about metadata encoding and decoding is in the [`rustc_metadata`] -package. +Everything about metadata encoding and decoding is in the [`rustc_metadata`] package. Here are a few highlights of things it contains: -* The version of the `rustc` compiler. The compiler will refuse to load files - from any other version. -* The [Strict Version Hash](#strict-version-hash) (SVH). This helps ensure the - correct dependency is loaded. -* The [Stable Crate Id](#stable-crate-id). This is a hash used - to identify crates. -* Information about all the source files in the library. This can be used for - a variety of things, such as diagnostics pointing to sources in a +* The version of the `rustc` compiler. + The compiler will refuse to load files from any other version. +* The [Strict Version Hash](#strict-version-hash) (SVH). + This helps ensure the correct dependency is loaded. +* The [Stable Crate Id](#stable-crate-id). + This is a hash used to identify crates. +* Information about all the source files in the library. + This can be used for a variety of things, such as diagnostics pointing to sources in a dependency. -* Information about exported macros, traits, types, and items. Generally, - anything that's needed to be known when a path references something inside a - crate dependency. -* Encoded [MIR]. This is optional, and only encoded if needed for code - generation. `cargo check` skips this for performance reasons. +* Information about exported macros, traits, types, and items. + Generally, + anything that's needed to be known when a path references something inside a crate dependency. +* Encoded [MIR]. + This is optional, and only encoded if needed for code generation. + `cargo check` skips this for performance reasons. [`CrateRoot`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/rmeta/struct.CrateRoot.html [`rustc_metadata`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/index.html @@ -89,10 +93,10 @@ Here are a few highlights of things it contains: ### Strict Version Hash The Strict Version Hash ([SVH], also known as the "crate hash") is a 64-bit -hash that is used to ensure that the correct crate dependencies are loaded. It -is possible for a directory to contain multiple copies of the same dependency -built with different settings, or built from different sources. The crate -loader will skip any crates that have the wrong SVH. +hash that is used to ensure that the correct crate dependencies are loaded. +It is possible for a directory to contain multiple copies of the same dependency +built with different settings, or built from different sources. +The crate loader will skip any crates that have the wrong SVH. The SVH is also used for the [incremental compilation] session filename, though that usage is mostly historic. @@ -114,14 +118,15 @@ See [`compute_hir_hash`] for where the hash is actually computed. ### Stable Crate Id The [`StableCrateId`] is a 64-bit hash used to identify different crates with -potentially the same name. It is a hash of the crate name and all the -[`-C metadata`] CLI options computed in [`StableCrateId::new`]. It is -used in a variety of places, such as symbol name mangling, crate loading, and +potentially the same name. +It is a hash of the crate name and all the +[`-C metadata`] CLI options computed in [`StableCrateId::new`]. +It is used in a variety of places, such as symbol name mangling, crate loading, and much more. By default, all Rust symbols are mangled and incorporate the stable crate id. -This allows multiple versions of the same crate to be included together. Cargo -automatically generates `-C metadata` hashes based on a variety of factors, like +This allows multiple versions of the same crate to be included together. +Cargo automatically generates `-C metadata` hashes based on a variety of factors, like the package version, source, and target kind (a lib and test can have the same crate name, so they need to be disambiguated). @@ -131,33 +136,33 @@ crate name, so they need to be disambiguated). ## Crate loading -Crate loading can have quite a few subtle complexities. During [name -resolution], when an external crate is referenced (via an `extern crate` or -path), the resolver uses the [`CrateLoader`] which is responsible for finding -the crate libraries and loading the [metadata] for them. After the dependency -is loaded, the `CrateLoader` will provide the information the resolver needs +Crate loading can have quite a few subtle complexities. +During [name resolution], when an external crate is referenced (via an `extern crate` or +path), the resolver uses the [`CStore`] which is responsible for finding +the crate libraries and loading the [metadata] for them. +After the dependency is loaded, the `CStore` will provide the information the resolver needs to perform its job (such as expanding macros, resolving paths, etc.). -To load each external crate, the `CrateLoader` uses a [`CrateLocator`] to -actually find the correct files for one specific crate. There is some great -documentation in the [`locator`] module that goes into detail on how loading +To load each external crate, the `CStore` uses a [`CrateLocator`] to +actually find the correct files for one specific crate. +There is some great documentation in the [`locator`] module that goes into detail on how loading works, and I strongly suggest reading it to get the full picture. -The location of a dependency can come from several different places. Direct -dependencies are usually passed with `--extern` flags, and the loader can look -at those directly. Direct dependencies often have references to their own -dependencies, which need to be loaded, too. These are usually found by +The location of a dependency can come from several different places. +Direct dependencies are usually passed with `--extern` flags, and the loader can look +at those directly. +Direct dependencies often have references to their own dependencies, which need to be loaded, too. +These are usually found by scanning the directories passed with the `-L` flag for any file whose metadata -contains a matching crate name and [SVH](#strict-version-hash). The loader -will also look at the [sysroot] to find dependencies. +contains a matching crate name and [SVH](#strict-version-hash). +The loader will also look at the [sysroot] to find dependencies. As crates are loaded, they are kept in the [`CStore`] with the crate metadata -wrapped in the [`CrateMetadata`] struct. After resolution and expansion, the -`CStore` will make its way into the [`GlobalCtxt`] for the rest of the -compilation. +wrapped in the [`CrateMetadata`] struct. +After resolution and expansion, the +`CStore` will make its way into the [`GlobalCtxt`] for the rest of the compilation. [name resolution]: ../name-resolution.md -[`CrateLoader`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/creader/struct.CrateLoader.html [`CrateLocator`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/locator/struct.CrateLocator.html [`locator`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/locator/index.html [`CStore`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/creader/struct.CStore.html @@ -168,20 +173,21 @@ compilation. ## Pipelining One trick to improve compile times is to start building a crate as soon as the -metadata for its dependencies is available. For a library, there is no need to -wait for the code generation of dependencies to finish. Cargo implements this -technique by telling `rustc` to emit an [`rmeta`](#rmeta) file for each -dependency as well as an [`rlib`](#rlib). As early as it can, `rustc` will -save the `rmeta` file to disk before it continues to the code generation -phase. The compiler sends a JSON message to let the build tool know that it +metadata for its dependencies is available. +For a library, there is no need to wait for the code generation of dependencies to finish. +Cargo implements this technique by telling `rustc` to emit an [`rmeta`](#rmeta) file for each +dependency as well as an [`rlib`](#rlib). +As early as it can, `rustc` will +save the `rmeta` file to disk before it continues to the code generation phase. +The compiler sends a JSON message to let the build tool know that it can start building the next crate if possible. The [crate loading](#crate-loading) system is smart enough to know when it -sees an `rmeta` file to use that if the `rlib` is not there (or has only been -partially written). +sees an `rmeta` file to use that if the `rlib` is not there (or has only been partially written). This pipelining isn't possible for binaries, because the linking phase will -require the code generation of all its dependencies. In the future, it may be +require the code generation of all its dependencies. +In the future, it may be possible to further improve this scenario by splitting linking into a separate command (see [#64191]). 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 c924216b8cd30..d0a38b12c550f 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 @@ -277,18 +277,20 @@ default). Once you have successfully built `rustc`, you will have created a bunch of files in your `build` directory. In order to actually run the resulting `rustc`, we recommend creating rustup toolchains. The first -one will run the stage1 compiler (which we built above). The second -will execute the stage2 compiler (which we did not build, but which -you will likely need to build at some point; for example, if you want -to run the entire test suite). +command listed below creates the stage1 toolchain, which was built in the +steps above, with the name `stage1`. The second command creates the stage2 +toolchain using the stage1 compiler. This will be needed in the future +if running the entire test suite, but will not be built in this page. +Building stage2 is done with the same `./x build` command as for stage1, +specifying that the stage is 2 instead. ```bash rustup toolchain link stage1 build/host/stage1 rustup toolchain link stage2 build/host/stage2 ``` -Now you can run the `rustc` you built with. If you run with `-vV`, you -should see a version number ending in `-dev`, indicating a build from +Now you can run the `rustc` you built with via the toolchain. If you run with +`-vV`, you should see a version number ending in `-dev`, indicating a build from your local environment: ```bash diff --git a/src/doc/rustc-dev-guide/src/building/quickstart.md b/src/doc/rustc-dev-guide/src/building/quickstart.md index 97314d8036953..42058246cd05f 100644 --- a/src/doc/rustc-dev-guide/src/building/quickstart.md +++ b/src/doc/rustc-dev-guide/src/building/quickstart.md @@ -66,6 +66,6 @@ questions, [the full chapter](./how-to-build-and-run.md) might contain the answers, and if it doesn't, feel free to ask for help on [Zulip](https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp). -If you use VSCode, Vim, Emacs or Helix, `./x setup` will ask you if you want to +If you use VSCode, Vim, Emacs, Helix or Zed, `./x setup` will ask you if you want to set up the editor config. For more information, check out [suggested workflows](./suggested.md). diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 8c764c31dbfa3..40ad58e025c17 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -52,6 +52,7 @@ the CI to build and test their PR (e.g. when developing on a slow machine). Rust has strong backwards-compatibility guarantees. Thus, new features can't just be implemented directly in stable Rust. Instead, we have 3 release channels: stable, beta, and nightly. +See [The Rust Book] for more details on Rust’s train release model. - **Stable**: this is the latest stable release for general usage. - **Beta**: this is the next release (will be stable within 6 weeks). @@ -62,6 +63,8 @@ Instead, we have 3 release channels: stable, beta, and nightly. See [this chapter on implementing new features](./implementing_new_features.md) for more information. +[The Rust Book]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html + ### Breaking changes Breaking changes have a [dedicated section][Breaking Changes] in the dev-guide. @@ -465,7 +468,7 @@ Just a few things to keep in mind: #### ⚠️ Note: Where to contribute `rustc-dev-guide` changes For detailed information about where to contribute rustc-dev-guide changes and the benefits of doing so, -see [the rustc-dev-guide working group documentation]. +see [the rustc-dev-guide team documentation]. ## Issue triage @@ -482,7 +485,7 @@ Please see . [regression-]: https://github.com/rust-lang/rust/labels?q=regression [relnotes]: https://github.com/rust-lang/rust/labels/relnotes [S-tracking-]: https://github.com/rust-lang/rust/labels?q=s-tracking -[the rustc-dev-guide working group documentation]: https://forge.rust-lang.org/wg-rustc-dev-guide/index.html#where-to-contribute-rustc-dev-guide-changes +[the rustc-dev-guide team documentation]: https://forge.rust-lang.org/rustc-dev-guide/index.html#where-to-contribute-rustc-dev-guide-changes ### rfcbot labels diff --git a/src/doc/rustc-dev-guide/src/hir-typeck/coercions.md b/src/doc/rustc-dev-guide/src/hir-typeck/coercions.md new file mode 100644 index 0000000000000..158ac0885d323 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/hir-typeck/coercions.md @@ -0,0 +1,284 @@ +# Coercions + +Coercions are implicit operations which transform a value into a different type. A coercion *site* is a position where a coercion is able to be implicitly performed. There are two kinds of coercion sites: +- one-to-one +- LUB (Least-Upper-Bound) + +```rust +let one_to_one_coercion: &u32 = &mut 8; + +let lub_coercion = match my_bool { + true => &mut 10, + false => &12, +}; +``` + +See the Reference page on coercions for descriptions of what coercions exist and what expressions are coercion sites: + +## one-to-one coercions + +With a one-to-one coercion we coerce from one singular type to a known target type. In the above example this would be the coercion from `&mut u32` to `&u32`. + +A one-to-one coercion can be performed by calling [`FnCtxt::coerce`][fnctxt_coerce]. + +## LUB coercions + +With a LUB coercion we coerce a set of source types to some unknown target type. Unlike one-to-one coercions, a LUB coercion *produces* the target type that all of the source types coerce to. + +In the above example this would be the LUB coercion of both `&mut i32` and `&i32`, where we produce the target type `&i32`. + +The name "LUB coercion" (Least-Upper-Bound coercion) comes from how this coercion takes a set of types and computes the least coerced/subtyped type that both source types are coercable/subtypeable into. + +The general process for performing a LUB coercion is as follows: + +```rust ignore +// * 1 +let mut coerce = CoerceMany::new(intial_lub_ty); +for expr in exprs { + // * 2 + let expr_ty = fcx.check_expr_with_expectation(expr, expectation); + coerce.coerce(fcx, &cause, expr, expr_ty); +} +// * 3 +let final_ty = coerce.complete(fcx); +``` + +There are a few key steps here: +1. Creating the [`CoerceMany`][coerce_many] value and picking an initial lub +2. Typechecking each expression and registering its type as part of the LUB coercion +3. Completing the LUB coercion to get the resulting lubbed type + +### Step 1 + +First we create a [`CoerceMany`][coerce_many] value, this stores all of the state required for the LUB coercion. Unlike one-to-one coercions, a LUB coercion isn't a single function call as we want to intermix typechecking with advancing the LUB coercion. + +Creating a `CoerceMany` takes some `initial_lub` type. This is different from the *target* of the coercion which is an output of a LUB coercion rather than an input (unlike a one-to-one coercion). + +The initial lub ty should be derived from the [`Expectation`][expectation] for whatever expression this LUB coercion is for. It allows for inference constraints from computing the LUB coercion to propagate into the `Expectation`s used for type checking later expressions participating in the LUB coercion. + +See the ["unnecessary inference constraints"][unnecessary_inference_constraints] header for some more information about the effects this has. + +If there's no `Expectation` to use then some new infer var should be made for the initial lub ty. + +### Step 2 + +Next, for each expression participating in the LUB coercion, we typecheck it then invoke [`CoerceMany::coerce`][coerce_many_coerce] with its type. + +In some cases the expression participating in the LUB coercion doesn't actually exist in the HIR. For example when handling an operand-less `break` or `return` expression we need `()` to participate in the LUB coercion. + +In these cases the [`CoerceMany::coerce_forced_unit`][coerce_many_coerce_forced_unit] method can be used. + +The `CoerceMany::coerce` and `coerce_forced_unit` methods will both emit errors if the new type causes the LUB coercion to be unsatisfiable. In this case the final type of the LUB coercion will be an error type. + +### Step 3 + +Finally once all expressions have been coerced the final type of the LUB coercion can be obtained by calling [`CoerceMany::complete`][coerce_many_complete]. + +The resulting type of the LUB coercion is meaningfully different from the initial lub type passed in when constructing the [`CoerceMany`][coerce_many]. You should always take the resulting type of the LUB coercion and perform any necessary checks on it. + +## Implementation nuances + +### Adjustments + +When a coerce operation succeeds we record what kind of coercion it was, for example an unsize coercion or an autoderef etc. This is handled as part of the coerce operation by writing a list of *adjustments* into the in-progress [`TypeckResults`][typeck_results]. + +When building THIR we take the adjustments stored in the `TypeckResults` and make all of the coercion steps explicit. After this point in the compiler there isn't really a notion of coercions, only explicit casts and subtyping in the MIR. + +TODO: write and link to an adjustments chapter here + +### How does `CoerceMany` work + +[`CoerceMany`][coerce_many] works by repeatedly taking the current lub ty and some new source type, and computing a new lub ty which both types can coerce to. The core logic of taking a pair of types and computing some new third type can be found in [`try_find_coercion_lub`][try_find_coercion_lub]. + +```rust +fn foo() {} +fn bar() {} + +let a = match my_bool { + true => foo, + true if other_bool => foo, + false => bar, +} +``` + +In this example when type checking the `match` expression a LUB coercion is performed. This LUB coercion starts out with an initial lub ty of some inference variable `?x` due to the let statement having no known type. + +There are three expressions that participate in this LUB coercion. The first expression of a LUB coercion is special, instead of computing a new type with the existing initial lub ty, we coerce directly from the first expression to the initial lub ty. + +1. After type checking `true => foo,` we wind up with the type `FnDef(Foo)`. We then call [`CoerceMany::coerce`][coerce_many_coerce] which will perform a one-to-one coercion of `FnDef(Foo)` to `?x`. This infers `?x=FnDef(Foo)` giving us a new lub ty for the LUB coercion. +2. After type checking `true if other_bool => foo,` we once again wind up with the type `FnDef(Foo)`. We'll then call `CoerceMany::coerce` which will attempt to compute a new lub ty from our previous lub ty (`FnDef(Foo)`) and the type of this expression (`FnDef(Foo)`). This gives us a lub ty of `FnDef(Foo)`. +3. After type checking `false => bar,` we'll wind up with the type `FnDef(Bar)`. We'll then call `CoerceMany::coerce` which will attempt to compute a new lub ty from our previous lub ty (`FnDef(Foo)`) and the type of this expression (`FnDef(Bar)`). In this case we get the type `fn() -> ()` as we choose to coerce both function item types to a function pointer. + +This gives us a final type for the LUB coercion of `fn() -> ()`. + +### Transitive coercions + +[`CoerceMany`][coerce_many]'s algorithm of repeatedly attempting to coerce the currrent target type to the new type currently results in "Transitive Coercions". It's possible for a step in a LUB coercion to coerce an expression, and then a later step to coerce that expression further. + +```rust +struct Foo; + +use std::ops::Deref; + +impl Deref for Foo { + type Target = [u8; 2]; + + fn deref(&self) -> &[u8; 2] { + &[1; _] + } +} + +fn main() { + match () { + _ if true => &Foo, + _ if true => &[1_u8; 2], + _ => &[1_u8; 2] as &[u8], + }; +} +``` + +Here we have a LUB coercion with an initial lub ty of `?x`. In the first step we do a one-to-one coercion of `&Foo` to `?x` (reminder the first step is special). + +In the second step we compute a new lub ty from the current lub ty of `&Foo` and the new type of `&[u8; 2]`. This new lub ty would be `&[u8; 2]` by performing a deref coercion of `&Foo` to `&[u8; 2]` on the first expression. + +In the third step we compute a new lub ty from the current lub ty of `&[u8; 2]` and the new type of `&[u8]`. This new lub ty would be `&[u8]` by performing an unsizing coercion of `&[u8; 2]` to `&[u8]` on the first two expressions. + +Note how the first expression is coerced twice. Once a deref coercion from `&Foo` to `&[u8; 2]`, and then an unsizing coercion from `&[u8; 2]` to `&[u8]`. + +The current implementation of transitive coercions is broken, the previous example actually ICEs on stable. While the logic for performing a LUB coercion can produce transitive coercions just fine, the rest of the compiler is not set up to handle them. + +One-to-one coercions are also not capable of producing a lot of the kinds of transitive coercions that LUB coercions can. For example if we take the previous example and turn it into a one-to-one coercion we get a compile error: +```rust +struct Foo; + +use std::ops::Deref; + +impl Deref for Foo { + type Target = [u8; 2]; + + fn deref(&self) -> &[u8; 2] { + &[1; _] + } +} + +fn main() { + let a: &[u8] = &Foo; +} +``` + +Here we try to perform a one-to-one coercion from `&Foo` to `&[u8]` which fails as we can only perform a deref coercion *or* an unsizing coercion, we can't compose the two. + +### How does `try_find_coercion_lub` work + +There are three ways that we can compute a new lub ty for a LUB coercion: +1. Coerce both the current lub ty and the new type to a function pointer +2. Coerce the current lub ty to the new type (or vice versa) +3. Compute a mutual supertype of the current lub ty and the new type + +Unfortunately the actual implementation obsfucates this a fair amount. + +Computing a mutual supertype happens implicitly due to reusing the logic for one-to-one coercions which already handles subtyping if coercing fails. + +Additionally when trying to coerce both the current lub ty and the new type to function pointers we eagerly try to compute a mutual supertype to avoid unnecessary coercions. + +There is likely room for improving the structure of this function to make it more closely align with the conceptual model. + +### `use_lub` field in one-to-one coercions + +The implementation of one-to-one coercions is reused as part of LUB coercions. + +It would be wrong for LUB coercions to use one way subtyping when relating signatures or falling back to subtyping in the case of no coercions being possible. Instead we want to compute a mutual supertype of the two types. + +The `use_lub` field on [`Coerce`][coerce_ty] exists to toggle whether to perform normal subtyping (in the case of a one-to-one coercion), or whether to compute a mutual supertype (in the case of a LUB coercion). + +### Lubbing + +In theory computing a mutual supertype should be as simple as creating some new infer var `?mutual_sup` and then requiring `lub_ty <: ?mutual_sup` and `new_ty <: ?mutual_sup`. In reality LUB coercions use a special [`TypeRelation`][type_relation], [`LatticeOp`][lattice_op]. + +This is primarily to work around subtyping/generalization for higher ranked types being fairly broken. Unlike normal subtyping, when encountering higher ranked types the lub type relation will switch to invariance. + +This enforces that the binders of the higher ranked types are equivalent which avoids the need to pick a "most general" binder, which would be quite difficult to do. + +It also avoids the process of computing a mutual supertype being *order dependent*. Given the types `a` and `b`, it may be nice if computing the mutual supertype of `a` and `b` would yield the same result as computing the mutual supertype of `b` and `a`. + +The current issues with higher ranked types and subtyping would cause this property to not hold if we were to use the naive method of computing a mutual supertype. + +Coercions being turned into explicit MIR operations during MIR building means that the process of computing the final type of a LUB coercion only occurs during HIR typeck. This also means the behaviour of computing a mutual supertype only matters for type inference, and is not soundness relevant. + +## Cautionary notes + +### Probes + +Care should be taken when coercing from inside of a probe as both one-to-one coercions and LUB coercions have side effects that can't be rolled back by a probe. + +LUB coercions will emit error when a coercion step fails, this makes it entirely suitable for use inside of probes. + +1-to-1 and LUB coercions will both apply *adjustments* to the coerced expressions on success. This means that if inside of a probe and an attempt to coerce succeeds, then the probe must not rollback anything. + +It's therefore correct to wrap a [`FnCtxt::coerce`][fnctxt_coerce] call inside of a [`commit_if_ok`][commit_if_ok], but would be wrong to do so if returning `Err` after the coerce call. It would also be wrong to call `FnCtxt::coerce` from within a [`probe`][probe]. + +[`CoerceMany`][coerce_many] should never be used from within a `probe` or `commit_if_ok`. + +### Never-to-Any coercions + +Coercing from the never type (`!`) to an inference variable will result in a [`NeverToAny`][never_to_any] coercion with a target type of the inference variable. This is subtly different from *unifying* the inference variable with the never type. + +Unifying some infer var `?x` with `!` requires that `?x` actually be *equal* to `!`. However, a `NeverToAny` coercion allows for `?x` to be inferred to any possible type. + +This distinction means that in cases where the initial lub ty of a coercion is an inference variable (e.g. there's no [`Expectation`][expectation] to use for the initial lub ty), it's still important to use a coercion instead of subtyping. + +See PR [#147834](https://github.com/rust-lang/rust/pull/147834) which fixes a bug where we were incorrectly inferring things to the never type instead of going through a coercion. + +### Fallback to subtyping + +Even though subtyping is not a coercion, both [`FnCtxt::coerce`][fnctxt_coerce] and [`CoerceMany::coerce`][coerce_many_coerce]/[`coerce_forced_unit`][coerce_many_coerce_forced_unit] are able to succeed due to subtyping. + +For one-to-one coercions we will try to enforce the source type is a subtype of the target type. For LUB coercions we will try to compute a type that is a supertype of all the existing types. + +For example performing a one-to-one coercion of `?x` to `u32` will fallback to subtyping, inferring `?x eq u32`. This means that when a coercion fails there's no need to attempt subtyping afterwards. + +### Unnecessary inference constraints + +Using types from [`Expectation`][expectation]s as the initial lub ty can cause infer vars to be constrained by the types of the expressions participating in the LUB coercion. This is not always desirable as these infer vars actually only need to be constrained by the final type of the LUB coercion. + +```rust +fn foo(_: T) {} + +fn a() {} +fn b() {} + +foo::(match my_bool { + true => a, + false => b, +}) +``` + +Here we have a LUB coercion with the first expression being of type `FnDef(a)` and the second expression being of type `FnDef(b)`. If we use `?x` as the initial lub ty of the LUB coercion then we would get the following behaviour: +- expression 1: infer `?x=FnDef(a)` +- expression 2: find a coercion lub between `FnDef(a), FnDef(b)` resulting in `fn() -> ()` +- the final type of the LUB coercion is `fn() -> ()`. equate `?x eq fn() -> ()`, where `?x` actually already has been inferred to `FnDef(a)`, so this is actually equating `FnDef(a) eq fn() -> ()` which does not hold + +To avoid some (but not all) of these undesirable inference constraints, if the `Expectation` for the LUB coercion is an inference variable then we won't use it as the initial lub ty. Instead we create a new infer var, for example in the above code snippet we would actually make some new infer var `?y` for the initial lub ty instead of using `?x`. +- expression 1: infer `?y=FnDef(a)` +- expression 2: find a coercion lub between `FnDef(a), FnDef(b)` resulting in `fn() -> ()` +- the final type of the LUB coercion is `fn() -> ()`, infer `?x=fn() -> ()` + +See [#140283](https://github.com/rust-lang/rust/pull/140283) for a case where we had undesirable inference constraints caused by not creating a new infer var. + +This doesn't avoid unnecessary constraints in *all* cases, only the most common case of having an infer var as our `Expectation`. In theory it would be desirable to avoid these constraints in all cases but it would be quite involved to do so. + +[coerce_many]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/coercion/struct.CoerceMany.html +[coerce_many_coerce]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/coercion/struct.CoerceMany.html#method.coerce +[coerce_many_coerce_forced_unit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/coercion/struct.CoerceMany.html#method.coerce_forced_unit +[coerce_many_complete]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/coercion/struct.CoerceMany.html#method.complete +[try_find_coercion_lub]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#method.try_find_coercion_lub +[expectation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/expectation/enum.Expectation.html +[unnecessary_inference_constraints]: #unnecessary-inference-constraints +[typeck_results]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html +[type_relation]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/canonical/ir/relate/trait.TypeRelation.html +[lattice_op]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/relate/lattice/struct.LatticeOp.html +[fnctxt_coerce]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#method.coerce +[coerce_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/coercion/struct.Coerce.html +[commit_if_ok]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.commit_if_ok +[probe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.probe +[never_to_any]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adjustment/enum.Adjust.html#variant.NeverToAny diff --git a/src/doc/rustc-dev-guide/src/method-lookup.md b/src/doc/rustc-dev-guide/src/hir-typeck/method-lookup.md similarity index 100% rename from src/doc/rustc-dev-guide/src/method-lookup.md rename to src/doc/rustc-dev-guide/src/hir-typeck/method-lookup.md diff --git a/src/doc/rustc-dev-guide/src/type-checking.md b/src/doc/rustc-dev-guide/src/hir-typeck/summary.md similarity index 94% rename from src/doc/rustc-dev-guide/src/type-checking.md rename to src/doc/rustc-dev-guide/src/hir-typeck/summary.md index 4e8b30b19fc7b..23df97a9cf833 100644 --- a/src/doc/rustc-dev-guide/src/type-checking.md +++ b/src/doc/rustc-dev-guide/src/hir-typeck/summary.md @@ -1,4 +1,4 @@ -# Type checking +# HIR Type checking The [`hir_analysis`] crate contains the source for "type collection" as well as a bunch of related functionality. @@ -7,8 +7,8 @@ These crates draw heavily on the [type inference] and [trait solving]. [`hir_analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/index.html [`hir_typeck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/index.html -[type inference]: ./type-inference.md -[trait solving]: ./traits/resolution.md +[type inference]: ./../type-inference.md +[trait solving]: ./../traits/resolution.md ## Type collection @@ -40,7 +40,7 @@ type *checking*). For more details, see the [`collect`][collect] module. -[queries]: ./query.md +[queries]: ../query.md [collect]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/index.html **TODO**: actually talk about type checking... [#1161](https://github.com/rust-lang/rustc-dev-guide/issues/1161) 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 30a1c5ebc7ef4..d71e51d5f61bf 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -84,11 +84,11 @@ Note that when building `rustc`, `profiler_builtins` is only included when `build.profiler = true` is set in `bootstrap.toml`. When compiling with `-C instrument-coverage`, -[`CrateLoader::postprocess()`][crate-loader-postprocess] dynamically loads +[`CStore::postprocess()`][crate-loader-postprocess] dynamically loads `profiler_builtins` by calling `inject_profiler_runtime()`. [compiler-rt-profile]: https://github.com/llvm/llvm-project/tree/main/compiler-rt/lib/profile -[crate-loader-postprocess]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/creader/struct.CrateLoader.html#method.postprocess +[crate-loader-postprocess]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/creader/struct.CStore.html#method.postprocess ## Testing coverage instrumentation diff --git a/src/doc/rustc-dev-guide/src/mir/drop-elaboration.md b/src/doc/rustc-dev-guide/src/mir/drop-elaboration.md index 93e21e2b227fc..7ef60f4cca00b 100644 --- a/src/doc/rustc-dev-guide/src/mir/drop-elaboration.md +++ b/src/doc/rustc-dev-guide/src/mir/drop-elaboration.md @@ -188,6 +188,6 @@ known to be uninitialized) to run these checks. [RFC 320]: https://rust-lang.github.io/rfcs/0320-nonzeroing-dynamic-drop.html [reference-drop]: https://doc.rust-lang.org/reference/destructors.html -[drops]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +[drops]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_mir_transform/src/elaborate_drops.rs [drops-shim]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_mir_transform/src/shim.rs [drops-transform]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_mir_transform/src/elaborate_drops.rs diff --git a/src/doc/rustc-dev-guide/src/offload/internals.md b/src/doc/rustc-dev-guide/src/offload/internals.md index 28857a6e78bff..77a4cadbcb986 100644 --- a/src/doc/rustc-dev-guide/src/offload/internals.md +++ b/src/doc/rustc-dev-guide/src/offload/internals.md @@ -7,3 +7,10 @@ also offer more advanced, possibly unsafe, interfaces which allow a higher degre The implementation is based on LLVM's "offload" project, which is already used by OpenMP to run Fortran or C++ code on GPUs. While the project is under development, users will need to call other compilers like clang to finish the compilation process. + +## High-level design: +We use a single-source, two-pass compilation approach. + +First we compile all functions that should be offloaded for the device (e.g nvptx64, amdgcn-amd-amdhsa, intel in the future). Currently we require cumbersome `#cfg(target_os="")` annotations, but we intend to recognize those in the future based on our offload intrinsic. + +We then compile the code for the host (e.g. x86-64), where most of the offloading logic happens. On the host side, we generate calls to the openmp offload runtime, to inform it about the layout of the types (a simplified version of the autodiff TypeTrees). We also use the type system to figure out whether kernel arguments have to be moved only to the device (e.g. `&[f32;1024]`), from the device, or both (e.g. `&mut [f64]`). We then launched the kernel, after which we inform the runtime to end this environment and move data back (as far as needed). diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md index f83b5b2e181c8..23cc94d41846d 100644 --- a/src/doc/rustc-dev-guide/src/overview.md +++ b/src/doc/rustc-dev-guide/src/overview.md @@ -130,7 +130,7 @@ with additional low-level types and annotations added (e.g. an ELF object or the final binary. [*trait solving*]: traits/resolution.md -[*type checking*]: type-checking.md +[*type checking*]: hir-typeck/summary.md [*type inference*]: type-inference.md [`bump`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html#method.bump [`check`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html#method.check diff --git a/src/doc/rustc-dev-guide/src/stability-guarantees.md b/src/doc/rustc-dev-guide/src/stability-guarantees.md new file mode 100644 index 0000000000000..21c4f3594d84e --- /dev/null +++ b/src/doc/rustc-dev-guide/src/stability-guarantees.md @@ -0,0 +1,26 @@ +# Stability guarantees + +This page gives an overview of our stability guarantees. + +## RFCs + +* [RFC 1105 api evolution](https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md) +* [RFC 1122 language semver](https://github.com/rust-lang/rfcs/blob/master/text/1122-language-semver.md) + +## Blog posts + +* [Stability as a Deliverable](https://blog.rust-lang.org/2014/10/30/Stability/) + +## rustc-dev-guide links + +* [Stabilizing library features](./stability.md) +* [Stabilizing language features](./stabilization_guide.md) +* [What qualifies as a bug fix?](./bug-fix-procedure.md#what-qualifies-as-a-bug-fix) + +## Exemptions + +Even if some of our infrastructure can be used by others, it is still considered +internal and comes without stability guarantees. This is a non-exhaustive list +of components without stability guarantees: + +* The CLIs and environment variables used by `remote-test-client` / `remote-test-server` diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index c2aee82bdd744..a691380234cd1 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -187,8 +187,26 @@ still pass. cause an Internal Compiler Error (ICE). This is a highly specialized directive to check that the incremental cache continues to work after an ICE. -[`tests/incremental`]: https://github.com/rust-lang/rust/tree/HEAD/tests/incremental - +Incremental tests may use the attribute `#[rustc_clean(...)]` attribute. This attribute compares +the fingerprint from the current compilation session with the previous one. +The first revision should never have an active `rustc_clean` attribute, since it will always be dirty. + +In the default mode, it asserts that the fingerprints must be the same. +The attribute takes the following arguments: + +* `cfg=""` — checks the cfg condition ``, and only runs the check if the config condition evaluates to true. + This can be used to only run the `rustc_clean` attribute in a specific revision. +* `except=",,..."` — asserts that the query results for the listed queries must be different, + rather than the same. +* `loaded_from_disk=",,..."` — asserts that the query results for the listed queries + were actually loaded from disk (not just marked green). + This can be useful to ensure that a test is actually exercising the deserialization + logic for a particular query result. This can be combined with `except`. + +A simple example of a test using `rustc_clean` is the [hello_world test]. + +[`tests/incremental`]: https://github.com/rust-lang/rust/tree/7b42543/tests/incremental +[hello_world test]: https://github.com/rust-lang/rust/blob/646a3f8c15baefb98dc6e0c1c1ba3356db702d2a/tests/incremental/hello_world.rs ### Debuginfo tests diff --git a/src/doc/rustc-dev-guide/src/tests/crater.md b/src/doc/rustc-dev-guide/src/tests/crater.md index 96bb5a4f2ae67..beea10aab7706 100644 --- a/src/doc/rustc-dev-guide/src/tests/crater.md +++ b/src/doc/rustc-dev-guide/src/tests/crater.md @@ -1,43 +1,45 @@ # Crater [Crater](https://github.com/rust-lang/crater) is a tool for compiling and -running tests for _every_ crate on [crates.io](https://crates.io) (and a few on -GitHub). It is mainly used for checking the extent of breakage when implementing +running tests for _every_ crate on [crates.io](https://crates.io) (and a few on GitHub). +It is mainly used for checking the extent of breakage when implementing potentially breaking changes and ensuring lack of breakage by running beta vs stable compiler versions. ## When to run Crater You should request a Crater run if your PR makes large changes to the compiler -or could cause breakage. If you are unsure, feel free to ask your PR's reviewer. +or could cause breakage. +If you are unsure, feel free to ask your PR's reviewer. ## Requesting Crater Runs The Rust team maintains a few machines that can be used for Crater runs -on the changes introduced by a PR. If your PR needs a Crater run, leave a -comment for the triage team in the PR thread. Please inform the team whether you -require a "check-only" Crater run, a "build only" Crater run, or a -"build-and-test" Crater run. The difference is primarily in time; -if you're not sure, go for the build-and-test run. If -making changes that will only have an effect at compile-time (e.g., implementing -a new trait), then you only need a check run. - -Your PR will be enqueued by the triage team and the results will be posted when -they are ready. Check runs will take around ~3-4 days, and the other two taking -5-6 days on average. - -While Crater is really useful, it is also important to be aware of a few -caveats: - -- Not all code is on crates.io! There is a lot of code in repos on GitHub and - elsewhere. Also, companies may not wish to publish their code. Thus, a - successful Crater run does not mean there will be no +on the changes introduced by a PR. +If your PR needs a Crater run, leave a comment for the triage team in the PR thread. +Please inform the team whether you +require a "check-only" Crater run, a "build only" Crater run, or a "build-and-test" Crater run. +The difference is primarily in time; +if you're not sure, go for the build-and-test run. +If making changes that will only have an effect at compile-time +(e.g., implementing a new trait), then you only need a check run. + +Your PR will be enqueued by the triage team and the results will be posted when they are ready. +Check runs will take around ~3-4 days, and the other two taking 5-6 days on average. + +While Crater is really useful, it is also important to be aware of a few caveats: + +- Not all code is on crates.io! + There is a lot of code in repos on GitHub and elsewhere. + Also, companies may not wish to publish their code. + Thus, a successful Crater run does not mean there will be no breakage; you still need to be careful. -- Crater only runs Linux builds on x86_64. Thus, other architectures and - platforms are not tested. Critically, this includes Windows. +- Crater only runs Linux builds on x86_64. Thus, other architectures and platforms are not tested. + Critically, this includes Windows. -- Many crates are not tested. This could be for a lot of reasons, including that +- Many crates are not tested. + This could be for a lot of reasons, including that the crate doesn't compile any more (e.g. used old nightly features), has broken or flaky tests, requires network access, or other reasons. diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 4226c1750ef2c..7cf5869b719cc 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -273,7 +273,9 @@ This affects which edition is used by `./x test` to run the test. For example: - A test with the `//@ edition: 2018` directive will only run under the 2018 edition. -- A test with the `//@ edition: 2015..2021` directive can be run under the 2015, 2018, and 2021 editions. +- A test with the `//@ edition: 2015..2021` directive can be run under the 2015 and the 2018 edition, + so the upper bound is exclusive just like in Rust + (note that there's no equivalent to Rust's `..=` where the upper bound is inclusive). However, CI will only run the test with the lowest edition in the range (which is 2015 in this example). - A test with the `//@ edition: 2018..` directive will run under 2018 edition or greater. However, CI will only run the test with the lowest edition in the range (which is 2018 in this example). diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 497e6109446ef..759029e671322 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -12,7 +12,7 @@ the resulting program](#controlling-passfail-expectations) to verify its behavior. For a survey of each subdirectory's purpose under `tests/ui`, consult the -[SUMMARY.md](https://github.com/rust-lang/rust/tree/HEAD/tests/ui/SUMMARY.md). +[README.md](https://github.com/rust-lang/rust/tree/HEAD/tests/ui/README.md). This is useful if you write a new test, and are looking for a category to place it in. diff --git a/src/doc/rustc-dev-guide/src/thir.md b/src/doc/rustc-dev-guide/src/thir.md index 3d3dafaef49ba..d5f7d8b5fcb70 100644 --- a/src/doc/rustc-dev-guide/src/thir.md +++ b/src/doc/rustc-dev-guide/src/thir.md @@ -5,7 +5,7 @@ The THIR ("Typed High-Level Intermediate Representation"), previously called HAI [type checking]. It is (as of January 2024) used for [MIR construction], [exhaustiveness checking], and [unsafety checking]. -[type checking]: ./type-checking.md +[type checking]: ./hir-typeck/summary.md [MIR construction]: ./mir/construction.md [exhaustiveness checking]: ./pat-exhaustive-checking.md [unsafety checking]: ./unsafety-checking.md diff --git a/src/doc/rustc-dev-guide/src/traits/canonical-queries.md b/src/doc/rustc-dev-guide/src/traits/canonical-queries.md index 792858bd2af8e..389f380e4b8de 100644 --- a/src/doc/rustc-dev-guide/src/traits/canonical-queries.md +++ b/src/doc/rustc-dev-guide/src/traits/canonical-queries.md @@ -214,7 +214,7 @@ As a result of this assignment, the type of `u` is forced to be `Option>`, where `?V` represents the element type of the vector. This in turn implies that `?U` is [unified] to `Vec`. -[unified]: ../type-checking.html +[unified]: ../hir-typeck/summary.md Let's suppose that the type checker decides to revisit the "as-yet-unproven" trait obligation we saw before, `Vec: