├── CNAME ├── mermaid-init.js ├── src ├── img │ ├── github-cli.png │ ├── wpa-stack.png │ ├── llvm-cov-show-01.png │ ├── rustbot-submodules.png │ ├── wpa-initial-memory.png │ ├── submodule-conflicts.png │ ├── other-peoples-commits.png │ ├── dataflow-graphviz-example.png │ ├── github-whitespace-changes.png │ └── coverage-branch-counting-01.png ├── queries │ ├── example-0.png │ └── example-0.counts.txt ├── feature-gate-ck.md ├── borrow_check │ ├── region_inference │ │ ├── error_reporting.md │ │ └── closure_constraints.md │ ├── moves_and_initialization.md │ ├── type_check.md │ └── two_phase_borrows.md ├── backend │ ├── inline-asm.md │ ├── lowering-mir.md │ └── codegen.md ├── mir │ ├── mir_overview.dot │ ├── mir_detailed.dot │ ├── visitor.md │ └── debugging.md ├── generic_parameters_summary.md ├── part-3-intro.md ├── syntax-intro.md ├── hir-debugging.md ├── part-4-intro.md ├── part-2-intro.md ├── rustc-driver-getting-diagnostics.md ├── rustc-driver-interacting-with-the-ast.md ├── notification-groups │ ├── arm.md │ ├── risc-v.md │ ├── rust-for-linux.md │ ├── llvm.md │ ├── windows.md │ ├── apple.md │ ├── about.md │ └── cleanup-crew.md ├── crates-io.md ├── building │ ├── build-install-distribution-artifacts.md │ ├── bootstrapping │ │ ├── intro.md │ │ └── how-bootstrap-does-it.md │ ├── compiler-documenting.md │ ├── prerequisites.md │ └── quickstart.md ├── appendix │ ├── humorust.md │ └── compiler-lecture.md ├── param_env │ ├── param_env_summary.md │ ├── param_env_what_is_it.md │ └── param_env_construction_internals.md ├── ast-validation.md ├── what_is_ty_generics.md ├── cli.md ├── diagnostics │ ├── error-guaranteed.md │ └── error-codes.md ├── early-late-bound-params │ └── early-late-bound-summary.md ├── traits │ ├── chalk.md │ ├── specialization.md │ ├── caching.md │ └── unsize.md ├── opaque-types-type-alias-impl-trait.md ├── type-checking.md ├── licenses.md ├── tests │ ├── crater.md │ ├── perf.md │ ├── suggest-tests.md │ ├── docker.md │ └── ci.md ├── solve │ ├── proof-trees.md │ ├── trait-solving.md │ ├── the-solver.md │ └── canonicalization.md ├── ast-lowering.md ├── feature-gates.md ├── part-5-intro.md ├── const-eval.md ├── rustc-driver.md ├── borrow_check.md ├── lang-items.md ├── rustbot.md ├── unsafety-checking.md ├── constants.md ├── effects.md ├── the-parser.md └── ty_module │ └── binders.md ├── .gitignore ├── triagebot.toml ├── CODE_OF_CONDUCT.md ├── .editorconfig ├── .mailmap ├── examples ├── README ├── rustc-driver-getting-diagnostics.rs ├── rustc-driver-interacting-with-the-ast.rs └── rustc-driver-example.rs ├── .gitattributes ├── ci ├── date-check │ ├── Cargo.toml │ └── Cargo.lock ├── linkcheck.sh └── check-in.sh ├── CITATION.cff ├── LICENSE-MIT ├── book.toml ├── .github └── workflows │ ├── date-check.yml │ └── ci.yml └── README.md /CNAME: -------------------------------------------------------------------------------- 1 | rustc-dev-guide.rust-lang.org 2 | -------------------------------------------------------------------------------- /mermaid-init.js: -------------------------------------------------------------------------------- 1 | mermaid.initialize({startOnLoad:true}); 2 | -------------------------------------------------------------------------------- /src/img/github-cli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikdesjardins/rustc-dev-guide/master/src/img/github-cli.png -------------------------------------------------------------------------------- /src/img/wpa-stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikdesjardins/rustc-dev-guide/master/src/img/wpa-stack.png -------------------------------------------------------------------------------- /src/queries/example-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikdesjardins/rustc-dev-guide/master/src/queries/example-0.png -------------------------------------------------------------------------------- /src/img/llvm-cov-show-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikdesjardins/rustc-dev-guide/master/src/img/llvm-cov-show-01.png -------------------------------------------------------------------------------- /src/img/rustbot-submodules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikdesjardins/rustc-dev-guide/master/src/img/rustbot-submodules.png -------------------------------------------------------------------------------- /src/img/wpa-initial-memory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikdesjardins/rustc-dev-guide/master/src/img/wpa-initial-memory.png -------------------------------------------------------------------------------- /src/img/submodule-conflicts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikdesjardins/rustc-dev-guide/master/src/img/submodule-conflicts.png -------------------------------------------------------------------------------- /src/img/other-peoples-commits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikdesjardins/rustc-dev-guide/master/src/img/other-peoples-commits.png -------------------------------------------------------------------------------- /src/img/dataflow-graphviz-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikdesjardins/rustc-dev-guide/master/src/img/dataflow-graphviz-example.png -------------------------------------------------------------------------------- /src/img/github-whitespace-changes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikdesjardins/rustc-dev-guide/master/src/img/github-whitespace-changes.png -------------------------------------------------------------------------------- /src/feature-gate-ck.md: -------------------------------------------------------------------------------- 1 | # Feature Gate Checking 2 | 3 | **TODO**: this chapter [#1158](https://github.com/rust-lang/rustc-dev-guide/issues/1158) 4 | -------------------------------------------------------------------------------- /src/img/coverage-branch-counting-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/erikdesjardins/rustc-dev-guide/master/src/img/coverage-branch-counting-01.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | 3 | # prevent accidental changes 4 | book.toml 5 | 6 | ci/date-check/target/ 7 | 8 | # Generated by check-in.sh 9 | pulls.json 10 | -------------------------------------------------------------------------------- /triagebot.toml: -------------------------------------------------------------------------------- 1 | [assign] 2 | 3 | [relabel] 4 | allow-unauthenticated = [ 5 | "waiting-on-review", 6 | "waiting-on-author", 7 | "blocked", 8 | ] 9 | -------------------------------------------------------------------------------- /src/borrow_check/region_inference/error_reporting.md: -------------------------------------------------------------------------------- 1 | # Reporting region errors 2 | 3 | TODO: we should discuss how to generate errors from the results of these analyses. 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # The Rust Code of Conduct 2 | 3 | This repository follows the [Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct) of the Rust organization. 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [src/*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | max_line_length = 100 7 | 8 | [ci/*.sh] 9 | indent_style = space 10 | indent_size = 2 11 | -------------------------------------------------------------------------------- /src/backend/inline-asm.md: -------------------------------------------------------------------------------- 1 | # Inline Assembly 2 | 3 | **TODO**: You can find more info 4 | [here](https://github.com/rust-lang/rust/pull/69171#issue-375572066) 5 | [#1162](https://github.com/rust-lang/rustc-dev-guide/issues/1162) 6 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Jynn Nelson 2 | Jynn Nelson 3 | Jynn Nelson 4 | Jynn Nelson 5 | Jynn Nelson 6 | -------------------------------------------------------------------------------- /src/mir/mir_overview.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | Operand -> Constant 3 | Operand -> Place 4 | Place -> Projection 5 | Projection -> Place 6 | Place -> Local 7 | Rvalue -> Operand 8 | Assignment -> Place 9 | Assignment -> Operand 10 | } -------------------------------------------------------------------------------- /examples/README: -------------------------------------------------------------------------------- 1 | For each example to compile, you will need to first run the following: 2 | 3 | rustup component add rustc-dev llvm-tools 4 | 5 | To create an executable: 6 | 7 | rustc rustc-driver-example.rs 8 | 9 | To run an executable: 10 | 11 | rustup run nightly ./rustc-driver-example 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto eol=lf 3 | 4 | # git grep shouldn't match entries in huge minified javascript 5 | *.min.js binary 6 | 7 | # Older git versions try to fix line endings on images, this prevents it. 8 | *.png binary 9 | *.jpg binary 10 | *.ico binary 11 | -------------------------------------------------------------------------------- /ci/date-check/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "date-check" 3 | version = "0.1.0" 4 | authors = ["Noah Lev "] 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | glob = "0.3" 11 | regex = "1" 12 | chrono = "0.4" 13 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | message: If you use this guide, please cite it using these metadata. 3 | title: Rust Compiler Development Guide (rustc-dev-guide) 4 | abstract: A guide to developing the Rust compiler (rustc) 5 | authors: 6 | - name: "The Rust Project Developers" 7 | date-released: "2018-01-16" 8 | license: "MIT OR Apache-2.0" 9 | repository-code: "https://github.com/rust-lang/rustc-dev-guide" 10 | -------------------------------------------------------------------------------- /src/generic_parameters_summary.md: -------------------------------------------------------------------------------- 1 | # Generic parameter definitions 2 | 3 | This chapter will discuss how rustc tracks what generic parameters are introduced by an item. For example given some struct defined via `struct Foo` how does rustc track that `Foo` defines some type parameter `T` and nothing else? 4 | 5 | This will *not* cover how we track generic parameters introduced via `for<'a>` syntax (i.e. in where clauses or `fn` types), which is covered elsewhere in the [chapter on `Binder`s ][ch_binders]. 6 | 7 | [ch_binders]: ./ty_module/binders.md -------------------------------------------------------------------------------- /src/part-3-intro.md: -------------------------------------------------------------------------------- 1 | # Source Code Representation 2 | 3 | This part describes the process of taking raw source code from the user and 4 | transforming it into various forms that the compiler can work with easily. 5 | These are called _intermediate representations (IRs)_. 6 | 7 | This process starts with compiler understanding what the user has asked for: 8 | parsing the command line arguments given and determining what it is to compile. 9 | After that, the compiler transforms the user input into a series of IRs that 10 | look progressively less like what the user wrote. 11 | -------------------------------------------------------------------------------- /src/borrow_check/region_inference/closure_constraints.md: -------------------------------------------------------------------------------- 1 | # Propagating closure constraints 2 | 3 | When we are checking the type tests and universal regions, we may come 4 | across a constraint that we can't prove yet if we are in a closure 5 | body! However, the necessary constraints may actually hold (we just 6 | don't know it yet). Thus, if we are inside a closure, we just collect 7 | all the constraints we can't prove yet and return them. Later, when we 8 | are borrow check the MIR node that created the closure, we can also 9 | check that these constraints hold. At that time, if we can't prove 10 | they hold, we report an error. 11 | -------------------------------------------------------------------------------- /src/syntax-intro.md: -------------------------------------------------------------------------------- 1 | # Syntax and the AST 2 | 3 | Working directly with source code is very inconvenient and error-prone. Thus, 4 | before we do anything else, we convert raw source code into an AST. It turns 5 | out that doing even this involves a lot of work, including lexing, parsing, 6 | macro expansion, name resolution, conditional compilation, feature-gate 7 | checking, and validation of the AST. In this chapter, we take a look at all 8 | of these steps. 9 | 10 | Notably, there isn't always a clean ordering between these tasks. For example, 11 | macro expansion relies on name resolution to resolve the names of macros and 12 | imports. And parsing requires macro expansion, which in turn may require 13 | parsing the output of the macro. 14 | -------------------------------------------------------------------------------- /src/hir-debugging.md: -------------------------------------------------------------------------------- 1 | # HIR Debugging 2 | 3 | Use the `-Z unpretty=hir` flag to produce a human-readable representation of the HIR. 4 | For cargo projects this can be done with `cargo rustc -- -Z unpretty=hir`. 5 | This output is useful when you need to see at a glance how your code was desugared and transformed 6 | during AST lowering. 7 | 8 | For a full `Debug` dump of the data in the HIR, use the `-Z unpretty=hir-tree` flag. 9 | This may be useful when you need to see the full structure of the HIR from the perspective of the 10 | compiler. 11 | 12 | If you are trying to correlate `NodeId`s or `DefId`s with source code, the 13 | `-Z unpretty=expanded,identified` flag may be useful. 14 | 15 | TODO: anything else? [#1159](https://github.com/rust-lang/rustc-dev-guide/issues/1159) 16 | -------------------------------------------------------------------------------- /src/part-4-intro.md: -------------------------------------------------------------------------------- 1 | # Analysis 2 | 3 | This part discusses the many analyses that the compiler uses to check various 4 | properties of the code and to inform later stages. Typically, this is what people 5 | mean when they talk about "Rust's type system". This includes the 6 | representation, inference, and checking of types, the trait system, and the 7 | borrow checker. These analyses do not happen as one big pass or set of 8 | contiguous passes. Rather, they are spread out throughout various parts of the 9 | compilation process and use different intermediate representations. For example, 10 | type checking happens on the HIR, while borrow checking happens on the MIR. 11 | Nonetheless, for the sake of presentation, we will discuss all of these 12 | analyses in this part of the guide. 13 | -------------------------------------------------------------------------------- /src/part-2-intro.md: -------------------------------------------------------------------------------- 1 | # High-Level Compiler Architecture 2 | 3 | The remaining parts of this guide discuss how the compiler works. They go 4 | through everything from high-level structure of the compiler to how each stage 5 | of compilation works. They should be friendly to both readers interested in the 6 | end-to-end process of compilation _and_ readers interested in learning about a 7 | specific system they wish to contribute to. If anything is unclear, feel free 8 | to file an issue on the [rustc-dev-guide 9 | repo](https://github.com/rust-lang/rustc-dev-guide/issues) or contact the compiler 10 | team, as detailed in [this chapter from Part 1](./compiler-team.md). 11 | 12 | In this part, we will look at the high-level architecture of the compiler. In 13 | particular, we will look at three overarching design choices that impact the 14 | whole compiler: the query system, incremental compilation, and interning. 15 | -------------------------------------------------------------------------------- /src/rustc-driver-getting-diagnostics.md: -------------------------------------------------------------------------------- 1 | # Example: Getting diagnostic through `rustc_interface` 2 | 3 | The [`rustc_interface`] allows you to intercept diagnostics that would 4 | otherwise be printed to stderr. 5 | 6 | ## Getting diagnostics 7 | 8 | To get diagnostics from the compiler, 9 | configure [`rustc_interface::Config`] to output diagnostic to a buffer, 10 | and run [`TyCtxt.analysis`]. The following was tested 11 | with `nightly-2024-05-09`: 12 | 13 | ```rust 14 | {{#include ../examples/rustc-driver-getting-diagnostics.rs}} 15 | ``` 16 | 17 | [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html 18 | [`rustc_interface::Config`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Config.html 19 | [`TyCtxt.analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.analysis.html 20 | -------------------------------------------------------------------------------- /src/rustc-driver-interacting-with-the-ast.md: -------------------------------------------------------------------------------- 1 | # Example: Type checking through `rustc_interface` 2 | 3 | The [`rustc_interface`] allows you to interact with Rust code at various stages of compilation. 4 | 5 | ## Getting the type of an expression 6 | 7 | To get the type of an expression, use the [`global_ctxt`] query to [get] a [`TyCtxt`]. 8 | The following was tested with `nightly-2024-05-09`: 9 | 10 | ```rust 11 | {{#include ../examples/rustc-driver-interacting-with-the-ast.rs}} 12 | ``` 13 | [get]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.GlobalCtxt.html#method.enter 14 | [`global_ctxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/queries/struct.Queries.html#method.global_ctxt 15 | [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface 16 | [`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html 17 | -------------------------------------------------------------------------------- /src/notification-groups/arm.md: -------------------------------------------------------------------------------- 1 | # ARM notification group 2 | 3 | **Github Label:** [O-ARM]
4 | **Ping command:** `@rustbot ping arm` 5 | 6 | [O-ARM]: https://github.com/rust-lang/rust/labels/O-ARM 7 | 8 | This list will be used to ask for help both in diagnosing and testing 9 | ARM-related issues as well as suggestions on how to resolve 10 | interesting questions regarding our ARM support. 11 | 12 | The group also has an associated Zulip stream ([`#t-compiler/arm`]) 13 | where people can go to pose questions and discuss ARM-specific 14 | topics. 15 | 16 | So, if you are interested in participating, please sign up for the 17 | ARM group! To do so, open a PR against the [rust-lang/team] 18 | repository. Just [follow this example][eg], but change the username to 19 | your own! 20 | 21 | [`#t-compiler/arm`]: https://rust-lang.zulipchat.com/#narrow/stream/242906-t-compiler.2Farm 22 | [rust-lang/team]: https://github.com/rust-lang/team 23 | [eg]: https://github.com/rust-lang/team/pull/358 24 | -------------------------------------------------------------------------------- /src/notification-groups/risc-v.md: -------------------------------------------------------------------------------- 1 | # RISC-V notification group 2 | 3 | **Github Label:** [O-riscv]
4 | **Ping command:** `@rustbot ping risc-v` 5 | 6 | [O-riscv]: https://github.com/rust-lang/rust/labels/O-riscv 7 | 8 | This list will be used to ask for help both in diagnosing and testing 9 | RISC-V-related issues as well as suggestions on how to resolve 10 | interesting questions regarding our RISC-V support. 11 | 12 | The group also has an associated Zulip stream ([`#t-compiler/risc-v`]) 13 | where people can go to pose questions and discuss RISC-V-specific 14 | topics. 15 | 16 | So, if you are interested in participating, please sign up for the 17 | RISC-V group! To do so, open a PR against the [rust-lang/team] 18 | repository. Just [follow this example][eg], but change the username to 19 | your own! 20 | 21 | [`#t-compiler/risc-v`]: https://rust-lang.zulipchat.com/#narrow/stream/250483-t-compiler.2Frisc-v 22 | [rust-lang/team]: https://github.com/rust-lang/team 23 | [eg]: https://github.com/rust-lang/team/pull/394 24 | -------------------------------------------------------------------------------- /src/crates-io.md: -------------------------------------------------------------------------------- 1 | # crates.io Dependencies 2 | 3 | The Rust compiler supports building with some dependencies from `crates.io`. 4 | Examples are `log` and `env_logger`. 5 | 6 | In general, 7 | you should avoid adding dependencies to the compiler for several reasons: 8 | 9 | - The dependency may not be of high quality or well-maintained. 10 | - The dependency may not be using a compatible license. 11 | - The dependency may have transitive dependencies that have one of the above 12 | problems. 13 | 14 | 15 | Note that there is no official policy for vetting new dependencies to the compiler. 16 | Decisions are made on a case-by-case basis, during code review. 17 | 18 | ## Permitted dependencies 19 | 20 | The `tidy` tool has [a list of crates that are allowed]. To add a 21 | dependency that is not already in the compiler, you will need to add it to the list. 22 | 23 | [a list of crates that are allowed]: https://github.com/rust-lang/rust/blob/9d1b2106e23b1abd32fce1f17267604a5102f57a/src/tools/tidy/src/deps.rs#L73 24 | -------------------------------------------------------------------------------- /src/building/build-install-distribution-artifacts.md: -------------------------------------------------------------------------------- 1 | # Build distribution artifacts 2 | 3 | You might want to build and package up the compiler for distribution. 4 | You’ll want to run this command to do it: 5 | 6 | ```bash 7 | ./x dist 8 | ``` 9 | 10 | # Install distribution artifacts 11 | 12 | If you’ve built a distribution artifact you might want to install it and 13 | test that it works on your target system. You’ll want to run this command: 14 | 15 | ```bash 16 | ./x install 17 | ``` 18 | 19 | Note: If you are testing out a modification to a compiler, you 20 | might want to use it to compile some project. 21 | Usually, you do not want to use `./x install` for testing. 22 | Rather, you should create a toolchain as discussed in 23 | [here][create-rustup-toolchain]. 24 | 25 | For example, if the toolchain you created is called foo, you 26 | would then invoke it with `rustc +foo ...` (where ... represents 27 | the rest of the arguments). 28 | 29 | [create-rustup-toolchain]: ./how-to-build-and-run.md#creating-a-rustup-toolchain -------------------------------------------------------------------------------- /src/mir/mir_detailed.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | Operand -> Constant 3 | Operand -> Place [taillabel="read"] 4 | Place -> Projection 5 | Projection -> Place 6 | Place -> LocalId 7 | Rvalue -> "Rvalue\nAggregate" 8 | Rvalue -> "Rvalue\nBinaryOp" 9 | Rvalue -> "Rvalue\nUnaryOp" 10 | Rvalue -> "Rvalue\n..." 11 | "Rvalue\nAggregate" -> Operand [headlabel="*"] 12 | "Rvalue\nBinaryOp" -> Operand [headlabel="2"] 13 | "Rvalue\nUnaryOp" -> Operand 14 | "Statement\nAssignment" -> Place [taillabel="write"] 15 | "Statement\nAssignment" -> Rvalue 16 | Statement -> "Statement\nAssignment" 17 | Statement -> "Statement\n..." 18 | Block -> Statement [headlabel="*"] 19 | Block -> Terminator 20 | Terminator -> "Terminator\nSwitchInt" 21 | "Terminator\nSwitchInt" -> Operand 22 | "Terminator\nSwitchInt" -> Constant [headlabel="*"] 23 | "Terminator\nSwitchInt" -> BlockId [headlabel="*"] 24 | Terminator -> "Terminator\n..." 25 | Mir -> Block [headlabel="*"] 26 | Mir -> Local [headlabel="*"] 27 | } -------------------------------------------------------------------------------- /src/notification-groups/rust-for-linux.md: -------------------------------------------------------------------------------- 1 | # Rust for Linux notification group 2 | 3 | **Github Label:** [O-rfl]
4 | **Ping command:** `@rustbot ping rfl` 5 | 6 | [O-rfl]: https://github.com/rust-lang/rust/labels/O-rfl 7 | 8 | This list will be used to notify [Rust for Linux (RfL)][rfl] maintainers 9 | when the compiler or the standard library changes in a way that would 10 | break Rust for Linux, since it depends on several unstable flags 11 | and features. The RfL maintainers should then ideally provide support 12 | for resolving the breakage or decide to temporarily accept the breakage 13 | and unblock CI by temporarily removing the RfL CI jobs. 14 | 15 | The group also has an associated Zulip stream ([`#rust-for-linux`]) 16 | where people can go to ask questions and discuss topics related to Rust 17 | for Linux. 18 | 19 | If you are interested in participating, please sign up for the 20 | Rust for Linux group on [Zulip][`#rust-for-linux`]! 21 | 22 | [rfl]: https://rust-for-linux.com/ 23 | [`#rust-for-linux`]: https://rust-lang.zulipchat.com/#narrow/stream/425075-rust-for-linux 24 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /src/building/bootstrapping/intro.md: -------------------------------------------------------------------------------- 1 | # Bootstrapping the compiler 2 | 3 | [*Bootstrapping*][boot] is the process of using a compiler to compile itself. 4 | More accurately, it means using an older compiler to compile a newer version 5 | of the same compiler. 6 | 7 | This raises a chicken-and-egg paradox: where did the first compiler come from? 8 | It must have been written in a different language. In Rust's case it was 9 | [written in OCaml][ocaml-compiler]. However it was abandoned long ago and the 10 | only way to build a modern version of rustc is a slightly less modern 11 | version. 12 | 13 | This is exactly how `x.py` works: it downloads the current beta release of 14 | rustc, then uses it to compile the new compiler. 15 | 16 | In this section, we give a high-level overview of 17 | [what Bootstrap does](./what-bootstrapping-does.md), followed by a high-level 18 | introduction to [how Bootstrap does it](./how-bootstrap-does-it.md). 19 | 20 | [boot]: https://en.wikipedia.org/wiki/Bootstrapping_(compilers) 21 | [ocaml-compiler]: https://github.com/rust-lang/rust/tree/ef75860a0a72f79f97216f8aaa5b388d98da6480/src/boot 22 | -------------------------------------------------------------------------------- /src/appendix/humorust.md: -------------------------------------------------------------------------------- 1 | # Humor in Rust 2 | 3 | What's a project without a sense of humor? And frankly some of these are 4 | enlightening? 5 | 6 | - [Weird exprs test](https://github.com/rust-lang/rust/blob/master/tests/ui/weird-exprs.rs) 7 | - [Ferris Rap](http://fitzgeraldnick.com/2018/12/13/rust-raps.html) 8 | - [The Genesis of Generic Germination](https://github.com/rust-lang/rust/pull/53645#issue-210543221) 9 | - [The Bastion of the Turbofish test](https://github.com/rust-lang/rust/blob/79d8a0fcefa5134db2a94739b1d18daa01fc6e9f/src/test/ui/bastion-of-the-turbofish.rs) 10 | - [Rust Koans](https://users.rust-lang.org/t/rust-koans/2408) 11 | - [`break rust;`](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0ab2bd6a9d722e0f05a95e2a5dcf89cc) 12 | - [The Nomicon Intro](https://doc.rust-lang.org/stable/nomicon/) 13 | - [`rustc-ty` renaming punfest](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/rustc-ty.20naming.20bikeshed.20.2F.20punfest.20%28was.3A.20design.20meeting.202.2E.2E.2E/near/189906455) 14 | - [try using their name "ferris" instead](https://github.com/rust-lang/rust/pull/91476) 15 | - [Forbid pineapple on pizza](https://github.com/rust-lang/rust/pull/70645) 16 | -------------------------------------------------------------------------------- /src/param_env/param_env_summary.md: -------------------------------------------------------------------------------- 1 | # The `ParamEnv` type 2 | 3 | ## Summary 4 | 5 | The [`ParamEnv`][pe] is used to store information about the environment that we are interacting with the type system from. For example the set of in-scope where-clauses is stored in `ParamEnv` as it differs between each item whereas the list of user written impls is not stored in the `ParamEnv` as this does not change for each item. 6 | 7 | This chapter of the dev guide covers: 8 | - A high level summary of what a `ParamEnv` is and what it is used for 9 | - Technical details about what the process of constructing a `ParamEnv` involves 10 | - Guidance about how to acquire a `ParamEnv` when one is required 11 | 12 | ## Bundling 13 | 14 | A useful API on `ParamEnv` is the [`and`][and] method which allows bundling a value with the `ParamEnv`. The `and` method produces a [`ParamEnvAnd`][pea] making it clearer that using the inner value is intended to be done in that specific environment. 15 | 16 | [and]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html#method.and 17 | [pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html 18 | [pea]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnvAnd.html -------------------------------------------------------------------------------- /ci/linkcheck.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | set_github_token() { 7 | jq '.config.output.linkcheck."http-headers"."github\\.com" = ["Authorization: Bearer $GITHUB_TOKEN"]' 8 | } 9 | 10 | # https://docs.github.com/en/actions/reference/environment-variables 11 | if [ "$GITHUB_EVENT_NAME" = "schedule" ] ; then # running in scheduled job 12 | FLAGS="" 13 | USE_TOKEN=1 14 | 15 | echo "Doing full link check." 16 | elif [ "$GITHUB_EVENT_NAME" = "pull_request" ] ; then # running in PR CI build 17 | if [ -z "$BASE_SHA" ]; then 18 | echo "error: unexpected state: BASE_SHA must be non-empty in CI" 19 | exit 1 20 | fi 21 | 22 | CHANGED_FILES=$(git diff --name-only $BASE_SHA... | tr '\n' ' ') 23 | FLAGS="--no-cache -f $CHANGED_FILES" 24 | USE_TOKEN=1 25 | 26 | echo "Checking files changed since $BASE_SHA: $CHANGED_FILES" 27 | else # running locally 28 | COMMIT_RANGE=master... 29 | CHANGED_FILES=$(git diff --name-only $COMMIT_RANGE | tr '\n' ' ') 30 | FLAGS="-f $CHANGED_FILES" 31 | 32 | echo "Checking files changed in $COMMIT_RANGE: $CHANGED_FILES" 33 | fi 34 | 35 | echo "exec mdbook-linkcheck $FLAGS" 36 | if [ "$USE_TOKEN" = 1 ]; then 37 | config=$(set_github_token) 38 | exec mdbook-linkcheck $FLAGS <<<"$config" 39 | else 40 | exec mdbook-linkcheck $FLAGS 41 | fi 42 | -------------------------------------------------------------------------------- /src/ast-validation.md: -------------------------------------------------------------------------------- 1 | # AST Validation 2 | 3 | _AST validation_ is a separate AST pass that visits each 4 | item in the tree and performs simple checks. This pass 5 | doesn't perform any complex analysis, type checking or 6 | name resolution. 7 | 8 | Before performing any validation, the compiler first expands 9 | the macros. Then this pass performs validations to check 10 | that each AST item is in the correct state. And when this pass 11 | is done, the compiler runs the crate resolution pass. 12 | 13 | ## Validations 14 | 15 | Validations are defined in `AstValidator` type, which 16 | itself is located in `rustc_ast_passes` crate. This 17 | type implements various simple checks which emit errors 18 | when certain language rules are broken. 19 | 20 | In addition, `AstValidator` implements `Visitor` trait 21 | that defines how to visit AST items (which can be functions, 22 | traits, enums, etc). 23 | 24 | For each item, visitor performs specific checks. For 25 | example, when visiting a function declaration, 26 | `AstValidator` checks that the function has: 27 | 28 | * no more than `u16::MAX` parameters; 29 | * c-variadic functions are declared with at least one named argument; 30 | * c-variadic argument goes the last in the declaration; 31 | * documentation comments aren't applied to function parameters; 32 | * and other validations. 33 | -------------------------------------------------------------------------------- /ci/check-in.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | # This is not a very smart script 6 | if [ $# != 2 ]; then 7 | echo "usage: $0 " 8 | if [ $# = 0 ]; then 9 | echo "help: you can find the last check-in at" \ 10 | "https://rust-lang.zulipchat.com/#narrow/stream/238009-t-compiler.2Fmeetings/search/wg-rustc-dev-guide" 11 | elif [ $# = 1 ] ; then 12 | echo "help: you can find the number of PRs merged at" \ 13 | "https://github.com/rust-lang/rustc-dev-guide/pulls?q=is%3Apr+is%3Amerged+updated%3A%3E$1" 14 | fi 15 | exit 1 16 | fi 17 | 18 | curl() { 19 | command curl -s "$@" 20 | } 21 | 22 | # Get recently updated PRs 23 | curl "https://api.github.com/repos/rust-lang/rustc-dev-guide/pulls?state=closed&per_page=$2" \ 24 | | jq '[.[] | select(.merged_at > "'"$1"'")]' > pulls.json 25 | 26 | show_pulls() { 27 | jq -r '.[] | { title, number, html_url, user: .user.login } | "- " + .title + " [#" + (.number | tostring) + "](" + .html_url + ")"' 28 | } 29 | 30 | echo "### Most notable changes" 31 | echo 32 | show_pulls < pulls.json 33 | echo 34 | echo "### Most notable WIPs" 35 | echo 36 | # If there are more than 30 PRs open at a time, you'll need to set `per_page`. 37 | # For now this seems unlikely. 38 | curl "https://api.github.com/repos/rust-lang/rustc-dev-guide/pulls?state=open" | show_pulls 39 | -------------------------------------------------------------------------------- /src/notification-groups/llvm.md: -------------------------------------------------------------------------------- 1 | # LLVM Notification group 2 | 3 | **Github Label:** [A-LLVM]
4 | **Ping command:** `@rustbot ping llvm` 5 | 6 | [A-LLVM]: https://github.com/rust-lang/rust/labels/A-LLVM 7 | 8 | The "LLVM Notification Group" are focused on bugs that center around LLVM. 9 | These bugs often arise because of LLVM optimizations gone awry, or as 10 | the result of an LLVM upgrade. The goal here is: 11 | 12 | - to determine whether the bug is a result of us generating invalid LLVM IR, 13 | or LLVM misoptimizing; 14 | - if the former, to fix our IR; 15 | - if the latter, to try and file a bug on LLVM (or identify an existing bug). 16 | 17 | The group may also be asked to weigh in on other sorts of LLVM-focused 18 | questions. 19 | 20 | ## Helpful tips and options 21 | 22 | The ["Debugging LLVM"][d] section of the 23 | rustc-dev-guide gives a step-by-step process for how to help debug bugs 24 | caused by LLVM. In particular, it discusses how to emit LLVM IR, run 25 | the LLVM IR optimization pipelines, and so forth. You may also find 26 | it useful to look at the various codegen options listed under `-C help` 27 | and the internal options under `-Z help` -- there are a number that 28 | pertain to LLVM (just search for LLVM). 29 | 30 | [d]: ../backend/debugging.md 31 | 32 | ## If you do narrow to an LLVM bug 33 | 34 | The ["Debugging LLVM"][d] section also describes what to do once 35 | you've identified the bug. 36 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | title = "Rust Compiler Development Guide" 3 | author = "The Rust Project Developers" 4 | description = "A guide to developing the Rust compiler (rustc)" 5 | 6 | [build] 7 | create-missing = false 8 | 9 | [preprocessor.toc] 10 | command = "mdbook-toc" 11 | renderer = ["html"] 12 | 13 | [preprocessor.mermaid] 14 | command = "mdbook-mermaid" 15 | 16 | [output.html] 17 | git-repository-url = "https://github.com/rust-lang/rustc-dev-guide" 18 | edit-url-template = "https://github.com/rust-lang/rustc-dev-guide/edit/master/{path}" 19 | additional-js = ["mermaid.min.js", "mermaid-init.js"] 20 | 21 | [output.html.search] 22 | use-boolean-and = true 23 | 24 | [output.html.fold] 25 | enable = true 26 | level = 0 27 | 28 | [output.linkcheck] 29 | command = "ci/linkcheck.sh" 30 | follow-web-links = true 31 | exclude = [ 32 | "crates\\.io", 33 | "gcc\\.godbolt\\.org", 34 | "youtube\\.com", 35 | "youtu\\.be", 36 | "dl\\.acm\\.org", 37 | "cs\\.bgu\\.ac\\.il", 38 | "www\\.amazon\\.com", 39 | "www\\.rustaceans\\.org", 40 | "play\\.rust-lang\\.org", 41 | "tomlee\\.co", 42 | "marketplace\\.visualstudio\\.com", 43 | "objects\\.githubusercontent\\.com" 44 | ] 45 | cache-timeout = 86400 46 | warning-policy = "error" 47 | 48 | [output.html.redirect] 49 | "/compiletest.html" = "tests/compiletest.html" 50 | "/diagnostics/sessiondiagnostic.html" = "diagnostic-structs.html" 51 | "/diagnostics/diagnostic-codes.html" = "error-codes.html" 52 | "/miri.html" = "const-eval/interpret.html" 53 | -------------------------------------------------------------------------------- /.github/workflows/date-check.yml: -------------------------------------------------------------------------------- 1 | name: Date-Check 2 | 3 | on: 4 | schedule: 5 | # Run at noon UTC every 1st of the month 6 | - cron: '00 12 01 * *' 7 | 8 | # Allow manually starting the workflow 9 | workflow_dispatch: 10 | 11 | jobs: 12 | date-check: 13 | if: github.repository == 'rust-lang/rustc-dev-guide' 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout repo 18 | uses: actions/checkout@v4 19 | 20 | - name: Ensure Rust is up-to-date 21 | run: | 22 | rustup update stable 23 | 24 | - name: Run `date-check` 25 | working-directory: ci/date-check 26 | run: | 27 | cargo run -- ../../src/ > ../../date-check-output.txt 28 | 29 | - name: Open issue 30 | uses: actions/github-script@v7 31 | with: 32 | script: | 33 | const fs = require('fs'); 34 | 35 | const rawText = fs.readFileSync('date-check-output.txt', { encoding: 'utf8' }); 36 | const title = rawText.split('\n')[0]; 37 | if (title != 'empty') { 38 | const body = rawText.split('\n').slice(1).join('\n'); 39 | github.rest.issues.create({ 40 | owner: context.repo.owner, 41 | repo: context.repo.repo, 42 | title, 43 | body, 44 | }); 45 | console.log('Opened issue.'); 46 | } else { 47 | console.log('No dates to triage.'); 48 | } 49 | -------------------------------------------------------------------------------- /src/building/compiler-documenting.md: -------------------------------------------------------------------------------- 1 | # Building documentation 2 | 3 | This chapter describes how to build documentation of toolchain components, 4 | like the standard library (std) or the compiler (rustc). 5 | 6 | - Document everything 7 | 8 | This uses `rustdoc` from the beta toolchain, 9 | so will produce (slightly) different output to stage 1 rustdoc, 10 | as rustdoc is under active development: 11 | 12 | ```bash 13 | ./x doc 14 | ``` 15 | 16 | If you want to be sure the documentation looks the same as on CI: 17 | 18 | ```bash 19 | ./x doc --stage 1 20 | ``` 21 | 22 | This ensures that (current) rustdoc gets built, 23 | then that is used to document the components. 24 | 25 | - Much like running individual tests or building specific components, 26 | you can build just the documentation you want: 27 | 28 | ```bash 29 | ./x doc src/doc/book 30 | ./x doc src/doc/nomicon 31 | ./x doc compiler library 32 | ``` 33 | 34 | See [the nightly docs index page](https://doc.rust-lang.org/nightly/) for a full list of books. 35 | 36 | - Document internal rustc items 37 | 38 | Compiler documentation is not built by default. 39 | To create it by default with `x doc`, modify `config.toml`: 40 | 41 | ```toml 42 | [build] 43 | compiler-docs = true 44 | ``` 45 | 46 | Note that when enabled, 47 | documentation for internal compiler items will also be built. 48 | 49 | NOTE: The documentation for the compiler is found at [this link]. 50 | 51 | [this link]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ 52 | -------------------------------------------------------------------------------- /src/notification-groups/windows.md: -------------------------------------------------------------------------------- 1 | # Windows notification group 2 | 3 | **Github Label:** [O-Windows]
4 | **Ping command:** `@rustbot ping windows` 5 | 6 | [O-Windows]: https://github.com/rust-lang/rust/labels/O-Windows 7 | 8 | This list will be used to ask for help both in diagnosing and testing 9 | Windows-related issues as well as suggestions on how to resolve 10 | interesting questions regarding our Windows support. 11 | 12 | The group also has an associated Zulip stream ([`#t-compiler/windows`]) 13 | where people can go to pose questions and discuss Windows-specific 14 | topics. 15 | 16 | To get a better idea for what the group will do, here are some 17 | examples of the kinds of questions where we would have reached out to 18 | the group for advice in determining the best course of action: 19 | 20 | * Which versions of MinGW should we support? 21 | * Should we remove the legacy InnoSetup GUI installer? [#72569] 22 | * What names should we use for static libraries on Windows? [#29520] 23 | 24 | So, if you are interested in participating, please sign up for the 25 | Windows group! To do so, open a PR against the [rust-lang/team] 26 | repository. Just [follow this example][eg], but change the username to 27 | your own! 28 | 29 | [`#t-compiler/windows`]: https://rust-lang.zulipchat.com/#streams/242869/t-compiler.2Fwindows 30 | [rust-lang/team]: https://github.com/rust-lang/team 31 | [eg]: https://github.com/rust-lang/team/pull/348/ 32 | [#72569]: https://github.com/rust-lang/rust/pull/72569 33 | [#29520]: https://github.com/rust-lang/rust/pull/29520 34 | -------------------------------------------------------------------------------- /src/what_is_ty_generics.md: -------------------------------------------------------------------------------- 1 | # What is `ty::Generics` 2 | 3 | The generic parameters introduced by an item are tracked the [`ty::Generics`] struct. Sometimes items allows usage of generics of parent items inside of them, this is accomplished via the `ty::Generics` struct having an optional field to specify a parent item to inherit generic parameters of. For example given the following code: 4 | 5 | ```rust,ignore 6 | trait Trait { 7 | fn foo(&self); 8 | } 9 | ``` 10 | 11 | The `ty::Generics` used for `foo` would contain `[U]` and a parent of `Some(Trait)`. `Trait` would have a `ty::Generics` containing `[Self, T]` with a parent of `None`. 12 | 13 | The [`GenericParamDef`] struct is used to represent each individual generic parameter in a `ty::Generics` listing. The `GenericParamDef` struct contains information about the generic parameter, for example its name, defid, what kind of parameter it is (i.e. type, const, lifetime). 14 | 15 | `GenericParamDef` also contains a `u32` index representing what position the parameter is (starting from the outermost parent), this is the value used to represent usages of generic parameters (more on this in the [chapter on representing types][ch_representing_types]). 16 | 17 | Interestingly, `ty::Generics` does not currently contain _every_ generic parameter defined on an item. In the case of functions it only contains the _early bound_ lifetime parameters. See the next chapter for information on what "early bound" and "late bound" parameters are. 18 | 19 | [ch_representing_types]: ./ty.md 20 | [`ty::Generics`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html 21 | [`GenericParamDef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/generics/struct.GenericParamDef.html -------------------------------------------------------------------------------- /src/cli.md: -------------------------------------------------------------------------------- 1 | # Command-line Arguments 2 | 3 | Command-line flags are documented in the [rustc book][cli-docs]. All *stable* 4 | flags should be documented there. Unstable flags should be documented in the 5 | [unstable book]. 6 | 7 | See the [forge guide for new options] for details on the *procedure* for 8 | adding a new command-line argument. 9 | 10 | ## Guidelines 11 | 12 | - Flags should be orthogonal to each other. For example, if we'd have a 13 | json-emitting variant of multiple actions `foo` and `bar`, an additional 14 | `--json` flag is better than adding `--foo-json` and `--bar-json`. 15 | - Avoid flags with the `no-` prefix. Instead, use the [`parse_bool`] function, 16 | such as `-C embed-bitcode=no`. 17 | - Consider the behavior if the flag is passed multiple times. In some 18 | situations, the values should be accumulated (in order!). In other 19 | situations, subsequent flags should override previous flags (for example, 20 | the lint-level flags). And some flags (like `-o`) should generate an error 21 | if it is too ambiguous what multiple flags would mean. 22 | - Always give options a long descriptive name, if only for more understandable 23 | compiler scripts. 24 | - The `--verbose` flag is for adding verbose information to `rustc` 25 | output. For example, using it with the `--version` 26 | flag gives information about the hashes of the compiler code. 27 | - Experimental flags and options must be guarded behind the `-Z 28 | unstable-options` flag. 29 | 30 | [cli-docs]: https://doc.rust-lang.org/rustc/command-line-arguments.html 31 | [forge guide for new options]: https://forge.rust-lang.org/compiler/new_option.html 32 | [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/ 33 | [`parse_bool`]: https://github.com/rust-lang/rust/blob/e5335592e78354e33d798d20c04bcd677c1df62d/src/librustc_session/options.rs#L307-L313 34 | -------------------------------------------------------------------------------- /src/borrow_check/moves_and_initialization.md: -------------------------------------------------------------------------------- 1 | # Tracking moves and initialization 2 | 3 | Part of the borrow checker's job is to track which variables are 4 | "initialized" at any given point in time -- this also requires 5 | figuring out where moves occur and tracking those. 6 | 7 | ## Initialization and moves 8 | 9 | From a user's perspective, initialization -- giving a variable some 10 | value -- and moves -- transferring ownership to another place -- might 11 | seem like distinct topics. Indeed, our borrow checker error messages 12 | often talk about them differently. But **within the borrow checker**, 13 | they are not nearly as separate. Roughly speaking, the borrow checker 14 | tracks the set of "initialized places" at any point in the source 15 | code. Assigning to a previously uninitialized local variable adds it 16 | to that set; moving from a local variable removes it from that set. 17 | 18 | Consider this example: 19 | 20 | ```rust,ignore 21 | fn foo() { 22 | let a: Vec; 23 | 24 | // a is not initialized yet 25 | 26 | a = vec![22]; 27 | 28 | // a is initialized here 29 | 30 | std::mem::drop(a); // a is moved here 31 | 32 | // a is no longer initialized here 33 | 34 | let l = a.len(); //~ ERROR 35 | } 36 | ``` 37 | 38 | Here you can see that `a` starts off as uninitialized; once it is 39 | assigned, it becomes initialized. But when `drop(a)` is called, that 40 | moves `a` into the call, and hence it becomes uninitialized again. 41 | 42 | ## Subsections 43 | 44 | To make it easier to peruse, this section is broken into a number of 45 | subsections: 46 | 47 | - [Move paths](./moves_and_initialization/move_paths.html) the 48 | *move path* concept that we use to track which local variables (or parts of 49 | local variables, in some cases) are initialized. 50 | - TODO *Rest not yet written* =) 51 | -------------------------------------------------------------------------------- /src/diagnostics/error-guaranteed.md: -------------------------------------------------------------------------------- 1 | # `ErrorGuaranteed` 2 | The previous sections have been about the error message that a user of the 3 | compiler sees. But emitting an error can also have a second important side 4 | effect within the compiler source code: it generates an 5 | [`ErrorGuaranteed`][errorguar]. 6 | 7 | `ErrorGuaranteed` is a zero-sized type that is unconstructable outside of the 8 | [`rustc_errors`][rerrors] crate. It is generated whenever an error is reported 9 | to the user, so that if your compiler code ever encounters a value of type 10 | `ErrorGuaranteed`, the compilation is _statically guaranteed to fail_. This is 11 | useful for avoiding unsoundness bugs because you can statically check that an 12 | error code path leads to a failure. 13 | 14 | There are some important considerations about the usage of `ErrorGuaranteed`: 15 | 16 | * It does _not_ convey information about the _kind_ of error. For example, the 17 | error may be due (indirectly) to a delayed bug or other compiler error. 18 | Thus, you should not rely on 19 | `ErrorGuaranteed` when deciding whether to emit an error, or what kind of error 20 | to emit. 21 | * `ErrorGuaranteed` should not be used to indicate that a compilation _will 22 | emit_ an error in the future. It should be used to indicate that an error 23 | _has already been_ emitted -- that is, the [`emit()`][emit] function has 24 | already been called. For example, if we detect that a future part of the 25 | compiler will error, we _cannot_ use `ErrorGuaranteed` unless we first emit 26 | an error or delayed bug ourselves. 27 | 28 | Thankfully, in most cases, it should be statically impossible to abuse 29 | `ErrorGuaranteed`. 30 | 31 | [errorguar]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.ErrorGuaranteed.html 32 | [rerrors]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html 33 | [emit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.diag.html#method.emit 34 | -------------------------------------------------------------------------------- /src/early-late-bound-params/early-late-bound-summary.md: -------------------------------------------------------------------------------- 1 | # Early/Late bound parameters 2 | 3 | This section discusses what it means for generic parameters to be early or late bound. 4 | 5 | ```rust 6 | fn foo<'a, T>(b: &'a T) -> &'a T { b } 7 | // ^^ ^early bound 8 | // ^^ 9 | // ^^late bound 10 | ``` 11 | 12 | Generally when referring to an item with generic parameters you must specify a list of generic arguments corresponding to the item's generic parameters. In 13 | some cases it is permitted to elide these arguments but still, implicitly, a set of arguments are provided (i.e. `Vec::default()` desugars to `Vec::<_>::default()`). 14 | 15 | For functions this is not necessarily the case, for example if we take the function `foo` from the example above and write the following code: 16 | ```rust 17 | fn main() { 18 | let f = foo::<_>; 19 | 20 | let b = String::new(); 21 | let c = String::new(); 22 | 23 | f(&b); 24 | drop(b); 25 | f(&c); 26 | } 27 | ``` 28 | 29 | This code compiles perfectly fine even though there is no single lifetime that could possibly be specified in `foo::<_>` that would allow for both 30 | the `&b` and `&c` borrows to be used as arguments (note: the `drop(b)` line forces the `&b` borrow to be shorter than the `&c` borrow). This works because 31 | the `'a` lifetime is _late bound_. 32 | 33 | A generic parameter being late bound means that when we write `foo::<_>` we do not actually provide an argument for that parameter, instead we wait until _calling_ the function to provide the generic argument. In the above example this means that we are doing something like `f::<'_>(&b);` and `f::<'_>(&c);` (although in practice we do not actually support turbofishing late bound parameters in this manner) 34 | 35 | It may be helpful to think of "early bound parameter" or "late bound parameter" as meaning "early provided parameter" and "late provided parameter", i.e. we provide the argument to the parameter either early (when naming the function) or late (when calling it). -------------------------------------------------------------------------------- /src/building/prerequisites.md: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | 3 | ## Dependencies 4 | 5 | See [the `rust-lang/rust` INSTALL](https://github.com/rust-lang/rust/blob/master/INSTALL.md#dependencies). 6 | 7 | ## Hardware 8 | 9 | You will need an internet connection to build. The bootstrapping process 10 | involves updating git submodules and downloading a beta compiler. It doesn't 11 | need to be super fast, but that can help. 12 | 13 | There are no strict hardware requirements, but building the compiler is 14 | computationally expensive, so a beefier machine will help, and I wouldn't 15 | recommend trying to build on a Raspberry Pi! We recommend the following. 16 | * 30GB+ of free disk space. Otherwise, you will have to keep 17 | clearing incremental caches. More space is better, the compiler is a bit of a 18 | hog; it's a problem we are aware of. 19 | * 8GB+ RAM 20 | * 2+ cores. Having more cores really helps. 10 or 20 or more is not too many! 21 | 22 | Beefier machines will lead to much faster builds. If your machine is not very 23 | powerful, a common strategy is to only use `./x check` on your local machine 24 | and let the CI build test your changes when you push to a PR branch. 25 | 26 | Building the compiler takes more than half an hour on my moderately powerful 27 | laptop. We suggest downloading LLVM from CI so you don't have to build it from source 28 | ([see here][config]). 29 | 30 | Like `cargo`, the build system will use as many cores as possible. Sometimes 31 | this can cause you to run low on memory. You can use `-j` to adjust the number 32 | of concurrent jobs. If a full build takes more than ~45 minutes to an hour, you 33 | are probably spending most of the time swapping memory in and out; try using 34 | `-j1`. 35 | 36 | If you don't have too much free disk space, you may want to turn off 37 | incremental compilation ([see here][config]). This will make compilation take 38 | longer (especially after a rebase), but will save a ton of space from the 39 | incremental caches. 40 | 41 | [config]: ./how-to-build-and-run.md#create-a-configtoml 42 | -------------------------------------------------------------------------------- /src/traits/chalk.md: -------------------------------------------------------------------------------- 1 | # Chalk-based trait solving 2 | 3 | [Chalk][chalk] is an experimental trait solver for Rust that is 4 | (as of May 2022) under development by the [Types team]. 5 | Its goal is to enable a lot of trait system features and bug fixes 6 | that are hard to implement (e.g. GATs or specialization). If you would like to 7 | help in hacking on the new solver, drop by on the rust-lang Zulip in the [`#t-types`] 8 | stream and say hello! 9 | 10 | [Types team]: https://github.com/rust-lang/types-team 11 | [`#t-types`]: https://rust-lang.zulipchat.com/#narrow/stream/144729-t-types 12 | 13 | The new-style trait solver is based on the work done in [chalk][chalk]. Chalk 14 | recasts Rust's trait system explicitly in terms of logic programming. It does 15 | this by "lowering" Rust code into a kind of logic program we can then execute 16 | queries against. 17 | 18 | The key observation here is that the Rust trait system is basically a 19 | kind of logic, and it can be mapped onto standard logical inference 20 | rules. We can then look for solutions to those inference rules in a 21 | very similar fashion to how e.g. a [Prolog] solver works. It turns out 22 | that we can't *quite* use Prolog rules (also called Horn clauses) but 23 | rather need a somewhat more expressive variant. 24 | 25 | [Prolog]: https://en.wikipedia.org/wiki/Prolog 26 | 27 | You can read more about chalk itself in the 28 | [Chalk book](https://rust-lang.github.io/chalk/book/) section. 29 | 30 | ## Ongoing work 31 | The design of the new-style trait solving happens in two places: 32 | 33 | **chalk**. The [chalk][chalk] repository is where we experiment with new ideas 34 | and designs for the trait system. 35 | 36 | **rustc**. Once we are happy with the logical rules, we proceed to 37 | implementing them in rustc. We map our struct, trait, and impl declarations 38 | into logical inference rules in the lowering module in rustc. 39 | 40 | [chalk]: https://github.com/rust-lang/chalk 41 | [rustc_traits]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_traits 42 | -------------------------------------------------------------------------------- /src/mir/visitor.md: -------------------------------------------------------------------------------- 1 | # MIR visitor 2 | 3 | The MIR visitor is a convenient tool for traversing the MIR and either 4 | looking for things or making changes to it. The visitor traits are 5 | defined in [the `rustc_middle::mir::visit` module][m-v] – there are two of 6 | them, generated via a single macro: `Visitor` (which operates on a 7 | `&Mir` and gives back shared references) and `MutVisitor` (which 8 | operates on a `&mut Mir` and gives back mutable references). 9 | 10 | [m-v]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/visit/index.html 11 | 12 | To implement a visitor, you have to create a type that represents 13 | your visitor. Typically, this type wants to "hang on" to whatever 14 | state you will need while processing MIR: 15 | 16 | ```rust,ignore 17 | struct MyVisitor<...> { 18 | tcx: TyCtxt<'tcx>, 19 | ... 20 | } 21 | ``` 22 | 23 | and you then implement the `Visitor` or `MutVisitor` trait for that type: 24 | 25 | ```rust,ignore 26 | impl<'tcx> MutVisitor<'tcx> for MyVisitor { 27 | fn visit_foo(&mut self, ...) { 28 | ... 29 | self.super_foo(...); 30 | } 31 | } 32 | ``` 33 | 34 | As shown above, within the impl, you can override any of the 35 | `visit_foo` methods (e.g., `visit_terminator`) in order to write some 36 | code that will execute whenever a `foo` is found. If you want to 37 | recursively walk the contents of the `foo`, you then invoke the 38 | `super_foo` method. (NB. You never want to override `super_foo`.) 39 | 40 | A very simple example of a visitor can be found in [`LocalUseVisitor`]. 41 | By implementing `visit_local` method, this visitor counts how many times each local is mutably used. 42 | 43 | [`LocalUseVisitor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/const_debuginfo/struct.LocalUseVisitor.html 44 | 45 | ## Traversal 46 | 47 | In addition the visitor, [the `rustc_middle::mir::traversal` module][t] 48 | contains useful functions for walking the MIR CFG in 49 | [different standard orders][traversal] (e.g. pre-order, reverse 50 | post-order, and so forth). 51 | 52 | [t]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/traversal/index.html 53 | [traversal]: https://en.wikipedia.org/wiki/Tree_traversal 54 | 55 | -------------------------------------------------------------------------------- /src/opaque-types-type-alias-impl-trait.md: -------------------------------------------------------------------------------- 1 | # Opaque types (type alias `impl Trait`) 2 | 3 | Opaque types are syntax to declare an opaque type alias that only 4 | exposes a specific set of traits as their interface; the concrete type in the 5 | background is inferred from a certain set of use sites of the opaque type. 6 | 7 | This is expressed by using `impl Trait` within type aliases, for example: 8 | 9 | ```rust,ignore 10 | type Foo = impl Bar; 11 | ``` 12 | 13 | This declares an opaque type named `Foo`, of which the only information is that 14 | it implements `Bar`. Therefore, any of `Bar`'s interface can be used on a `Foo`, 15 | but nothing else (regardless of whether it implements any other traits). 16 | 17 | Since there needs to be a concrete background type, 18 | you can (as of January 2021) express that type 19 | by using the opaque type in a "defining use site". 20 | 21 | ```rust,ignore 22 | struct Struct; 23 | impl Bar for Struct { /* stuff */ } 24 | fn foo() -> Foo { 25 | Struct 26 | } 27 | ``` 28 | 29 | Any other "defining use site" needs to produce the exact same type. 30 | 31 | ## Defining use site(s) 32 | 33 | Currently only the return value of a function can be a defining use site 34 | of an opaque type (and only if the return type of that function contains 35 | the opaque type). 36 | 37 | The defining use of an opaque type can be any code *within* the parent 38 | of the opaque type definition. This includes any siblings of the 39 | opaque type and all children of the siblings. 40 | 41 | The initiative for *"not causing fatal brain damage to developers due to 42 | accidentally running infinite loops in their brain while trying to 43 | comprehend what the type system is doing"* has decided to disallow children 44 | of opaque types to be defining use sites. 45 | 46 | ### Associated opaque types 47 | 48 | Associated opaque types can be defined by any other associated item 49 | on the same trait `impl` or a child of these associated items. For instance: 50 | 51 | ```rust,ignore 52 | trait Baz { 53 | type Foo; 54 | fn foo() -> Self::Foo; 55 | } 56 | 57 | struct Quux; 58 | 59 | impl Baz for Quux { 60 | type Foo = impl Bar; 61 | fn foo() -> Self::Foo { ... } 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /src/type-checking.md: -------------------------------------------------------------------------------- 1 | # Type checking 2 | 3 | The [`hir_analysis`] crate contains the source for "type collection" as well 4 | as a bunch of related functionality. 5 | Checking the bodies of functions is implemented in the [`hir_typeck`] crate. 6 | These crates draw heavily on the [type inference] and [trait solving]. 7 | 8 | [`hir_analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/index.html 9 | [`hir_typeck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/index.html 10 | [type inference]: ./type-inference.md 11 | [trait solving]: ./traits/resolution.md 12 | 13 | ## Type collection 14 | 15 | Type "collection" is the process of converting the types found in the HIR 16 | (`hir::Ty`), which represent the syntactic things that the user wrote, into the 17 | **internal representation** used by the compiler (`Ty<'tcx>`) – we also do 18 | similar conversions for where-clauses and other bits of the function signature. 19 | 20 | To try and get a sense for the difference, consider this function: 21 | 22 | ```rust,ignore 23 | struct Foo { } 24 | fn foo(x: Foo, y: self::Foo) { ... } 25 | // ^^^ ^^^^^^^^^ 26 | ``` 27 | 28 | Those two parameters `x` and `y` each have the same type: but they will have 29 | distinct `hir::Ty` nodes. Those nodes will have different spans, and of course 30 | they encode the path somewhat differently. But once they are "collected" into 31 | `Ty<'tcx>` nodes, they will be represented by the exact same internal type. 32 | 33 | Collection is defined as a bundle of [queries] for computing information about 34 | the various functions, traits, and other items in the crate being compiled. 35 | Note that each of these queries is concerned with *interprocedural* things – 36 | for example, for a function definition, collection will figure out the type and 37 | signature of the function, but it will not visit the *body* of the function in 38 | any way, nor examine type annotations on local variables (that's the job of 39 | type *checking*). 40 | 41 | For more details, see the [`collect`][collect] module. 42 | 43 | [queries]: ./query.md 44 | [collect]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/index.html 45 | 46 | **TODO**: actually talk about type checking... [#1161](https://github.com/rust-lang/rustc-dev-guide/issues/1161) 47 | -------------------------------------------------------------------------------- /src/licenses.md: -------------------------------------------------------------------------------- 1 | # `rust-lang/rust` Licenses 2 | 3 | The `rustc` compiler source and standard library are dual licensed under the [Apache License v2.0](https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE) and the [MIT License](https://github.com/rust-lang/rust/blob/master/LICENSE-MIT) unless otherwise specified. 4 | 5 | Detailed licensing information is available in the [COPYRIGHT document](https://github.com/rust-lang/rust/blob/master/COPYRIGHT) of the `rust-lang/rust` repository. 6 | 7 | ## Guidelines for reviewers 8 | 9 | In general, reviewers need to be looking not only for the code quality of contributions but also 10 | that they are properly licensed. 11 | We have some tips below for things to look out for when reviewing, but if you ever feel uncertain 12 | as to whether some code might be properly licensed, err on the safe side — reach out to the Council 13 | or Compiler Team Leads for feedback! 14 | 15 | Things to watch out for: 16 | 17 | - The PR author states that they copied, ported, or adapted the code from some other source. 18 | - There is a comment in the code pointing to a webpage or describing where the algorithm was taken 19 | from. 20 | - The algorithm or code pattern seems like it was likely copied from somewhere else. 21 | - When adding new dependencies, double check the dependency's license. 22 | 23 | In all of these cases, we will want to check that source to make sure it it is licensed in a way 24 | that is compatible with Rust’s license. 25 | 26 | Examples 27 | 28 | - Porting C code from a GPL project, like GNU binutils, is not allowed. That would require Rust 29 | itself to be licensed under the GPL. 30 | - Copying code from an algorithms text book may be allowed, but some algorithms are patented. 31 | 32 | ## Porting 33 | 34 | Contributions to rustc, especially around platform and compiler intrinsics, often include porting 35 | over work from other projects, mainly LLVM and GCC. 36 | 37 | Some general rules apply: 38 | 39 | - Copying work needs to adhere to the original license 40 | - This applies to direct copy & paste 41 | - This also applies to code you looked at and ported 42 | 43 | In general, taking inspiration from other codebases is fine, but please exercise caution when 44 | porting code. 45 | 46 | Ports of full libraries (e.g. C libraries shipped with LLVM) must keep the license of the original 47 | library. 48 | -------------------------------------------------------------------------------- /src/tests/crater.md: -------------------------------------------------------------------------------- 1 | # Crater 2 | 3 | [Crater](https://github.com/rust-lang/crater) is a tool for compiling 4 | and running tests for _every_ crate on [crates.io](https://crates.io) (and a 5 | few on GitHub). It is mainly used for checking the extent of breakage when 6 | implementing potentially breaking changes and ensuring lack of breakage by 7 | running beta vs stable compiler versions. 8 | 9 | ## When to run Crater 10 | 11 | You should request a crater run if your PR makes large changes to the compiler 12 | or could cause breakage. If you are unsure, feel free to ask your PR's reviewer. 13 | 14 | ## Requesting Crater Runs 15 | 16 | The rust team maintains a few machines that can be used for running crater runs 17 | on the changes introduced by a PR. If your PR needs a crater run, leave a 18 | comment for the triage team in the PR thread. Please inform the team whether 19 | you require a "check-only" crater run, a "build only" crater run, or a 20 | "build-and-test" crater run. The difference is primarily in time; the 21 | conservative (if you're not sure) option is to go for the build-and-test run. 22 | If making changes that will only have an effect at compile-time (e.g., 23 | implementing a new trait) then you only need a check run. 24 | 25 | Your PR will be enqueued by the triage team and the results will be posted when 26 | they are ready. Check runs will take around ~3-4 days, with the other two 27 | taking 5-6 days on average. 28 | 29 | While crater is really useful, it is also important to be aware of a few 30 | caveats: 31 | 32 | - Not all code is on crates.io! There is a lot of code in repos on GitHub and 33 | elsewhere. Also, companies may not wish to publish their code. Thus, a 34 | successful crater run is not a magically green light that there will be no 35 | breakage; you still need to be careful. 36 | 37 | - Crater only runs Linux builds on x86_64. Thus, other architectures and 38 | platforms are not tested. Critically, this includes Windows. 39 | 40 | - Many crates are not tested. This could be for a lot of reasons, including 41 | that the crate doesn't compile any more (e.g. used old nightly features), 42 | has broken or flaky tests, requires network access, or other reasons. 43 | 44 | - Before crater can be run, `@bors try` needs to succeed in building artifacts. 45 | This means that if your code doesn't compile, you cannot run crater. 46 | -------------------------------------------------------------------------------- /src/building/bootstrapping/how-bootstrap-does-it.md: -------------------------------------------------------------------------------- 1 | # How Bootstrap does it 2 | 3 | The core concept in Bootstrap is a build [`Step`], which are chained together 4 | by [`Builder::ensure`]. [`Builder::ensure`] takes a [`Step`] as input, and runs 5 | the [`Step`] if and only if it has not already been run. Let's take a closer 6 | look at [`Step`]. 7 | 8 | ## Synopsis of [`Step`] 9 | 10 | A [`Step`] represents a granular collection of actions involved in the process 11 | of producing some artifact. It can be thought of like a rule in Makefiles. 12 | The [`Step`] trait is defined as: 13 | 14 | ```rs,no_run 15 | pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { 16 | type Output: Clone; 17 | 18 | const DEFAULT: bool = false; 19 | const ONLY_HOSTS: bool = false; 20 | 21 | // Required methods 22 | fn run(self, builder: &Builder<'_>) -> Self::Output; 23 | fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_>; 24 | 25 | // Provided method 26 | fn make_run(_run: RunConfig<'_>) { ... } 27 | } 28 | ``` 29 | 30 | - `run` is the function that is responsible for doing the work. 31 | [`Builder::ensure`] invokes `run`. 32 | - `should_run` is the command-line interface, which determines if an invocation 33 | such as `x build foo` should run a given [`Step`]. In a "default" context 34 | where no paths are provided, then `make_run` is called directly. 35 | - `make_run` is invoked only for things directly asked via the CLI and not 36 | for steps which are dependencies of other steps. 37 | 38 | ## The entry points 39 | 40 | There's a couple of preliminary steps before core Bootstrap code is reached: 41 | 42 | 1. Shell script or `make`: [`./x`](https://github.com/rust-lang/rust/blob/master/x) or [`./x.ps1`](https://github.com/rust-lang/rust/blob/master/x.ps1) or `make` 43 | 2. Convenience wrapper script: [`x.py`](https://github.com/rust-lang/rust/blob/master/x.py) 44 | 3. [`src/bootstrap/bootstrap.py`](https://github.com/rust-lang/rust/blob/master/src/bootstrap/bootstrap.py) 45 | 4. [`src/bootstrap/src/bin/main.rs`](https://github.com/rust-lang/rust/blob/master/src/bootstrap/src/bin/main.rs) 46 | 47 | See [src/bootstrap/README.md](https://github.com/rust-lang/rust/blob/master/src/bootstrap/README.md) 48 | for a more specific description of the implementation details. 49 | 50 | [`Step`]: https://doc.rust-lang.org/nightly/nightly-rustc/bootstrap/core/builder/trait.Step.html 51 | [`Builder::ensure`]: https://doc.rust-lang.org/nightly/nightly-rustc/bootstrap/core/builder/struct.Builder.html#method.ensure 52 | -------------------------------------------------------------------------------- /src/building/quickstart.md: -------------------------------------------------------------------------------- 1 | # Quickstart 2 | 3 | This is a quickstart guide about getting the compiler running. For more information in the individual steps, 4 | see the other pages in this chapter. 5 | 6 | First, clone the repository: 7 | 8 | ```sh 9 | git clone https://github.com/rust-lang/rust.git 10 | cd rust 11 | ``` 12 | 13 | When building the compiler, we don't use `cargo` directly, instead we use a wrapper called "x". 14 | It is invoked with `./x`. 15 | 16 | We need to create a configuration for the build. Use `./x setup` to create a good default. 17 | 18 | ```sh 19 | ./x setup 20 | ``` 21 | 22 | Then, we can build the compiler. Use `./x build` to build the compiler, standard library and a few tools. 23 | You can also `./x check` to just check it. 24 | All these commands can take specific components/paths as arguments, for example `./x check compiler` to just check the compiler. 25 | 26 | ```sh 27 | ./x build 28 | ``` 29 | 30 | > When doing a change to the compiler that does not affect the way it compiles the standard library 31 | (so for example, a change to an error message), use `--keep-stage-std 1` to avoid recompiling it. 32 | 33 | After building the compiler and standard library, you now have a working compiler toolchain. 34 | You can use it with rustup by linking it. 35 | 36 | ```sh 37 | rustup toolchain link stage1 build/host/stage1 38 | ``` 39 | 40 | Now you have a toolchain called `stage1` linked to your build. You can use it to test the compiler. 41 | 42 | ```sh 43 | rustc +stage1 testfile.rs 44 | ``` 45 | 46 | After doing a change, you can run the compiler test suite with `./x test`. 47 | 48 | `./x test` runs the full test suite, which is slow and rarely what you want. 49 | Usually, `./x test tests/ui` is what you want after a compiler change, 50 | testing all [UI tests](../tests/ui.md) that invoke the compiler on a specific test file and check the output. 51 | 52 | ```sh 53 | ./x test tests/ui 54 | ``` 55 | 56 | Use `--bless` if you've made a change and want to update the `.stderr` files with the new output. 57 | 58 | > `./x suggest` can also be helpful for suggesting which tests to run after a change. 59 | 60 | Congrats, you are now ready to make a change to the compiler! If you have more questions, 61 | [the full chapter](./how-to-build-and-run.md) might contain the answers, and if it doesn't, 62 | feel free to ask for help on [Zulip](https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp). 63 | 64 | If you use VSCode, `./x setup` will ask you if you want to set up the config. For other editors, check out [suggested workflows](./suggested.md). 65 | -------------------------------------------------------------------------------- /src/solve/proof-trees.md: -------------------------------------------------------------------------------- 1 | # Proof trees 2 | 3 | The trait solver can optionally emit a "proof tree", a tree representation of what 4 | happened while trying to prove a goal. 5 | 6 | The used datastructures for which are currently stored in 7 | [`rustc_middle::traits::solve::inspect`]. 8 | 9 | ## What are they used for 10 | 11 | There are 3 intended uses for proof trees. These uses are not yet implemented as 12 | the representation of proof trees itself is currently still unstable. 13 | 14 | They should be used by type system diagnostics to get information about 15 | why a goal failed or remained ambiguous. They should be used by rustdoc to get the 16 | auto-trait implementations for user-defined types, and they should be usable to 17 | vastly improve the debugging experience of the trait solver. 18 | 19 | For debugging you can use `-Zdump-solver-proof-tree` which dumps the proof tree 20 | for all goals proven by the trait solver in the current session. 21 | 22 | ## Requirements and design constraints for proof trees 23 | 24 | The trait solver uses [Canonicalization] and uses completely separate `InferCtxt` for 25 | each nested goal. Both diagnostics and auto-traits in rustdoc need to correctly 26 | handle "looking into nested goals". Given a goal like `Vec>: Debug`, we 27 | canonicalize to `exists Vec>: Debug`, instantiate that goal as 28 | `Vec>: Debug`, get a nested goal `Vec: Debug`, canonicalize this to get 29 | `exists Vec: Debug`, instantiate this as `Vec: Debug` which then results 30 | in a nested `?0: Debug` goal which is ambiguous. 31 | 32 | We need to be able to figure out that `?x` corresponds to `?0` in the nested queries. 33 | 34 | The debug output should also accurately represent the state at each point in the solver. 35 | This means that even though a goal like `fn(?0): FnOnce(i32)` infers `?0` to `i32`, the 36 | proof tree should still store `fn(): FnOnce(i32)` instead of 37 | `fn(i32): FnOnce(i32)` until we actually infer `?0` to `i32`. 38 | 39 | ## The current implementation and how to extract information from proof trees. 40 | 41 | Proof trees will be quite involved as they should accurately represent everything the 42 | trait solver does, which includes fixpoint iterations and performance optimizations. 43 | 44 | We intend to provide a lossy user interface for all usecases. 45 | 46 | TODO: implement this user interface and explain how it can be used here. 47 | 48 | 49 | [`rustc_middle::traits::solve::inspect`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/traits/solve/inspect/index.html 50 | [Canonicalization]: ./canonicalization.md -------------------------------------------------------------------------------- /src/traits/specialization.md: -------------------------------------------------------------------------------- 1 | # Specialization 2 | 3 | **TODO**: where does Chalk fit in? Should we mention/discuss it here? 4 | 5 | Defined in the `specialize` module. 6 | 7 | The basic strategy is to build up a *specialization graph* during 8 | coherence checking (recall that coherence checking looks for overlapping 9 | impls). Insertion into the graph locates the right place 10 | to put an impl in the specialization hierarchy; if there is no right 11 | place (due to partial overlap but no containment), you get an overlap 12 | error. Specialization is consulted when selecting an impl (of course), 13 | and the graph is consulted when propagating defaults down the 14 | specialization hierarchy. 15 | 16 | You might expect that the specialization graph would be used during 17 | selection – i.e. when actually performing specialization. This is 18 | not done for two reasons: 19 | 20 | - It's merely an optimization: given a set of candidates that apply, 21 | we can determine the most specialized one by comparing them directly 22 | for specialization, rather than consulting the graph. Given that we 23 | also cache the results of selection, the benefit of this 24 | optimization is questionable. 25 | 26 | - To build the specialization graph in the first place, we need to use 27 | selection (because we need to determine whether one impl specializes 28 | another). Dealing with this reentrancy would require some additional 29 | mode switch for selection. Given that there seems to be no strong 30 | reason to use the graph anyway, we stick with a simpler approach in 31 | selection, and use the graph only for propagating default 32 | implementations. 33 | 34 | Trait impl selection can succeed even when multiple impls can apply, 35 | as long as they are part of the same specialization family. In that 36 | case, it returns a *single* impl on success – this is the most 37 | specialized impl *known* to apply. However, if there are any inference 38 | variables in play, the returned impl may not be the actual impl we 39 | will use at codegen time. Thus, we take special care to avoid projecting 40 | associated types unless either (1) the associated type does not use 41 | `default` and thus cannot be overridden or (2) all input types are 42 | known concretely. 43 | 44 | ## Additional Resources 45 | 46 | [This talk][talk] by @sunjay may be useful. Keep in mind that the talk only 47 | gives a broad overview of the problem and the solution (it was presented about 48 | halfway through @sunjay's work). Also, it was given in June 2018, and some 49 | things may have changed by the time you watch it. 50 | 51 | [talk]: https://www.youtube.com/watch?v=rZqS4bLPL24 52 | -------------------------------------------------------------------------------- /src/ast-lowering.md: -------------------------------------------------------------------------------- 1 | # AST lowering 2 | 3 | The AST lowering step converts AST to [HIR](hir.html). 4 | This means many structures are removed if they are irrelevant 5 | for type analysis or similar syntax agnostic analyses. Examples 6 | of such structures include but are not limited to 7 | 8 | * Parenthesis 9 | * Removed without replacement, the tree structure makes order explicit 10 | * `for` loops and `while (let)` loops 11 | * Converted to `loop` + `match` and some `let` bindings 12 | * `if let` 13 | * Converted to `match` 14 | * Universal `impl Trait` 15 | * Converted to generic arguments 16 | (but with some flags, to know that the user didn't write them) 17 | * Existential `impl Trait` 18 | * Converted to a virtual `existential type` declaration 19 | 20 | Lowering needs to uphold several invariants in order to not trigger the 21 | sanity checks in `compiler/rustc_passes/src/hir_id_validator.rs`: 22 | 23 | 1. A `HirId` must be used if created. So if you use the `lower_node_id`, 24 | you *must* use the resulting `NodeId` or `HirId` (either is fine, since 25 | any `NodeId`s in the `HIR` are checked for existing `HirId`s) 26 | 2. Lowering a `HirId` must be done in the scope of the *owning* item. 27 | This means you need to use `with_hir_id_owner` if you are creating parts 28 | of an item other than the one being currently lowered. This happens for 29 | example during the lowering of existential `impl Trait` 30 | 3. A `NodeId` that will be placed into a HIR structure must be lowered, 31 | even if its `HirId` is unused. Calling 32 | `let _ = self.lower_node_id(node_id);` is perfectly legitimate. 33 | 4. If you are creating new nodes that didn't exist in the `AST`, you *must* 34 | create new ids for them. This is done by calling the `next_id` method, 35 | which produces both a new `NodeId` as well as automatically lowering it 36 | for you so you also get the `HirId`. 37 | 38 | If you are creating new `DefId`s, since each `DefId` needs to have a 39 | corresponding `NodeId`, it is advisable to add these `NodeId`s to the 40 | `AST` so you don't have to generate new ones during lowering. This has 41 | the advantage of creating a way to find the `DefId` of something via its 42 | `NodeId`. If lowering needs this `DefId` in multiple places, you can't 43 | generate a new `NodeId` in all those places because you'd also get a new 44 | `DefId` then. With a `NodeId` from the `AST` this is not an issue. 45 | 46 | Having the `NodeId` also allows the `DefCollector` to generate the `DefId`s 47 | instead of lowering having to do it on the fly. Centralizing the `DefId` 48 | generation in one place makes it easier to refactor and reason about. 49 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | schedule: 9 | # Run at 18:00 UTC every day 10 | - cron: '0 18 * * *' 11 | 12 | jobs: 13 | ci: 14 | if: github.repository == 'rust-lang/rustc-dev-guide' 15 | runs-on: ubuntu-latest 16 | env: 17 | MDBOOK_VERSION: 0.4.21 18 | MDBOOK_LINKCHECK_VERSION: 0.7.6 19 | MDBOOK_MERMAID_VERSION: 0.12.6 20 | MDBOOK_TOC_VERSION: 0.11.2 21 | DEPLOY_DIR: book/html 22 | BASE_SHA: ${{ github.event.pull_request.base.sha }} 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | steps: 25 | - uses: actions/checkout@v4 26 | with: 27 | # linkcheck needs the base commit. 28 | fetch-depth: 0 29 | 30 | - name: Cache binaries 31 | id: mdbook-cache 32 | uses: actions/cache@v4 33 | with: 34 | path: | 35 | ~/.cargo/bin 36 | key: ${{ runner.os }}-${{ env.MDBOOK_VERSION }}--${{ env.MDBOOK_LINKCHECK_VERSION }}--${{ env.MDBOOK_TOC_VERSION }}--${{ env.MDBOOK_MERMAID_VERSION }} 37 | 38 | - name: Cache linkcheck 39 | uses: actions/cache@v4 40 | with: 41 | path: | 42 | ~/book/linkcheck 43 | key: ${{ runner.os }}-${{ hashFiles('./book/linkcheck') }} 44 | 45 | - name: Install latest nightly Rust toolchain 46 | if: steps.mdbook-cache.outputs.cache-hit != 'true' 47 | run: | 48 | rustup update nightly 49 | rustup override set nightly 50 | 51 | - name: Install Dependencies 52 | if: steps.mdbook-cache.outputs.cache-hit != 'true' 53 | run: | 54 | cargo install mdbook --version ${{ env.MDBOOK_VERSION }} 55 | cargo install mdbook-linkcheck --version ${{ env.MDBOOK_LINKCHECK_VERSION }} 56 | cargo install mdbook-toc --version ${{ env.MDBOOK_TOC_VERSION }} 57 | cargo install mdbook-mermaid --version ${{ env.MDBOOK_MERMAID_VERSION }} 58 | 59 | - name: Check build 60 | run: mdbook build 61 | 62 | - name: Deploy to gh-pages 63 | if: github.event_name == 'push' 64 | run: | 65 | touch "${{ env.DEPLOY_DIR }}/.nojekyll" 66 | cp CNAME "${{ env.DEPLOY_DIR }}" 67 | cd "${{ env.DEPLOY_DIR }}" 68 | rm -rf .git 69 | git init 70 | git config user.name "Deploy from CI" 71 | git config user.email "" 72 | git add . 73 | git commit -m "Deploy ${GITHUB_SHA} to gh-pages" 74 | git push --quiet -f "https://x-token:${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}" HEAD:gh-pages 75 | -------------------------------------------------------------------------------- /src/notification-groups/apple.md: -------------------------------------------------------------------------------- 1 | # Apple notification group 2 | 3 | **Github Labels:** [O-macos], [O-ios], [O-tvos], [O-watchos] and [O-visionos]
4 | **Ping command:** `@rustbot ping apple` 5 | 6 | This list will be used to ask for help both in diagnosing and testing 7 | Apple-related issues as well as suggestions on how to resolve interesting 8 | questions regarding our macOS/iOS/tvOS/watchOS/visionOS support. 9 | 10 | To get a better idea for what the group will do, here are some examples of the 11 | kinds of questions where we would have reached out to the group for advice in 12 | determining the best course of action: 13 | 14 | * Raising the minimum supported versions (e.g. [#104385]) 15 | * Additional Apple targets (e.g. [#121419]) 16 | * Obscure Xcode linker details (e.g. [#121430]) 17 | 18 | [O-macos]: https://github.com/rust-lang/rust/labels/O-macos 19 | [O-ios]: https://github.com/rust-lang/rust/labels/O-ios 20 | [O-tvos]: https://github.com/rust-lang/rust/labels/O-tvos 21 | [O-watchos]: https://github.com/rust-lang/rust/labels/O-watchos 22 | [O-visionos]: https://github.com/rust-lang/rust/labels/O-visionos 23 | [#104385]: https://github.com/rust-lang/rust/pull/104385 24 | [#121419]: https://github.com/rust-lang/rust/pull/121419 25 | [#121430]: https://github.com/rust-lang/rust/pull/121430 26 | 27 | ## Deployment targets 28 | 29 | Apple platforms have a concept of "deployment target", controlled with the 30 | `*_DEPLOYMENT_TARGET` environment variables, and specifies the minimum OS 31 | version that a binary runs on. 32 | 33 | Using an API from a newer OS version in the standard library than the default 34 | that `rustc` uses will result in either a static or a dynamic linker error. 35 | For this reason, try to suggest that people document on `extern "C"` APIs 36 | which OS version they were introduced with, and if that's newer than the 37 | current default used by `rustc`, suggest to use weak linking. 38 | 39 | ## The App Store and private APIs 40 | 41 | Apple are very protective about using undocumented APIs, so it's important 42 | that whenever a change uses a new function, that they are verified to actually 43 | be public API, as even just mentioning undocumented APIs in the binary 44 | (without calling it) can lead to rejections from the App Store. 45 | 46 | For example, Darwin / the XNU kernel actually has futex syscalls, but we can't 47 | use them in `std` because they are not public API. 48 | 49 | In general, for an API to be considered public by Apple, it has to: 50 | - Appear in a public header (i.e. one distributed with Xcode, and found for 51 | the specific platform under `xcrun --show-sdk-path --sdk $SDK`). 52 | - Have an availability attribute on it (like `__API_AVAILABLE`, 53 | `API_AVAILABLE` or similar). 54 | -------------------------------------------------------------------------------- /src/tests/perf.md: -------------------------------------------------------------------------------- 1 | # Performance testing 2 | 3 | ## rustc-perf 4 | 5 | A lot of work is put into improving the performance of the compiler and 6 | preventing performance regressions. 7 | The [rustc-perf](https://github.com/rust-lang/rustc-perf) project provides 8 | several services for testing and tracking performance. 9 | It provides hosted infrastructure for running benchmarks as a service. 10 | At this time, only `x86_64-unknown-linux-gnu` builds are tracked. 11 | 12 | A "perf run" is used to compare the performance of the compiler in different 13 | configurations for a large collection of popular crates. 14 | Different configurations include "fresh builds", builds with incremental compilation, etc. 15 | 16 | The result of a perf run is a comparison between two versions of the compiler 17 | (by their commit hashes). 18 | 19 | ### Automatic perf runs 20 | 21 | After every PR is merged, a suite of benchmarks are run against the compiler. 22 | The results are tracked over time on the website. 23 | Any changes are noted in a comment on the PR. 24 | 25 | ### Manual perf runs 26 | 27 | Additionally, performance tests can be ran before a PR is merged on an as-needed basis. 28 | You should request a perf run if your PR may affect performance, especially if 29 | it can affect performance adversely. 30 | 31 | To evaluate the performance impact of a PR, write this comment on the PR: 32 | 33 | `@bors try @rust-timer queue` 34 | 35 | > **Note**: Only users authorized to do perf runs are allowed to post this comment. 36 | > Teams that are allowed to use it are tracked in the [Teams 37 | > repository](https://github.com/rust-lang/team) with the `perf = true` value 38 | > in the `[permissions]` section (and bors permissions are also required). 39 | > If you are not on one of those teams, feel free to ask for someone to post 40 | > it for you (either on Zulip or ask the assigned reviewer). 41 | 42 | This will first tell bors to do a "try" build which do a full release build 43 | for `x86_64-unknown-linux-gnu`. 44 | After the build finishes, it will place it in the queue to run the performance 45 | suite against it. 46 | After the performance tests finish, the bot will post a comment on the PR with 47 | a summary and a link to a full report. 48 | 49 | If you want to do a perf run for an already built artifact (e.g. for a previous try 50 | build that wasn't benchmarked yet), you can run this instead: 51 | 52 | `@rust-timer build ` 53 | 54 | You cannot benchmark the same artifact twice though. 55 | 56 | More information about the available perf bot commands can be found 57 | [here](https://perf.rust-lang.org/help.html). 58 | 59 | More details about the benchmarking process itself are available in the [perf collector 60 | documentation](https://github.com/rust-lang/rustc-perf/blob/master/collector/README.md). 61 | -------------------------------------------------------------------------------- /src/feature-gates.md: -------------------------------------------------------------------------------- 1 | # Feature Gates 2 | 3 | This chapter is intended to provide basic help for adding, removing, and 4 | modifying feature gates. 5 | 6 | Note that this is specific to *language* feature gates; *library* feature gates use [a different 7 | mechanism][libs-gate]. 8 | 9 | [libs-gate]: ./stability.md 10 | 11 | ## Adding a feature gate 12 | 13 | See ["Stability in code"][adding] in the "Implementing new features" section for instructions. 14 | 15 | [adding]: ./implementing_new_features.md#stability-in-code 16 | 17 | ## Removing a feature gate 18 | 19 | [removing]: #removing-a-feature-gate 20 | 21 | To remove a feature gate, follow these steps: 22 | 23 | 1. Remove the feature gate declaration in `rustc_feature/src/unstable.rs`. 24 | It will look like this: 25 | 26 | ```rust,ignore 27 | /// description of feature 28 | (unstable, $feature_name, "$version", Some($tracking_issue_number)) 29 | ``` 30 | 31 | 2. Add a modified version of the feature gate declaration that you just 32 | removed to `rustc_feature/src/removed.rs`: 33 | 34 | ```rust,ignore 35 | /// description of feature 36 | (removed, $old_feature_name, "$version", Some($tracking_issue_number), 37 | Some("$why_it_was_removed")) 38 | ``` 39 | 40 | 41 | ## Renaming a feature gate 42 | 43 | [renaming]: #renaming-a-feature-gate 44 | 45 | To rename a feature gate, follow these steps (the first two are the same steps 46 | to follow when [removing a feature gate][removing]): 47 | 48 | 1. Remove the old feature gate declaration in `rustc_feature/src/unstable.rs`. 49 | It will look like this: 50 | 51 | ```rust,ignore 52 | /// description of feature 53 | (unstable, $old_feature_name, "$version", Some($tracking_issue_number)) 54 | ``` 55 | 56 | 2. Add a modified version of the old feature gate declaration that you just 57 | removed to `rustc_feature/src/removed.rs`: 58 | 59 | ```rust,ignore 60 | /// description of feature 61 | /// Renamed to `$new_feature_name` 62 | (removed, $old_feature_name, "$version", Some($tracking_issue_number), 63 | Some("renamed to `$new_feature_name`")) 64 | ``` 65 | 66 | 3. Add a feature gate declaration with the new name to 67 | `rustc_feature/src/unstable.rs`. It should look very similar to the old 68 | declaration: 69 | 70 | ```rust,ignore 71 | /// description of feature 72 | (unstable, $new_feature_name, "$version", Some($tracking_issue_number)) 73 | ``` 74 | 75 | 76 | ## Stabilizing a feature 77 | 78 | See ["Updating the feature-gate listing"] in the "Stabilizing Features" chapter 79 | for instructions. There are additional steps you will need to take beyond just 80 | updating the declaration! 81 | 82 | 83 | ["Stability in code"]: ./implementing_new_features.md#stability-in-code 84 | ["Updating the feature-gate listing"]: ./stabilization_guide.md#updating-the-feature-gate-listing 85 | -------------------------------------------------------------------------------- /src/part-5-intro.md: -------------------------------------------------------------------------------- 1 | # From MIR to Binaries 2 | 3 | All of the preceding chapters of this guide have one thing in common: 4 | we never generated any executable machine code at all! 5 | With this chapter, all of that changes. 6 | 7 | So far, 8 | we've shown how the compiler can take raw source code in text format 9 | and transform it into [MIR]. 10 | We have also shown how the compiler does various 11 | analyses on the code to detect things like type or lifetime errors. 12 | Now, we will finally take the MIR and produce some executable machine code. 13 | 14 | [MIR]: ./mir/index.md 15 | 16 | > NOTE: This part of a compiler is often called the _backend_. 17 | > The term is a bit overloaded because in the compiler source, 18 | > it usually refers to the "codegen backend" (i.e. LLVM, Cranelift, or GCC). 19 | > Usually, when you see the word "backend" in this part, 20 | > we are referring to the "codegen backend". 21 | 22 | So what do we need to do? 23 | 24 | 1. First, we need to collect the set of things to generate code for. 25 | In particular, 26 | we need to find out which concrete types to substitute for generic ones, 27 | since we need to generate code for the concrete types. 28 | Generating code for the concrete types 29 | (i.e. emitting a copy of the code for each concrete type) is called _monomorphization_, 30 | so the process of collecting all the concrete types is called _monomorphization collection_. 31 | 2. Next, we need to actually lower the MIR to a codegen IR 32 | (usually LLVM IR) for each concrete type we collected. 33 | 3. Finally, we need to invoke the codegen backend, 34 | which runs a bunch of optimization passes, 35 | generates executable code, 36 | and links together an executable binary. 37 | 38 | [codegen1]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/base/fn.codegen_crate.html 39 | 40 | The code for codegen is actually a bit complex due to a few factors: 41 | 42 | - Support for multiple codegen backends (LLVM, Cranelift, and GCC). 43 | We try to share as much backend code between them as possible, 44 | so a lot of it is generic over the codegen implementation. 45 | This means that there are often a lot of layers of abstraction. 46 | - Codegen happens asynchronously in another thread for performance. 47 | - The actual codegen is done by a third-party library (either of the 3 backends). 48 | 49 | Generally, the [`rustc_codegen_ssa`][ssa] crate contains backend-agnostic code, 50 | while the [`rustc_codegen_llvm`][llvm] crate contains code specific to LLVM codegen. 51 | 52 | [ssa]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html 53 | [llvm]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/index.html 54 | 55 | At a very high level, the entry point is 56 | [`rustc_codegen_ssa::base::codegen_crate`][codegen1]. 57 | This function starts the process discussed in the rest of this chapter. 58 | -------------------------------------------------------------------------------- /src/const-eval.md: -------------------------------------------------------------------------------- 1 | # Constant Evaluation 2 | 3 | Constant evaluation is the process of computing values at compile time. For a 4 | specific item (constant/static/array length) this happens after the MIR for the 5 | item is borrow-checked and optimized. In many cases trying to const evaluate an 6 | item will trigger the computation of its MIR for the first time. 7 | 8 | Prominent examples are: 9 | 10 | * The initializer of a `static` 11 | * Array length 12 | * needs to be known to reserve stack or heap space 13 | * Enum variant discriminants 14 | * needs to be known to prevent two variants from having the same 15 | discriminant 16 | * Patterns 17 | * need to be known to check for overlapping patterns 18 | 19 | Additionally constant evaluation can be used to reduce the workload or binary 20 | size at runtime by precomputing complex operations at compiletime and only 21 | storing the result. 22 | 23 | All uses of constant evaluation can either be categorized as "influencing the type system" 24 | (array lengths, enum variant discriminants, const generic parameters), or as solely being 25 | done to precompute expressions to be used at runtime. 26 | 27 | Constant evaluation can be done by calling the `const_eval_*` functions of `TyCtxt`. 28 | They're the wrappers of the `const_eval` query. 29 | 30 | * `const_eval_global_id_for_typeck` evaluates a constant to a valtree, 31 | so the result value can be further inspected by the compiler. 32 | * `const_eval_global_id` evaluate a constant to an "opaque blob" containing its final value; 33 | this is only useful for codegen backends and the CTFE evaluator engine itself. 34 | * `eval_static_initializer` specifically computes the initial values of a static. 35 | Statics are special; all other functions do not represent statics correctly 36 | and have thus assertions preventing their use on statics. 37 | 38 | The `const_eval_*` functions use a [`ParamEnv`](./param_env/param_env_summary.html) of environment 39 | in which the constant is evaluated (e.g. the function within which the constant is used) 40 | and a [`GlobalId`]. The `GlobalId` is made up of an `Instance` referring to a constant 41 | or static or of an `Instance` of a function and an index into the function's `Promoted` table. 42 | 43 | Constant evaluation returns an [`EvalToValTreeResult`] for type system constants 44 | or [`EvalToConstValueResult`] with either the error, or a representation of the 45 | evaluated constant: a [valtree](mir/index.md#valtrees) or a [MIR constant 46 | value](mir/index.md#mir-constant-values), respectively. 47 | 48 | [`GlobalId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/struct.GlobalId.html 49 | [`EvalToConstValueResult`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToConstValueResult.html 50 | [`EvalToValTreeResult`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToValTreeResult.html 51 | -------------------------------------------------------------------------------- /src/solve/trait-solving.md: -------------------------------------------------------------------------------- 1 | # Trait solving (new) 2 | 3 | This chapter describes how trait solving works with the new WIP solver located in 4 | [`rustc_trait_selection/solve`][solve]. Feel free to also look at the docs for 5 | [the current solver](../traits/resolution.md) and [the chalk solver](../traits/chalk.md) 6 | can be found separately. 7 | 8 | ## Core concepts 9 | 10 | The goal of the trait system is to check whether a given trait bound is satisfied. 11 | Most notably when typechecking the body of - potentially generic - functions. 12 | For example: 13 | 14 | ```rust 15 | fn uses_vec_clone(x: Vec) -> (Vec, Vec) { 16 | (x.clone(), x) 17 | } 18 | ``` 19 | Here the call to `x.clone()` requires us to prove that `Vec` implements `Clone` given 20 | the assumption that `T: Clone` is true. We can assume `T: Clone` as that will be proven by 21 | callers of this function. 22 | 23 | The concept of "prove the `Vec: Clone` with the assumption `T: Clone`" is called a [`Goal`]. 24 | Both `Vec: Clone` and `T: Clone` are represented using [`Predicate`]. There are other 25 | predicates, most notably equality bounds on associated items: ` as IntoIterator>::Item == T`. 26 | See the `PredicateKind` enum for an exhaustive list. A `Goal` is represented as the `predicate` we 27 | have to prove and the `param_env` in which this predicate has to hold. 28 | 29 | We prove goals by checking whether each possible [`Candidate`] applies for the given goal by 30 | recursively proving its nested goals. For a list of possible candidates with examples, look at 31 | [`CandidateSource`]. The most important candidates are `Impl` candidates, i.e. trait implementations 32 | written by the user, and `ParamEnv` candidates, i.e. assumptions in our current environment. 33 | 34 | Looking at the above example, to prove `Vec: Clone` we first use 35 | `impl Clone for Vec`. To use this impl we have to prove the nested 36 | goal that `T: Clone` holds. This can use the assumption `T: Clone` from the `ParamEnv` 37 | which does not have any nested goals. Therefore `Vec: Clone` holds. 38 | 39 | The trait solver can either return success, ambiguity or an error as a [`CanonicalResponse`]. 40 | For success and ambiguity it also returns constraints inference and region constraints. 41 | 42 | [solve]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/index.html 43 | [`Goal`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/solve/struct.Goal.html 44 | [`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html 45 | [`Candidate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/assembly/struct.Candidate.html 46 | [`CandidateSource`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/solve/enum.CandidateSource.html 47 | [`CanonicalResponse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/solve/type.CanonicalResponse.html 48 | -------------------------------------------------------------------------------- /src/appendix/compiler-lecture.md: -------------------------------------------------------------------------------- 1 | # Compiler Lecture Series 2 | 3 | These are videos where various experts explain different parts of the compiler: 4 | 5 | ## General 6 | - [January 2019: Tom Tromey discusses debugging support in rustc](https://www.youtube.com/watch?v=elBxMRSNYr4) 7 | - [June 2019: Responsive compilers - Nicholas Matsakis - PLISS 2019](https://www.youtube.com/watch?v=N6b44kMS6OM) 8 | - [June 2019: Things I Learned (TIL) - Nicholas Matsakis - PLISS 2019](https://www.youtube.com/watch?v=LIYkT3p5gTs) 9 | 10 | ## Rust Analyzer 11 | - [January 2019: How Salsa Works](https://www.youtube.com/watch?v=_muY4HjSqVw) 12 | - [January 2019: Salsa In More Depth](https://www.youtube.com/watch?v=i_IhACacPRY) 13 | - [January 2019: Rust analyzer guide](https://www.youtube.com/watch?v=ANKBNiSWyfc) 14 | - [February 2019: Rust analyzer syntax trees](https://www.youtube.com/watch?v=DGAuLWdCCAI) 15 | - [March 2019: rust-analyzer type-checker overview by flodiebold](https://www.youtube.com/watch?v=Lmp3P9WNL8o) 16 | - [March 2019: RLS 2.0, Salsa, and Name Resolution](https://www.youtube.com/watch?v=Xr-rBqLr-G4) 17 | 18 | ## Type System 19 | - [July 2015: Felix Klock - Rust: A type system you didn't know you wanted - Curry On](https://www.youtube.com/watch?v=Q7lQCgnNWU0) 20 | - [November 2016: Felix Klock - Subtyping in Rust and Clarke's Third Law](https://www.youtube.com/watch?v=fI4RG_uq-WU) 21 | - [February 2019: Universes and Lifetimes](https://www.youtube.com/watch?v=iV1Z0xYXkck) 22 | - [April 2019: Representing types in rustc](https://www.youtube.com/watch?v=c01TsOsr3-c) 23 | - [March 2019: RFC #2229 Disjoint Field Capture plan](https://www.youtube.com/watch?v=UTXOptVMuIc) 24 | 25 | ## Closures 26 | - [October 2018: closures and upvar capture](https://www.youtube.com/watch?v=fMopdkn5-Xw) 27 | - [October 2018: blitzerr closure upvar tys](https://www.youtube.com/watch?v=pLmVhSB-z4s) 28 | - [January 2019: Convert Closure Upvar Representation to Tuples with blitzerr](https://www.youtube.com/watch?v=2QCuNtISoYc) 29 | 30 | ## Chalk 31 | - [July 2018: Coherence in Chalk by Sunjay Varma - Bay Area Rust Meetup](https://www.youtube.com/watch?v=rZqS4bLPL24) 32 | - [March 2019: rustc-chalk integration overview](https://www.youtube.com/watch?v=MBWtbDifPeU) 33 | - [April 2019: How the chalk-engine crate works](https://www.youtube.com/watch?v=Ny2928cGDoM) 34 | - [May 2019: How the chalk-engine crate works 2](https://www.youtube.com/watch?v=hmV66tB79LM) 35 | 36 | ## Polonius 37 | - [March 2019: Polonius-rustc walkthrough](https://www.youtube.com/watch?v=i5KdU0ieb_A) 38 | - [May 2019: Polonius WG: Initialization and move tracking](https://www.youtube.com/watch?v=ilv9V-328HI) 39 | 40 | ## Miri 41 | - [March 2019: oli-obk on miri and constant evaluation](https://www.youtube.com/watch?v=5Pm2C1YXrvM) 42 | 43 | ## Async 44 | - [February 2019: async-await implementation plans](https://www.youtube.com/watch?v=xe2_whJWBC0) 45 | - [April 2019: async-await region inferencer](https://www.youtube.com/watch?v=hlOxfkUDLPQ) 46 | 47 | ## Code Generation 48 | - [January 2019: Cranelift](https://www.youtube.com/watch?v=9OIA7DTFQWU) 49 | -------------------------------------------------------------------------------- /src/rustc-driver.md: -------------------------------------------------------------------------------- 1 | # `rustc_driver` and `rustc_interface` 2 | 3 | The [`rustc_driver`] is essentially `rustc`'s `main()` function. It acts as 4 | the glue for running the various phases of the compiler in the correct order, 5 | using the interface defined in the [`rustc_interface`] crate. 6 | 7 | The `rustc_interface` crate provides external users with an (unstable) API 8 | for running code at particular times during the compilation process, allowing 9 | third parties to effectively use `rustc`'s internals as a library for 10 | analyzing a crate or emulating the compiler in-process (e.g. rustdoc). 11 | 12 | For those using `rustc` as a library, the [`rustc_interface::run_compiler()`][i_rc] 13 | function is the main entrypoint to the compiler. It takes a configuration for the compiler 14 | and a closure that takes a [`Compiler`]. `run_compiler` creates a `Compiler` from the 15 | configuration and passes it to the closure. Inside the closure, you can use the `Compiler` 16 | to drive queries to compile a crate and get the results. This is what the `rustc_driver` does too. 17 | You can see a minimal example of how to use `rustc_interface` [here][example]. 18 | 19 | You can see what queries are currently available through the rustdocs for [`Compiler`]. 20 | You can see an example of how to use them by looking at the `rustc_driver` implementation, 21 | specifically the [`rustc_driver::run_compiler` function][rd_rc] (not to be confused with 22 | [`rustc_interface::run_compiler`][i_rc]). The `rustc_driver::run_compiler` function 23 | takes a bunch of command-line args and some other configurations and 24 | drives the compilation to completion. 25 | 26 | `rustc_driver::run_compiler` also takes a [`Callbacks`][cb], 27 | a trait that allows for custom compiler configuration, 28 | as well as allowing some custom code run after different phases of the compilation. 29 | 30 | > **Warning:** By its very nature, the internal compiler APIs are always going 31 | > to be unstable. That said, we do try not to break things unnecessarily. 32 | 33 | 34 | [cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html 35 | [rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver_impl/fn.run_compiler.html 36 | [i_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/fn.run_compiler.html 37 | [example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-example.rs 38 | [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html 39 | [`rustc_driver`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/ 40 | [`Compiler`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Compiler.html 41 | [`Session`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html 42 | [`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html 43 | [`SourceMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/source_map/struct.SourceMap.html 44 | [stupid-stats]: https://github.com/nrc/stupid-stats 45 | [Appendix A]: appendix/stupid-stats.html 46 | -------------------------------------------------------------------------------- /src/borrow_check.md: -------------------------------------------------------------------------------- 1 | # MIR borrow check 2 | 3 | The borrow check is Rust's "secret sauce" – it is tasked with 4 | enforcing a number of properties: 5 | 6 | - That all variables are initialized before they are used. 7 | - That you can't move the same value twice. 8 | - That you can't move a value while it is borrowed. 9 | - That you can't access a place while it is mutably borrowed (except through 10 | the reference). 11 | - That you can't mutate a place while it is immutably borrowed. 12 | - etc 13 | 14 | The borrow checker operates on the MIR. An older implementation operated on the 15 | HIR. Doing borrow checking on MIR has several advantages: 16 | 17 | - The MIR is *far* less complex than the HIR; the radical desugaring 18 | helps prevent bugs in the borrow checker. (If you're curious, you 19 | can see 20 | [a list of bugs that the MIR-based borrow checker fixes here][47366].) 21 | - Even more importantly, using the MIR enables ["non-lexical lifetimes"][nll], 22 | which are regions derived from the control-flow graph. 23 | 24 | [47366]: https://github.com/rust-lang/rust/issues/47366 25 | [nll]: https://rust-lang.github.io/rfcs/2094-nll.html 26 | 27 | ### Major phases of the borrow checker 28 | 29 | The borrow checker source is found in 30 | [the `rustc_borrowck` crate][b_c]. The main entry point is 31 | the [`mir_borrowck`] query. 32 | 33 | [b_c]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/index.html 34 | [`mir_borrowck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/fn.mir_borrowck.html 35 | 36 | - We first create a **local copy** of the MIR. In the coming steps, 37 | we will modify this copy in place to modify the types and things to 38 | include references to the new regions that we are computing. 39 | - We then invoke [`replace_regions_in_mir`] to modify our local MIR. 40 | Among other things, this function will replace all of the [regions](./appendix/glossary.md#region) 41 | in the MIR with fresh [inference variables](./appendix/glossary.md#inf-var). 42 | - Next, we perform a number of 43 | [dataflow analyses](./appendix/background.md#dataflow) that 44 | compute what data is moved and when. 45 | - We then do a [second type check](borrow_check/type_check.md) across the MIR: 46 | the purpose of this type check is to determine all of the constraints between 47 | different regions. 48 | - Next, we do [region inference](borrow_check/region_inference.md), which computes 49 | the values of each region — basically, the points in the control-flow graph where 50 | each lifetime must be valid according to the constraints we collected. 51 | - At this point, we can compute the "borrows in scope" at each point. 52 | - Finally, we do a second walk over the MIR, looking at the actions it 53 | does and reporting errors. For example, if we see a statement like 54 | `*a + 1`, then we would check that the variable `a` is initialized 55 | and that it is not mutably borrowed, as either of those would 56 | require an error to be reported. Doing this check requires the results of all 57 | the previous analyses. 58 | 59 | [`replace_regions_in_mir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/nll/fn.replace_regions_in_mir.html 60 | -------------------------------------------------------------------------------- /src/tests/suggest-tests.md: -------------------------------------------------------------------------------- 1 | # Suggest tests tool 2 | 3 | This chapter is about the internals of and contribution instructions for the 4 | `suggest-tests` tool. For a high-level overview of the tool, see 5 | [this section](../building/suggested.md#x-suggest). This tool is currently in a 6 | beta state and is tracked by [this](https://github.com/rust-lang/rust/issues/109933) 7 | issue on Github. Currently the number of tests it will suggest are very limited 8 | in scope, we are looking to expand this (contributions welcome!). 9 | 10 | ## Internals 11 | 12 | The tool is defined in a separate crate ([`src/tools/suggest-tests`](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests)) 13 | which outputs suggestions which are parsed by a shim in bootstrap 14 | ([`src/bootstrap/src/core/build_steps/suggest.rs`](https://github.com/rust-lang/rust/blob/master/src/bootstrap/src/core/build_steps/suggest.rs)). 15 | The only notable thing the bootstrap shim does is (when invoked with the 16 | `--run` flag) use bootstrap's internal mechanisms to create a new `Builder` and 17 | uses it to invoke the suggested commands. The `suggest-tests` crate is where the 18 | fun happens, two kinds of suggestions are defined: "static" and "dynamic" 19 | suggestions. 20 | 21 | ### Static suggestions 22 | 23 | Defined [here](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests/src/static_suggestions.rs). 24 | Static suggestions are simple: they are just [globs](https://crates.io/crates/glob) 25 | which map to a `x` command. In `suggest-tests`, this is implemented with a 26 | simple `macro_rules` macro. 27 | 28 | ### Dynamic suggestions 29 | 30 | Defined [here](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests/src/dynamic_suggestions.rs). 31 | These are more complicated than static suggestions and are implemented as 32 | functions with the following signature: `fn(&Path) -> Vec`. In 33 | other words, each suggestion takes a path to a modified file and (after running 34 | arbitrary Rust code) can return any number of suggestions, or none. Dynamic 35 | suggestions are useful for situations where fine-grained control over 36 | suggestions is needed. For example, modifications to the `compiler/xyz/` path 37 | should trigger the `x test compiler/xyz` suggestion. In the future, dynamic 38 | suggestions might even read file contents to determine if (what) tests should 39 | run. 40 | 41 | ## Adding a suggestion 42 | 43 | The following steps should serve as a rough guide to add suggestions to 44 | `suggest-tests` (very welcome!): 45 | 46 | 1. Determine the rules for your suggestion. Is it simple and operates only on 47 | a single path or does it match globs? Does it need fine-grained control over 48 | the resulting command or does "one size fit all"? 49 | 2. Based on the previous step, decide if your suggestion should be implemented 50 | as either static or dynamic. 51 | 3. Implement the suggestion. If it is dynamic then a test is highly recommended, 52 | to verify that your logic is correct and to give an example of the suggestion. 53 | See the [tests.rs](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests/src/tests.rs) 54 | file. 55 | 4. Open a PR implementing your suggestion. **(TODO: add example PR)** 56 | -------------------------------------------------------------------------------- /src/queries/example-0.counts.txt: -------------------------------------------------------------------------------- 1 | translation,1,0.891 2 | symbol_name,2658,0.733 3 | def_symbol_name,2556,0.268 4 | item_attrs,5566,0.162 5 | type_of,6922,0.117 6 | generics_of,8020,0.084 7 | serialize dep graph,1,0.079 8 | relevant_trait_impls_for,50,0.063 9 | def_span,24875,0.061 10 | expansion,1,0.059 11 | const checking,1,0.055 12 | adt_def,1141,0.048 13 | trait_impls_of,32,0.045 14 | is_copy_raw,47,0.045 15 | is_foreign_item,2638,0.042 16 | fn_sig,2172,0.033 17 | adt_dtorck_constraint,2,0.023 18 | impl_trait_ref,2434,0.023 19 | typeck_tables_of,29,0.022 20 | item-bodies checking,1,0.017 21 | typeck_item_bodies,1,0.017 22 | is_default_impl,2320,0.017 23 | borrow checking,1,0.014 24 | borrowck,4,0.014 25 | mir_validated,4,0.013 26 | adt_destructor,10,0.012 27 | layout_raw,258,0.010 28 | load_dep_graph,1,0.007 29 | item-types checking,1,0.005 30 | mir_const,2,0.005 31 | name resolution,1,0.004 32 | is_object_safe,35,0.003 33 | is_sized_raw,89,0.003 34 | parsing,1,0.003 35 | is_freeze_raw,11,0.001 36 | privacy checking,1,0.001 37 | privacy_access_levels,5,0.001 38 | resolving dependency formats,1,0.001 39 | adt_sized_constraint,9,0.001 40 | wf checking,1,0.001 41 | liveness checking,1,0.001 42 | compute_incremental_hashes_map,1,0.001 43 | match checking,1,0.001 44 | type collecting,1,0.001 45 | param_env,31,0.000 46 | effect checking,1,0.000 47 | trait_def,140,0.000 48 | lowering ast -> hir,1,0.000 49 | predicates_of,70,0.000 50 | extern_crate,319,0.000 51 | lifetime resolution,1,0.000 52 | is_const_fn,6,0.000 53 | intrinsic checking,1,0.000 54 | translation item collection,1,0.000 55 | impl_polarity,15,0.000 56 | creating allocators,1,0.000 57 | language item collection,1,0.000 58 | crate injection,1,0.000 59 | early lint checks,1,0.000 60 | indexing hir,1,0.000 61 | maybe creating a macro crate,1,0.000 62 | coherence checking,1,0.000 63 | optimized_mir,6,0.000 64 | is_panic_runtime,33,0.000 65 | associated_item_def_ids,7,0.000 66 | needs_drop_raw,10,0.000 67 | lint checking,1,0.000 68 | complete gated feature checking,1,0.000 69 | stability index,1,0.000 70 | region_maps,11,0.000 71 | super_predicates_of,8,0.000 72 | coherent_trait,2,0.000 73 | AST validation,1,0.000 74 | loop checking,1,0.000 75 | static item recursion checking,1,0.000 76 | variances_of,11,0.000 77 | associated_item,5,0.000 78 | plugin loading,1,0.000 79 | looking for plugin registrar,1,0.000 80 | stability checking,1,0.000 81 | describe_def,15,0.000 82 | variance testing,1,0.000 83 | codegen unit partitioning,1,0.000 84 | looking for entry point,1,0.000 85 | checking for inline asm in case the target doesn't support it,1,0.000 86 | inherent_impls,1,0.000 87 | crate_inherent_impls,1,0.000 88 | trait_of_item,7,0.000 89 | crate_inherent_impls_overlap_check,1,0.000 90 | attribute checking,1,0.000 91 | internalize symbols,1,0.000 92 | impl wf inference,1,0.000 93 | death checking,1,0.000 94 | reachability checking,1,0.000 95 | reachable_set,1,0.000 96 | is_exported_symbol,3,0.000 97 | is_mir_available,2,0.000 98 | unused lib feature checking,1,0.000 99 | maybe building test harness,1,0.000 100 | recursion limit,1,0.000 101 | write allocator module,1,0.000 102 | assert dep graph,1,0.000 103 | plugin registration,1,0.000 104 | write metadata,1,0.000 105 | -------------------------------------------------------------------------------- /src/tests/docker.md: -------------------------------------------------------------------------------- 1 | # Testing with Docker 2 | 3 | The Rust tree includes [Docker] image definitions for the platforms used on 4 | GitHub Actions in [`src/ci/docker`]. 5 | The script [`src/ci/docker/run.sh`] is used to build the Docker image, run it, 6 | build Rust within the image, and run the tests. 7 | 8 | You can run these images on your local development machine. This can be 9 | helpful to test environments different from your local system. First you will 10 | need to install Docker on a Linux, Windows, or macOS system (typically Linux 11 | will be much faster than Windows or macOS because the latter use virtual 12 | machines to emulate a Linux environment). To enter interactive mode which will 13 | start a bash shell in the container, run `src/ci/docker/run.sh --dev ` 14 | where `` is one of the directory names in `src/ci/docker` (for example 15 | `x86_64-gnu` is a fairly standard Ubuntu environment). 16 | 17 | The docker script will mount your local Rust source tree in read-only mode, 18 | and an `obj` directory in read-write mode. All of the compiler artifacts will 19 | be stored in the `obj` directory. The shell will start out in the `obj` 20 | directory. From there, you can run `../src/ci/run.sh` which will run the build 21 | as defined by the image. 22 | 23 | Alternatively, you can run individual commands to do specific tasks. For 24 | example, you can run `../x test tests/ui` to just run UI tests. 25 | Note that there is some configuration in the [`src/ci/run.sh`] script that you 26 | may need to recreate. Particularly, set `submodules = false` in your 27 | `config.toml` so that it doesn't attempt to modify the read-only directory. 28 | 29 | Some additional notes about using the Docker images: 30 | 31 | - Some of the std tests require IPv6 support. Docker on Linux seems to have it 32 | disabled by default. Run the commands in [`enable-docker-ipv6.sh`] to enable 33 | IPv6 before creating the container. This only needs to be done once. 34 | - The container will be deleted automatically when you exit the shell, however 35 | the build artifacts persist in the `obj` directory. If you are switching 36 | between different Docker images, the artifacts from previous environments 37 | stored in the `obj` directory may confuse the build system. Sometimes you 38 | will need to delete parts or all of the `obj` directory before building 39 | inside the container. 40 | - The container is bare-bones, with only a minimal set of packages. You may 41 | want to install some things like `apt install less vim`. 42 | - You can open multiple shells in the container. First you need the container 43 | name (a short hash), which is displayed in the shell prompt, or you can run 44 | `docker container ls` outside of the container to list the available 45 | containers. With the container name, run `docker exec -it 46 | /bin/bash` where `` is the container name like `4ba195e95cef`. 47 | 48 | [Docker]: https://www.docker.com/ 49 | [`src/ci/docker`]: https://github.com/rust-lang/rust/tree/master/src/ci/docker 50 | [`src/ci/docker/run.sh`]: https://github.com/rust-lang/rust/blob/master/src/ci/docker/run.sh 51 | [`src/ci/run.sh`]: https://github.com/rust-lang/rust/blob/master/src/ci/run.sh 52 | [`enable-docker-ipv6.sh`]: https://github.com/rust-lang/rust/blob/master/src/ci/scripts/enable-docker-ipv6.sh 53 | -------------------------------------------------------------------------------- /src/traits/caching.md: -------------------------------------------------------------------------------- 1 | # Caching and subtle considerations therewith 2 | 3 | In general, we attempt to cache the results of trait selection. This 4 | is a somewhat complex process. Part of the reason for this is that we 5 | want to be able to cache results even when all the types in the trait 6 | reference are not fully known. In that case, it may happen that the 7 | trait selection process is also influencing type variables, so we have 8 | to be able to not only cache the *result* of the selection process, 9 | but *replay* its effects on the type variables. 10 | 11 | ## An example 12 | 13 | The high-level idea of how the cache works is that we first replace 14 | all unbound inference variables with placeholder versions. Therefore, 15 | if we had a trait reference `usize : Foo<$t>`, where `$t` is an unbound 16 | inference variable, we might replace it with `usize : Foo<$0>`, where 17 | `$0` is a placeholder type. We would then look this up in the cache. 18 | 19 | If we found a hit, the hit would tell us the immediate next step to 20 | take in the selection process (e.g. apply impl #22, or apply where 21 | clause `X : Foo`). 22 | 23 | On the other hand, if there is no hit, we need to go through the [selection 24 | process] from scratch. Suppose, we come to the conclusion that the only 25 | possible impl is this one, with def-id 22: 26 | 27 | [selection process]: ./resolution.html#selection 28 | 29 | ```rust,ignore 30 | impl Foo for usize { ... } // Impl #22 31 | ``` 32 | 33 | We would then record in the cache `usize : Foo<$0> => ImplCandidate(22)`. Next 34 | we would [confirm] `ImplCandidate(22)`, which would (as a side-effect) unify 35 | `$t` with `isize`. 36 | 37 | [confirm]: ./resolution.html#confirmation 38 | 39 | Now, at some later time, we might come along and see a `usize : 40 | Foo<$u>`. When replaced with a placeholder, this would yield `usize : Foo<$0>`, just as 41 | before, and hence the cache lookup would succeed, yielding 42 | `ImplCandidate(22)`. We would confirm `ImplCandidate(22)` which would 43 | (as a side-effect) unify `$u` with `isize`. 44 | 45 | ## Where clauses and the local vs global cache 46 | 47 | One subtle interaction is that the results of trait lookup will vary 48 | depending on what where clauses are in scope. Therefore, we actually 49 | have *two* caches, a local and a global cache. The local cache is 50 | attached to the [`ParamEnv`], and the global cache attached to the 51 | [`tcx`]. We use the local cache whenever the result might depend on the 52 | where clauses that are in scope. The determination of which cache to 53 | use is done by the method `pick_candidate_cache` in `select.rs`. At 54 | the moment, we use a very simple, conservative rule: if there are any 55 | where-clauses in scope, then we use the local cache. We used to try 56 | and draw finer-grained distinctions, but that led to a series of 57 | annoying and weird bugs like [#22019] and [#18290]. This simple rule seems 58 | to be pretty clearly safe and also still retains a very high hit rate 59 | (~95% when compiling rustc). 60 | 61 | **TODO**: it looks like `pick_candidate_cache` no longer exists. In 62 | general, is this section still accurate at all? 63 | 64 | [`ParamEnv`]: ../param_env/param_env_summary.html 65 | [`tcx`]: ../ty.html 66 | [#18290]: https://github.com/rust-lang/rust/issues/18290 67 | [#22019]: https://github.com/rust-lang/rust/issues/22019 68 | -------------------------------------------------------------------------------- /src/lang-items.md: -------------------------------------------------------------------------------- 1 | # Lang items 2 | 3 | The compiler has certain pluggable operations; that is, functionality that isn't hard-coded into 4 | the language, but is implemented in libraries, with a special marker to tell the compiler it 5 | exists. The marker is the attribute `#[lang = "..."]`, and there are various different values of 6 | `...`, i.e. various different 'lang items'. 7 | 8 | Many such lang items can be implemented only in one sensible way, such as `add` (`trait 9 | core::ops::Add`) or `future_trait` (`trait core::future::Future`). Others can be overridden to 10 | achieve some specific goals; for example, you can control your binary's entrypoint. 11 | 12 | Features provided by lang items include: 13 | 14 | - overloadable operators via traits: the traits corresponding to the 15 | `==`, `<`, dereference (`*`), `+`, etc. operators are all 16 | marked with lang items; those specific four are `eq`, `ord`, 17 | `deref`, and `add` respectively. 18 | - panicking and stack unwinding; the `eh_personality`, `panic` and 19 | `panic_bounds_checks` lang items. 20 | - the traits in `std::marker` used to indicate properties of types used by the compiler; 21 | lang items `send`, `sync` and `copy`. 22 | - the special marker types used for variance indicators found in 23 | `core::marker`; lang item `phantom_data`. 24 | 25 | Lang items are loaded lazily by the compiler; e.g. if one never uses `Box` 26 | then there is no need to define functions for `exchange_malloc` and 27 | `box_free`. `rustc` will emit an error when an item is needed but not found 28 | in the current crate or any that it depends on. 29 | 30 | Most lang items are defined by the `core` library, but if you're trying to build an 31 | executable with `#![no_std]`, you'll still need to define a few lang items that are 32 | usually provided by `std`. 33 | 34 | ## Retrieving a language item 35 | 36 | You can retrieve lang items by calling [`tcx.lang_items()`]. 37 | 38 | Here's a small example of retrieving the `trait Sized {}` language item: 39 | 40 | ```rust 41 | // Note that in case of `#![no_core]`, the trait is not available. 42 | if let Some(sized_trait_def_id) = tcx.lang_items().sized_trait() { 43 | // do something with `sized_trait_def_id` 44 | } 45 | ``` 46 | 47 | Note that `sized_trait()` returns an `Option`, not the `DefId` itself. 48 | That's because language items are defined in the standard library, so if someone compiles with 49 | `#![no_core]` (or for some lang items, `#![no_std]`), the lang item may not be present. 50 | You can either: 51 | 52 | - Give a hard error if the lang item is necessary to continue (don't panic, since this can happen in 53 | user code). 54 | - Proceed with limited functionality, by just omitting whatever you were going to do with the 55 | `DefId`. 56 | 57 | [`tcx.lang_items()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.lang_items 58 | 59 | ## List of all language items 60 | 61 | You can find language items in the following places: 62 | - An exhaustive reference in the compiler documentation: [`rustc_hir::LangItem`] 63 | - An auto-generated list with source locations by using ripgrep: `rg '#\[.*lang =' library/` 64 | 65 | Note that language items are explicitly unstable and may change in any new release. 66 | 67 | [`rustc_hir::LangItem`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/lang_items/enum.LangItem.html 68 | -------------------------------------------------------------------------------- /src/rustbot.md: -------------------------------------------------------------------------------- 1 | # Mastering @rustbot 2 | 3 | `@rustbot` (also known as `triagebot`) is a utility robot that is mostly used to 4 | allow any contributor to achieve certain tasks that would normally require GitHub 5 | membership to the `rust-lang` organization. Its most interesting features for 6 | contributors to `rustc` are issue claiming and relabeling. 7 | 8 | ## Issue claiming 9 | 10 | `@rustbot` exposes a command that allows anyone to assign an issue to themselves. 11 | If you see an issue you want to work on, you can send the following message as a 12 | comment on the issue at hand: 13 | 14 | @rustbot claim 15 | 16 | This will tell `@rustbot` to assign the issue to you if it has no assignee yet. 17 | Note that because of some GitHub restrictions, you may be assigned indirectly, 18 | i.e. `@rustbot` will assign itself as a placeholder and edit the top comment to 19 | reflect the fact that the issue is now assigned to you. 20 | 21 | If you want to unassign from an issue, `@rustbot` has a different command: 22 | 23 | @rustbot release-assignment 24 | 25 | ## Issue relabeling 26 | 27 | Changing labels for an issue or PR is also normally reserved for members of the 28 | organization. However, `@rustbot` allows you to relabel an issue yourself, only 29 | with a few restrictions. This is mostly useful in two cases: 30 | 31 | **Helping with issue triage**: Rust's issue tracker has more than 5,000 open 32 | issues at the time of this writing, so labels are the most powerful tool that we 33 | have to keep it as tidy as possible. You don't need to spend hours in the issue tracker 34 | to triage issues, but if you open an issue, you should feel free to label it if 35 | you are comfortable with doing it yourself. 36 | 37 | **Updating the status of a PR**: We use "status labels" to reflect the status of 38 | PRs. For example, if your PR has merge conflicts, it will automatically be assigned 39 | the `S-waiting-on-author`, and reviewers might not review it until you rebase your 40 | PR. Once you do rebase your branch, you should change the labels yourself to remove 41 | the `S-waiting-on-author` label and add back `S-waiting-on-review`. In this case, 42 | the `@rustbot` command will look like this: 43 | 44 | @rustbot label -S-waiting-on-author +S-waiting-on-review 45 | 46 | The syntax for this command is pretty loose, so there are other variants of this 47 | command invocation. There are also some shortcuts to update labels, 48 | for instance `@rustbot ready` will do the same thing with above command. 49 | For more details, see [the docs page about labeling][labeling] and [shortcuts][shortcuts]. 50 | 51 | [labeling]: https://forge.rust-lang.org/triagebot/labeling.html 52 | [shortcuts]: https://forge.rust-lang.org/triagebot/shortcuts.html 53 | 54 | ## Other commands 55 | 56 | If you are interested in seeing what `@rustbot` is capable of, check out its [documentation], 57 | which is meant as a reference for the bot and should be kept up to date every time the 58 | bot gets an upgrade. 59 | 60 | `@rustbot` is maintained by the Release team. If you have any feedback regarding 61 | existing commands or suggestions for new commands, feel free to reach out 62 | [on Zulip][zulip] or file an issue in [the triagebot repository][repo] 63 | 64 | [documentation]: https://forge.rust-lang.org/triagebot/index.html 65 | [zulip]: https://rust-lang.zulipchat.com/#narrow/stream/224082-t-release.2Ftriagebot 66 | [repo]: https://github.com/rust-lang/triagebot/ 67 | -------------------------------------------------------------------------------- /src/backend/lowering-mir.md: -------------------------------------------------------------------------------- 1 | # Lowering MIR to a Codegen IR 2 | 3 | Now that we have a list of symbols to generate from the collector, we need to 4 | generate some sort of codegen IR. In this chapter, we will assume LLVM IR, 5 | since that's what rustc usually uses. The actual monomorphization is performed 6 | as we go, while we do the translation. 7 | 8 | Recall that the backend is started by 9 | [`rustc_codegen_ssa::base::codegen_crate`][codegen1]. Eventually, this reaches 10 | [`rustc_codegen_ssa::mir::codegen_mir`][codegen2], which does the lowering from 11 | MIR to LLVM IR. 12 | 13 | [codegen1]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/base/fn.codegen_crate.html 14 | [codegen2]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/fn.codegen_mir.html 15 | 16 | The code is split into modules which handle particular MIR primitives: 17 | 18 | - [`rustc_codegen_ssa::mir::block`][mirblk] will deal with translating 19 | blocks and their terminators. The most complicated and also the most 20 | interesting thing this module does is generating code for function calls, 21 | including the necessary unwinding handling IR. 22 | - [`rustc_codegen_ssa::mir::statement`][mirst] translates MIR statements. 23 | - [`rustc_codegen_ssa::mir::operand`][mirop] translates MIR operands. 24 | - [`rustc_codegen_ssa::mir::place`][mirpl] translates MIR place references. 25 | - [`rustc_codegen_ssa::mir::rvalue`][mirrv] translates MIR r-values. 26 | 27 | [mirblk]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/block/index.html 28 | [mirst]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/statement/index.html 29 | [mirop]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/operand/index.html 30 | [mirpl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/place/index.html 31 | [mirrv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/rvalue/index.html 32 | 33 | Before a function is translated a number of simple and primitive analysis 34 | passes will run to help us generate simpler and more efficient LLVM IR. An 35 | example of such an analysis pass would be figuring out which variables are 36 | SSA-like, so that we can translate them to SSA directly rather than relying on 37 | LLVM's `mem2reg` for those variables. The analysis can be found in 38 | [`rustc_codegen_ssa::mir::analyze`][mirana]. 39 | 40 | [mirana]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/analyze/index.html 41 | 42 | Usually a single MIR basic block will map to a LLVM basic block, with very few 43 | exceptions: intrinsic or function calls and less basic MIR statements like 44 | `assert` can result in multiple basic blocks. This is a perfect lede into the 45 | non-portable LLVM-specific part of the code generation. Intrinsic generation is 46 | fairly easy to understand as it involves very few abstraction levels in between 47 | and can be found in [`rustc_codegen_llvm::intrinsic`][llvmint]. 48 | 49 | [llvmint]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/intrinsic/index.html 50 | 51 | Everything else will use the [builder interface][builder]. This is the code that gets 52 | called in the [`rustc_codegen_ssa::mir::*`][ssamir] modules discussed above. 53 | 54 | [builder]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/builder/index.html 55 | [ssamir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/index.html 56 | 57 | > TODO: discuss how constants are generated 58 | -------------------------------------------------------------------------------- /examples/rustc-driver-getting-diagnostics.rs: -------------------------------------------------------------------------------- 1 | #![feature(rustc_private)] 2 | 3 | extern crate rustc_driver; 4 | extern crate rustc_error_codes; 5 | extern crate rustc_errors; 6 | extern crate rustc_hash; 7 | extern crate rustc_hir; 8 | extern crate rustc_interface; 9 | extern crate rustc_session; 10 | extern crate rustc_span; 11 | 12 | use rustc_errors::{ 13 | emitter::Emitter, registry, translation::Translate, DiagCtxt, DiagInner, FluentBundle, 14 | }; 15 | use rustc_session::config; 16 | use rustc_span::source_map::SourceMap; 17 | 18 | use std::{ 19 | path, process, str, 20 | sync::{Arc, Mutex}, 21 | }; 22 | 23 | struct DebugEmitter { 24 | source_map: Arc, 25 | diagnostics: Arc>>, 26 | } 27 | 28 | impl Translate for DebugEmitter { 29 | fn fluent_bundle(&self) -> Option<&Arc> { 30 | None 31 | } 32 | 33 | fn fallback_fluent_bundle(&self) -> &FluentBundle { 34 | panic!("this emitter should not translate message") 35 | } 36 | } 37 | 38 | impl Emitter for DebugEmitter { 39 | fn emit_diagnostic(&mut self, diag: DiagInner) { 40 | self.diagnostics.lock().unwrap().push(diag); 41 | } 42 | 43 | fn source_map(&self) -> Option<&Arc> { 44 | Some(&self.source_map) 45 | } 46 | } 47 | 48 | fn main() { 49 | let out = process::Command::new("rustc") 50 | .arg("--print=sysroot") 51 | .current_dir(".") 52 | .output() 53 | .unwrap(); 54 | let sysroot = str::from_utf8(&out.stdout).unwrap().trim(); 55 | let buffer: Arc>> = Arc::default(); 56 | let diagnostics = buffer.clone(); 57 | let config = rustc_interface::Config { 58 | opts: config::Options { 59 | maybe_sysroot: Some(path::PathBuf::from(sysroot)), 60 | ..config::Options::default() 61 | }, 62 | // This program contains a type error. 63 | input: config::Input::Str { 64 | name: rustc_span::FileName::Custom("main.rs".into()), 65 | input: " 66 | fn main() { 67 | let x: &str = 1; 68 | } 69 | " 70 | .into(), 71 | }, 72 | crate_cfg: Vec::new(), 73 | crate_check_cfg: Vec::new(), 74 | output_dir: None, 75 | output_file: None, 76 | file_loader: None, 77 | locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES, 78 | lint_caps: rustc_hash::FxHashMap::default(), 79 | psess_created: Some(Box::new(|parse_sess| { 80 | parse_sess.dcx = DiagCtxt::new(Box::new(DebugEmitter { 81 | source_map: parse_sess.clone_source_map(), 82 | diagnostics, 83 | })) 84 | })), 85 | register_lints: None, 86 | override_queries: None, 87 | registry: registry::Registry::new(rustc_errors::codes::DIAGNOSTICS), 88 | make_codegen_backend: None, 89 | expanded_args: Vec::new(), 90 | ice_file: None, 91 | hash_untracked_state: None, 92 | using_internal_features: Arc::default(), 93 | }; 94 | rustc_interface::run_compiler(config, |compiler| { 95 | compiler.enter(|queries| { 96 | queries.global_ctxt().unwrap().enter(|tcx| { 97 | // Run the analysis phase on the local crate to trigger the type error. 98 | let _ = tcx.analysis(()); 99 | }); 100 | }); 101 | }); 102 | // Read buffered diagnostics. 103 | buffer.lock().unwrap().iter().for_each(|diagnostic| { 104 | println!("{diagnostic:#?}"); 105 | }); 106 | } 107 | -------------------------------------------------------------------------------- /src/borrow_check/type_check.md: -------------------------------------------------------------------------------- 1 | # The MIR type-check 2 | 3 | A key component of the borrow check is the 4 | [MIR type-check](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/index.html). 5 | This check walks the MIR and does a complete "type check" -- the same 6 | kind you might find in any other language. In the process of doing 7 | this type-check, we also uncover the region constraints that apply to 8 | the program. 9 | 10 | TODO -- elaborate further? Maybe? :) 11 | 12 | ## User types 13 | 14 | At the start of MIR type-check, we replace all regions in the body with new unconstrained regions. 15 | However, this would cause us to accept the following program: 16 | ```rust 17 | fn foo<'a>(x: &'a u32) { 18 | let y: &'static u32 = x; 19 | } 20 | ``` 21 | By erasing the lifetimes in the type of `y` we no longer know that it is supposed to be `'static`, 22 | ignoring the intentions of the user. 23 | 24 | To deal with this we remember all places where the user explicitly mentioned a type during 25 | HIR type-check as [`CanonicalUserTypeAnnotations`][annot]. 26 | 27 | There are two different annotations we care about: 28 | - explicit type ascriptions, e.g. `let y: &'static u32` results in `UserType::Ty(&'static u32)`. 29 | - explicit generic arguments, e.g. `x.foo<&'a u32, Vec>` 30 | results in `UserType::TypeOf(foo_def_id, [&'a u32, Vec])`. 31 | 32 | As we do not want the region inference from the HIR type-check to influence MIR typeck, 33 | we store the user type right after lowering it from the HIR. 34 | This means that it may still contain inference variables, 35 | which is why we are using **canonical** user type annotations. 36 | We replace all inference variables with existential bound variables instead. 37 | Something like `let x: Vec<_>` would therefore result in `exists UserType::Ty(Vec)`. 38 | 39 | A pattern like `let Foo(x): Foo<&'a u32>` has a user type `Foo<&'a u32>` but 40 | the actual type of `x` should only be `&'a u32`. For this, we use a [`UserTypeProjection`][proj]. 41 | 42 | In the MIR, we deal with user types in two slightly different ways. 43 | 44 | Given a MIR local corresponding to a variable in a pattern which has an explicit type annotation, 45 | we require the type of that local to be equal to the type of the [`UserTypeProjection`][proj]. 46 | This is directly stored in the [`LocalDecl`][decl]. 47 | 48 | We also constrain the type of scrutinee expressions, e.g. the type of `x` in `let _: &'a u32 = x;`. 49 | Here `T_x` only has to be a subtype of the user type, so we instead use 50 | [`StatementKind::AscribeUserType`][stmt] for that. 51 | 52 | Note that we do not directly use the user type as the MIR typechecker 53 | doesn't really deal with type and const inference variables. We instead store the final 54 | [`inferred_type`][inf] from the HIR type-checker. During MIR typeck, we then replace its regions 55 | with new nll inference vars and relate it with the actual `UserType` to get the correct region 56 | constraints again. 57 | 58 | After the MIR type-check, all user type annotations get discarded, as they aren't needed anymore. 59 | 60 | [annot]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.CanonicalUserTypeAnnotation.html 61 | [proj]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.UserTypeProjection.html 62 | [decl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.LocalDecl.html 63 | [stmt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.StatementKind.html#variant.AscribeUserType 64 | [inf]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.CanonicalUserTypeAnnotation.html#structfield.inferred_ty -------------------------------------------------------------------------------- /src/mir/debugging.md: -------------------------------------------------------------------------------- 1 | # MIR Debugging 2 | 3 | The `-Z dump-mir` flag can be used to dump a text representation of the MIR. 4 | The following optional flags, used in combination with `-Z dump-mir`, enable 5 | additional output formats, including: 6 | 7 | * `-Z dump-mir-graphviz` - dumps a `.dot` file that represents MIR as a 8 | control-flow graph 9 | * `-Z dump-mir-dataflow` - dumps a `.dot` file showing the [dataflow state] at 10 | each point in the control-flow graph 11 | 12 | `-Z dump-mir=F` is a handy compiler option that will let you view the MIR for 13 | each function at each stage of compilation. `-Z dump-mir` takes a **filter** `F` 14 | which allows you to control which functions and which passes you are 15 | interested in. For example: 16 | 17 | ```bash 18 | > rustc -Z dump-mir=foo ... 19 | ``` 20 | 21 | This will dump the MIR for any function whose name contains `foo`; it 22 | will dump the MIR both before and after every pass. Those files will 23 | be created in the `mir_dump` directory. There will likely be quite a 24 | lot of them! 25 | 26 | ```bash 27 | > cat > foo.rs 28 | fn main() { 29 | println!("Hello, world!"); 30 | } 31 | ^D 32 | > rustc -Z dump-mir=main foo.rs 33 | > ls mir_dump/* | wc -l 34 | 161 35 | ``` 36 | 37 | The files have names like `rustc.main.000-000.CleanEndRegions.after.mir`. These 38 | names have a number of parts: 39 | 40 | ```text 41 | rustc.main.000-000.CleanEndRegions.after.mir 42 | ---- --- --- --------------- ----- either before or after 43 | | | | name of the pass 44 | | | index of dump within the pass (usually 0, but some passes dump intermediate states) 45 | | index of the pass 46 | def-path to the function etc being dumped 47 | ``` 48 | 49 | You can also make more selective filters. For example, `main & CleanEndRegions` 50 | will select for things that reference *both* `main` and the pass 51 | `CleanEndRegions`: 52 | 53 | ```bash 54 | > rustc -Z dump-mir='main & CleanEndRegions' foo.rs 55 | > ls mir_dump 56 | rustc.main.000-000.CleanEndRegions.after.mir rustc.main.000-000.CleanEndRegions.before.mir 57 | ``` 58 | 59 | Filters can also have `|` parts to combine multiple sets of 60 | `&`-filters. For example `main & CleanEndRegions | main & 61 | NoLandingPads` will select *either* `main` and `CleanEndRegions` *or* 62 | `main` and `NoLandingPads`: 63 | 64 | ```bash 65 | > rustc -Z dump-mir='main & CleanEndRegions | main & NoLandingPads' foo.rs 66 | > ls mir_dump 67 | rustc.main-promoted[0].002-000.NoLandingPads.after.mir 68 | rustc.main-promoted[0].002-000.NoLandingPads.before.mir 69 | rustc.main-promoted[0].002-006.NoLandingPads.after.mir 70 | rustc.main-promoted[0].002-006.NoLandingPads.before.mir 71 | rustc.main-promoted[1].002-000.NoLandingPads.after.mir 72 | rustc.main-promoted[1].002-000.NoLandingPads.before.mir 73 | rustc.main-promoted[1].002-006.NoLandingPads.after.mir 74 | rustc.main-promoted[1].002-006.NoLandingPads.before.mir 75 | rustc.main.000-000.CleanEndRegions.after.mir 76 | rustc.main.000-000.CleanEndRegions.before.mir 77 | rustc.main.002-000.NoLandingPads.after.mir 78 | rustc.main.002-000.NoLandingPads.before.mir 79 | rustc.main.002-006.NoLandingPads.after.mir 80 | rustc.main.002-006.NoLandingPads.before.mir 81 | ``` 82 | 83 | (Here, the `main-promoted[0]` files refer to the MIR for "promoted constants" 84 | that appeared within the `main` function.) 85 | 86 | The `-Z unpretty=mir-cfg` flag can be used to create a graphviz MIR 87 | control-flow diagram for the whole crate: 88 | 89 | ![A control-flow diagram](mir_cfg.svg) 90 | 91 | TODO: anything else? 92 | 93 | [dataflow state]: ./dataflow.html#graphviz-diagrams 94 | -------------------------------------------------------------------------------- /src/unsafety-checking.md: -------------------------------------------------------------------------------- 1 | # Unsafety Checking 2 | 3 | Certain expressions in Rust can violate memory safety and as such need to be 4 | inside an `unsafe` block or function. The compiler will also warn if an unsafe 5 | block is used without any corresponding unsafe operations. 6 | 7 | ## Overview 8 | 9 | The unsafety check is located in the [`check_unsafety`] module. It performs a 10 | walk over the [THIR] of a function and all of its closures and inline constants. 11 | It keeps track of the unsafe context: whether it has entered an `unsafe` block. 12 | If an unsafe operation is used outside of an `unsafe` block, then an error is 13 | reported. If an unsafe operation is used in an unsafe block then that block is 14 | marked as used for [the unused_unsafe lint](#the-unused_unsafe-lint). 15 | 16 | The unsafety check needs type information so could potentially be done on the 17 | HIR, making use of typeck results, THIR or MIR. THIR is chosen because there are 18 | fewer cases to consider than in HIR, for example unsafe function calls and 19 | unsafe method calls have the same representation in THIR. The check is not done 20 | on MIR because safety checks do not depend on control flow so MIR is not 21 | necessary to use and MIR doesn't have as precise spans for some expressions. 22 | 23 | Most unsafe operations can be identified by checking the `ExprKind` in THIR and 24 | checking the type of the argument. For example, dereferences of a raw pointer 25 | correspond to `ExprKind::Deref`s with an argument that has a raw pointer type. 26 | 27 | Looking for unsafe Union field accesses is a bit more complex because writing to 28 | a field of a union is safe. The checker tracks when it's visiting the left-hand 29 | side of an assignment expression and allows union fields to directly appear 30 | there, while erroring in all other cases. Union field accesses can also occur 31 | in patterns, so those have to be walked as well. 32 | 33 | The other complicated safety check is for writes to fields of layout constrained 34 | structs (such as [`NonNull`]). These are found by looking for the borrow or 35 | assignment expression and then visiting the subexpression being borrowed or 36 | assigned with a separate visitor. 37 | 38 | [THIR]: ./thir.md 39 | [`check_unsafety`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/check_unsafety/index.html 40 | [`NonNull`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html 41 | 42 | ## The unused_unsafe lint 43 | 44 | The unused_unsafe lint reports `unsafe` blocks that can be removed. The unsafety 45 | checker records whenever it finds an operation that requires unsafe. The lint is 46 | then reported if either: 47 | 48 | - An `unsafe` block contains no unsafe operations 49 | - An `unsafe` block is within another unsafe block, and the outer block 50 | isn't considered unused 51 | 52 | ```rust 53 | #![deny(unused_unsafe)] 54 | let y = 0; 55 | let x: *const u8 = core::ptr::addr_of!(y); 56 | unsafe { // lint reported for this block 57 | unsafe { 58 | let z = *x; 59 | } 60 | let safe_expr = 123; 61 | } 62 | unsafe { 63 | unsafe { // lint reported for this block 64 | let z = *x; 65 | } 66 | let unsafe_expr = *x; 67 | } 68 | ``` 69 | 70 | ## Other checks involving `unsafe` 71 | 72 | [Unsafe traits] require an `unsafe impl` to be implemented, the check for this 73 | is done as part of [coherence]. The `unsafe_code` lint is run as a lint pass on 74 | the ast that searches for unsafe blocks, functions and implementations, as well 75 | as certain unsafe attributes. 76 | 77 | [Unsafe traits]: https://doc.rust-lang.org/reference/items/traits.html#unsafe-traits 78 | [coherence]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir_analysis/src/coherence/unsafety.rs 79 | -------------------------------------------------------------------------------- /examples/rustc-driver-interacting-with-the-ast.rs: -------------------------------------------------------------------------------- 1 | #![feature(rustc_private)] 2 | 3 | extern crate rustc_ast_pretty; 4 | extern crate rustc_driver; 5 | extern crate rustc_error_codes; 6 | extern crate rustc_errors; 7 | extern crate rustc_hash; 8 | extern crate rustc_hir; 9 | extern crate rustc_interface; 10 | extern crate rustc_session; 11 | extern crate rustc_span; 12 | 13 | use std::{path, process, str, sync::Arc}; 14 | 15 | use rustc_ast_pretty::pprust::item_to_string; 16 | use rustc_errors::registry; 17 | use rustc_session::config; 18 | 19 | fn main() { 20 | let out = process::Command::new("rustc") 21 | .arg("--print=sysroot") 22 | .current_dir(".") 23 | .output() 24 | .unwrap(); 25 | let sysroot = str::from_utf8(&out.stdout).unwrap().trim(); 26 | let config = rustc_interface::Config { 27 | opts: config::Options { 28 | maybe_sysroot: Some(path::PathBuf::from(sysroot)), 29 | ..config::Options::default() 30 | }, 31 | input: config::Input::Str { 32 | name: rustc_span::FileName::Custom("main.rs".to_string()), 33 | input: r#" 34 | fn main() { 35 | let message = "Hello, World!"; 36 | println!("{message}"); 37 | } 38 | "# 39 | .to_string(), 40 | }, 41 | crate_cfg: Vec::new(), 42 | crate_check_cfg: Vec::new(), 43 | output_dir: None, 44 | output_file: None, 45 | file_loader: None, 46 | locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES, 47 | lint_caps: rustc_hash::FxHashMap::default(), 48 | psess_created: None, 49 | register_lints: None, 50 | override_queries: None, 51 | make_codegen_backend: None, 52 | registry: registry::Registry::new(rustc_errors::codes::DIAGNOSTICS), 53 | expanded_args: Vec::new(), 54 | ice_file: None, 55 | hash_untracked_state: None, 56 | using_internal_features: Arc::default(), 57 | }; 58 | rustc_interface::run_compiler(config, |compiler| { 59 | compiler.enter(|queries| { 60 | // TODO: add this to -Z unpretty 61 | let ast_krate = queries.parse().unwrap().get_mut().clone(); 62 | for item in ast_krate.items { 63 | println!("{}", item_to_string(&item)); 64 | } 65 | // Analyze the crate and inspect the types under the cursor. 66 | queries.global_ctxt().unwrap().enter(|tcx| { 67 | // Every compilation contains a single crate. 68 | let hir_krate = tcx.hir(); 69 | // Iterate over the top-level items in the crate, looking for the main function. 70 | for id in hir_krate.items() { 71 | let item = hir_krate.item(id); 72 | // Use pattern-matching to find a specific node inside the main function. 73 | if let rustc_hir::ItemKind::Fn(_, _, body_id) = item.kind { 74 | let expr = &tcx.hir().body(body_id).value; 75 | if let rustc_hir::ExprKind::Block(block, _) = expr.kind { 76 | if let rustc_hir::StmtKind::Let(let_stmt) = block.stmts[0].kind { 77 | if let Some(expr) = let_stmt.init { 78 | let hir_id = expr.hir_id; // hir_id identifies the string "Hello, world!" 79 | let def_id = item.hir_id().owner.def_id; // def_id identifies the main function 80 | let ty = tcx.typeck(def_id).node_type(hir_id); 81 | println!("{expr:#?}: {ty:?}"); 82 | } 83 | } 84 | } 85 | } 86 | } 87 | }) 88 | }); 89 | }); 90 | } 91 | -------------------------------------------------------------------------------- /src/constants.md: -------------------------------------------------------------------------------- 1 | # Constants in the type system 2 | 3 | Constants used in the type system are represented as [`ty::Const`]. 4 | The variants of their [`const_kind::ConstKind`] mostly mirror the variants of [`ty_kind::TyKind`] 5 | with the two *additional* variants being `ConstKind::Value` and `ConstKind::Unevaluated`. 6 | 7 | ## `WithOptConstParam` and dealing with the query system 8 | 9 | To typecheck constants used in the type system, we have to know their expected type. 10 | For const arguments in type dependent paths, e.g. `x.foo::<{ 3 + 4 }>()`, we don't know 11 | the expected type for `{ 3 + 4 }` until we are typechecking the containing function. 12 | 13 | As we may however have to evaluate that constant during this typecheck, we would get a cycle error. 14 | For more details, you can look at [this document](https://hackmd.io/@rust-const-generics/Bk5GHW-Iq). 15 | 16 | ## Unevaluated constants 17 | 18 | *This section talks about what's happening with `feature(generic_const_exprs)` enabled. 19 | On stable we do not yet supply any generic parameters to anonymous constants, 20 | avoiding most of the issues mentioned here.* 21 | 22 | Unless a constant is either a simple literal, e.g. `[u8; 3]` or `foo::<{ 'c' }>()`, 23 | or a generic parameter, e.g. `[u8; N]`, converting a constant to its [`ty::Const`] representation 24 | returns an unevaluated constant. Even fully concrete constants which do not depend on 25 | generic parameters are not evaluated right away. 26 | 27 | Anonymous constants are typechecked separately from their containing item, e.g. 28 | ```rust 29 | fn foo() -> [u8; N + 1] { 30 | [0; N + 1] 31 | } 32 | ``` 33 | is treated as 34 | ```rust 35 | const ANON_CONST_1 = N + 1; 36 | const ANON_CONST_2 = N + 1; 37 | fn foo() -> [u8; ANON_CONST_1::] { 38 | [0; ANON_CONST_2::] 39 | } 40 | ``` 41 | 42 | ### Unifying constants 43 | 44 | For the compiler, `ANON_CONST_1` and `ANON_CONST_2` are completely different, so 45 | we have to somehow look into unevaluated constants to check whether they should 46 | unify. 47 | 48 | For this we use [InferCtxt::try_unify_abstract_consts](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.try_unify_abstract_consts). 49 | This builds a custom AST for the two inputs from their THIR. This is then used for 50 | the actual comparison. 51 | 52 | ### Lazy normalization for constants 53 | 54 | We do not eagerly evaluate constant as they can be used in the `where`-clauses of their 55 | parent item, for example: 56 | 57 | ```rust 58 | #[feature(generic_const_exprs)] 59 | fn foo() 60 | where 61 | [u8; ::ASSOC + 1]: SomeOtherTrait, 62 | {} 63 | ``` 64 | 65 | The constant `::ASSOC + 1` depends on the `T: Trait` bound of 66 | its parents caller bounds, but is also part of another bound itself. 67 | If we were to eagerly evaluate this constant while computing its parents bounds 68 | this would cause a query cycle. 69 | 70 | ### Unused generic arguments of anonymous constants 71 | 72 | Anonymous constants inherit the generic parameters of their parent, which is 73 | why the array length in `foo() -> [u8; N + 1]` can use `N`. 74 | 75 | Without any manual adjustments, this causes us to include parameters even if 76 | the constant doesn't use them in any way. This can cause 77 | [some interesting errors][pcg-unused-substs] and breaks some already stable code. 78 | 79 | [`ty::Const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Const.html 80 | [`const_kind::ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/const_kind/enum.ConstKind.html 81 | [`ty_kind::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html 82 | [pcg-unused-substs]: https://github.com/rust-lang/project-const-generics/issues/33 83 | -------------------------------------------------------------------------------- /src/solve/the-solver.md: -------------------------------------------------------------------------------- 1 | # The solver 2 | 3 | Also consider reading the documentation for [the recursive solver in chalk][chalk] 4 | as it is very similar to this implementation and also talks about limitations of this 5 | approach. 6 | 7 | [chalk]: https://rust-lang.github.io/chalk/book/recursive.html 8 | 9 | ## A rough walkthrough 10 | 11 | The entry-point of the solver is `InferCtxtEvalExt::evaluate_root_goal`. This 12 | function sets up the root `EvalCtxt` and then calls `EvalCtxt::evaluate_goal`, 13 | to actually enter the trait solver. 14 | 15 | `EvalCtxt::evaluate_goal` handles [canonicalization](./canonicalization.md), caching, 16 | overflow, and solver cycles. Once that is done, it creates a nested `EvalCtxt` with a 17 | separate local `InferCtxt` and calls `EvalCtxt::compute_goal`, which is responsible for the 18 | 'actual solver behavior'. We match on the `PredicateKind`, delegating to a separate function 19 | for each one. 20 | 21 | For trait goals, such a `Vec: Clone`, `EvalCtxt::compute_trait_goal` has 22 | to collect all the possible ways this goal can be proven via 23 | `EvalCtxt::assemble_and_evaluate_candidates`. Each candidate is handled in 24 | a separate "probe", to not leak inference constraints to the other candidates. 25 | We then try to merge the assembled candidates via `EvalCtxt::merge_candidates`. 26 | 27 | 28 | ## Important concepts and design pattern 29 | 30 | ### `EvalCtxt::add_goal` 31 | 32 | To prove nested goals, we don't directly call `EvalCtxt::compute_goal`, but instead 33 | add the goal to the `EvalCtxt` with `EvalCtxt::all_goal`. We then prove all nested 34 | goals together in either `EvalCtxt::try_evaluate_added_goals` or 35 | `EvalCtxt::evaluate_added_goals_and_make_canonical_response`. This allows us to handle 36 | inference constraints from later goals. 37 | 38 | E.g. if we have both `?x: Debug` and `(): ConstrainToU8` as nested goals, 39 | then proving `?x: Debug` is initially ambiguous, but after proving `(): ConstrainToU8` 40 | we constrain `?x` to `u8` and proving `u8: Debug` succeeds. 41 | 42 | ### Matching on `TyKind` 43 | 44 | We lazily normalize types in the solver, so we always have to assume that any types 45 | and constants are potentially unnormalized. This means that matching on `TyKind` can easily 46 | be incorrect. 47 | 48 | We handle normalization in two different ways. When proving `Trait` goals when normalizing 49 | associated types, we separately assemble candidates depending on whether they structurally 50 | match the self type. Candidates which match on the self type are handled in 51 | `EvalCtxt::assemble_candidates_via_self_ty` which recurses via 52 | `EvalCtxt::assemble_candidates_after_normalizing_self_ty`, which normalizes the self type 53 | by one level. In all other cases we have to match on a `TyKind` we first use 54 | `EvalCtxt::try_normalize_ty` to normalize the type as much as possible. 55 | 56 | ### Higher ranked goals 57 | 58 | In case the goal is higher-ranked, e.g. `for<'a> F: FnOnce(&'a ())`, `EvalCtxt::compute_goal` 59 | eagerly instantiates `'a` with a placeholder and then recursively proves 60 | `F: FnOnce(&'!a ())` as a nested goal. 61 | 62 | ### Dealing with choice 63 | 64 | Some goals can be proven in multiple ways. In these cases we try each option in 65 | a separate "probe" and then attempt to merge the resulting responses by using 66 | `EvalCtxt::try_merge_responses`. If merging the responses fails, we use 67 | `EvalCtxt::flounder` instead, returning ambiguity. For some goals, we try 68 | incompletely prefer some choices over others in case `EvalCtxt::try_merge_responses` 69 | fails. 70 | 71 | ## Learning more 72 | 73 | The solver should be fairly self-contained. I hope that the above information provides a 74 | good foundation when looking at the code itself. Please reach out on zulip if you get stuck 75 | while doing so or there are some quirks and design decisions which were unclear and deserve 76 | better comments or should be mentioned here. 77 | -------------------------------------------------------------------------------- /src/effects.md: -------------------------------------------------------------------------------- 1 | # Effects and effect checking 2 | 3 | Note: all of this describes the implementation of the unstable `effects` and 4 | `const_trait_impl` features. None of this implementation is usable or visible from 5 | stable Rust. 6 | 7 | The implementation of const traits and `~const` bounds is a limited effect system. 8 | It is used to allow trait bounds on `const fn` to be used within the `const fn` for 9 | method calls. Within the function, in order to know whether a method on a trait 10 | bound is `const`, we need to know whether there is a `~const` bound for the trait. 11 | In order to know whether we can instantiate a `~const` bound on a `const fn`, we 12 | need to know whether there is a `const_trait` impl for the type and trait being 13 | used (or whether the `const fn` is used at runtime, then any type implementing the 14 | trait is ok, just like with other bounds). 15 | 16 | We perform these checks via a const generic boolean that gets attached to all 17 | `const fn` and `const trait`. The following sections will explain the desugarings 18 | and the way we perform the checks at call sites. 19 | 20 | The const generic boolean is inverted to the meaning of `const`. In the compiler 21 | it is called `host`, because it enables "host APIs" like `static` items, network 22 | access, disk access, random numbers and everything else that isn't available in 23 | `const` contexts. So `false` means "const", `true` means "not const" and if it's 24 | a generic parameter, it means "maybe const" (meaning we're in a const fn or const 25 | trait). 26 | 27 | ## `const fn` 28 | 29 | All `const fn` have a `#[rustc_host] const host: bool` generic parameter that is 30 | hidden from users. Any `~const Trait` bounds in the generics list or `where` bounds 31 | of a `const fn` get converted to `Trait + Trait` bounds. The `Trait` 32 | exists so that associated types of the generic param can be used from projections 33 | like `::Assoc`, because there are no `` projections for now. 34 | 35 | ## `#[const_trait] trait`s 36 | 37 | The `#[const_trait]` attribute gives the marked trait a `#[rustc_host] const host: bool` 38 | generic parameter. All functions of the trait "inherit" this generic parameter, just like 39 | they have all the regular generic parameters of the trait. Any `~const Trait` super-trait 40 | bounds get desugared to `Trait + Trait` in order to allow using associated 41 | types and consts of the super traits in the trait declaration. This is necessary, because 42 | `::Assoc` is always `>::Assoc` as there is 43 | no `` syntax. 44 | 45 | ## `typeck` performing method and function call checks. 46 | 47 | When generic parameters are instantiated for any items, the `host` generic parameter 48 | is always instantiated as an inference variable. This is a special kind of inference var 49 | that is not part of the type or const inference variables, similar to how we have 50 | special inference variables for type variables that we know to be an integer, but not 51 | yet which one. These separate inference variables fall back to `true` at 52 | the end of typeck (in `fallback_effects`) to ensure that `let _ = some_fn_item_name;` 53 | will keep compiling. 54 | 55 | All actually used (in function calls, casts, or anywhere else) function items, will 56 | have the `enforce_context_effects` method invoked. 57 | It trivially returns if the function being called has no `host` generic parameter. 58 | 59 | In order to error if a non-const function is called in a const context, we have not 60 | yet disabled the const-check logic that happens on MIR, because 61 | `enforce_context_effects` does not yet perform this check. 62 | 63 | The function call's `host` parameter is then equated to the context's `host` value, 64 | which almost always trivially succeeds, as it was an inference var. If the inference 65 | var has already been bound (since the function item is invoked twice), the second 66 | invocation checks it against the first. 67 | -------------------------------------------------------------------------------- /src/diagnostics/error-codes.md: -------------------------------------------------------------------------------- 1 | # Error codes 2 | We generally try to assign each error message a unique code like `E0123`. These 3 | codes are defined in the compiler in the `diagnostics.rs` files found in each 4 | crate, which basically consist of macros. All error codes have an associated 5 | explanation: new error codes must include them. Note that not all _historical_ 6 | (no longer emitted) error codes have explanations. 7 | 8 | ## Error explanations 9 | 10 | The explanations are written in Markdown (see the [CommonMark Spec] for 11 | specifics around syntax), and all of them are linked in the [`rustc_error_codes`] 12 | crate. Please read [RFC 1567] for details on how to format and write long error 13 | codes. As of February 2023, there is an 14 | effort[^new-explanations] to replace this largely outdated RFC with a new more 15 | flexible standard. 16 | 17 | Error explanations should expand on the error message and provide details about 18 | _why_ the error occurs. It is not helpful for users to copy-paste a quick fix; 19 | explanations should help users understand why their code cannot be accepted by 20 | the compiler. Rust prides itself on helpful error messages and long-form 21 | explanations are no exception. However, before error explanations are 22 | overhauled[^new-explanations] it is a bit open as to how exactly they should be 23 | written, as always: ask your reviewer or ask around on the Rust Discord or Zulip. 24 | 25 | [^new-explanations]: See the draft RFC [here][new-explanations-rfc]. 26 | 27 | [`rustc_error_codes`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_error_codes/index.html 28 | [CommonMark Spec]: https://spec.commonmark.org/current/ 29 | [RFC 1567]: https://github.com/rust-lang/rfcs/blob/master/text/1567-long-error-codes-explanation-normalization.md 30 | [new-explanations-rfc]: https://github.com/rust-lang/rfcs/pull/3370 31 | 32 | ## Allocating a fresh code 33 | 34 | Error codes are stored in `compiler/rustc_error_codes`. 35 | 36 | To create a new error, you first need to find the next available 37 | code. You can find it with `tidy`: 38 | 39 | ``` 40 | ./x test tidy 41 | ``` 42 | 43 | This will invoke the tidy script, which generally checks that your code obeys 44 | our coding conventions. Some of these jobs check error codes and ensure that 45 | there aren't duplicates, etc (the tidy check is defined in 46 | `src/tools/tidy/src/error_codes.rs`). Once it is finished with that, tidy will 47 | print out the highest used error code: 48 | 49 | ``` 50 | ... 51 | tidy check 52 | Found 505 error codes 53 | Highest error code: `E0591` 54 | ... 55 | ``` 56 | 57 | Here we see the highest error code in use is `E0591`, so we _probably_ want 58 | `E0592`. To be sure, run `rg E0592` and check, you should see no references. 59 | 60 | You will have to write an extended description for your error, 61 | which will go in `rustc_error_codes/src/error_codes/E0592.md`. 62 | To register the error, open `rustc_error_codes/src/error_codes.rs` and add the 63 | code (in its proper numerical order) into` register_diagnostics!` macro, like 64 | this: 65 | 66 | ```rust 67 | register_diagnostics! { 68 | ... 69 | E0592: include_str!("./error_codes/E0592.md"), 70 | } 71 | ``` 72 | 73 | To actually issue the error, you can use the `struct_span_code_err!` macro: 74 | 75 | ```rust 76 | struct_span_code_err!(self.dcx(), // some path to the `DiagCtxt` here 77 | span, // whatever span in the source you want 78 | E0592, // your new error code 79 | fluent::example::an_error_message) 80 | .emit() // actually issue the error 81 | ``` 82 | 83 | If you want to add notes or other snippets, you can invoke methods before you 84 | call `.emit()`: 85 | 86 | ```rust 87 | struct_span_code_err!(...) 88 | .span_label(another_span, fluent::example::example_label) 89 | .span_note(another_span, fluent::example::separate_note) 90 | .emit() 91 | ``` 92 | 93 | For an example of a PR adding an error code, see [#76143]. 94 | 95 | [#76143]: https://github.com/rust-lang/rust/pull/76143 96 | -------------------------------------------------------------------------------- /src/the-parser.md: -------------------------------------------------------------------------------- 1 | # Lexing and Parsing 2 | 3 | The very first thing the compiler does is take the program (in Unicode 4 | characters) and turn it into something the compiler can work with more 5 | conveniently than strings. This happens in two stages: Lexing and Parsing. 6 | 7 | Lexing takes strings and turns them into streams of [tokens]. For example, 8 | `foo.bar + buz` would be turned into the tokens `foo`, `.`, 9 | `bar`, `+`, and `buz`. The lexer lives in [`rustc_lexer`][lexer]. 10 | 11 | [tokens]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/token/index.html 12 | [lexer]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lexer/index.html 13 | 14 | Parsing then takes streams of tokens and turns them into a structured 15 | form which is easier for the compiler to work with, usually called an [*Abstract 16 | Syntax Tree*][ast] (AST). An AST mirrors the structure of a Rust program in memory, 17 | using a `Span` to link a particular AST node back to its source text. 18 | 19 | The AST is defined in [`rustc_ast`][rustc_ast], along with some definitions for 20 | tokens and token streams, data structures/traits for mutating ASTs, and shared 21 | definitions for other AST-related parts of the compiler (like the lexer and 22 | macro-expansion). 23 | 24 | The parser is defined in [`rustc_parse`][rustc_parse], along with a 25 | high-level interface to the lexer and some validation routines that run after 26 | macro expansion. In particular, the [`rustc_parse::parser`][parser] contains 27 | the parser implementation. 28 | 29 | The main entrypoint to the parser is via the various `parse_*` functions and others in the 30 | [parser crate][parser_lib]. They let you do things like turn a [`SourceFile`][sourcefile] 31 | (e.g. the source in a single file) into a token stream, create a parser from 32 | the token stream, and then execute the parser to get a `Crate` (the root AST 33 | node). 34 | 35 | To minimize the amount of copying that is done, 36 | both [`StringReader`] and [`Parser`] have lifetimes which bind them to the parent `ParseSess`. 37 | This contains all the information needed while parsing, 38 | as well as the [`SourceMap`] itself. 39 | 40 | Note that while parsing, we may encounter macro definitions or invocations. We 41 | set these aside to be expanded (see [this chapter](./macro-expansion.md)). 42 | Expansion may itself require parsing the output of the macro, which may reveal 43 | more macros to be expanded, and so on. 44 | 45 | ## More on Lexical Analysis 46 | 47 | Code for lexical analysis is split between two crates: 48 | 49 | - `rustc_lexer` crate is responsible for breaking a `&str` into chunks 50 | constituting tokens. Although it is popular to implement lexers as generated 51 | finite state machines, the lexer in `rustc_lexer` is hand-written. 52 | 53 | - [`StringReader`] integrates `rustc_lexer` with data structures specific to `rustc`. 54 | Specifically, 55 | it adds `Span` information to tokens returned by `rustc_lexer` and interns identifiers. 56 | 57 | [rustc_ast]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/index.html 58 | [rustc_errors]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html 59 | [ast]: https://en.wikipedia.org/wiki/Abstract_syntax_tree 60 | [`SourceMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/source_map/struct.SourceMap.html 61 | [ast module]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/index.html 62 | [rustc_parse]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html 63 | [parser_lib]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html 64 | [parser]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/index.html 65 | [`Parser`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html 66 | [`StringReader`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/lexer/struct.StringReader.html 67 | [visit module]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/visit/index.html 68 | [sourcefile]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.SourceFile.html 69 | -------------------------------------------------------------------------------- /src/param_env/param_env_what_is_it.md: -------------------------------------------------------------------------------- 1 | 2 | # What is a `ParamEnv`? 3 | 4 | The type system relies on information in the environment in order for it to function correctly. This information is stored in the [`ParamEnv`][pe] type and it is important to use the correct `ParamEnv` when interacting with the type system. 5 | 6 | The information represented by `ParamEnv` is a list of in-scope where-clauses, and a [`Reveal`][reveal] (see linked docs for more information). A `ParamEnv` typically corresponds to a specific item's where clauses, some clauses are not explicitly written bounds and instead are implicitly added in [`predicates_of`][predicates_of] such as `ConstArgHasType` or some implied bounds. 7 | 8 | A `ParamEnv` can also be created with arbitrary data that is not derived from a specific item such as in [`compare_method_predicate_entailment`][method_pred_entailment] which creates a hybrid `ParamEnv` consisting of the impl's where clauses and the trait definition's function's where clauses. In most cases `ParamEnv`s are initially created via the [`param_env` query][query] which returns a `ParamEnv` derived from the provided item's where clauses. 9 | 10 | If we have a function such as: 11 | ```rust 12 | // `foo` would have a `ParamEnv` of: 13 | // `[T: Sized, T: Trait, ::Assoc: Clone]` 14 | fn foo() 15 | where 16 | ::Assoc: Clone, 17 | {} 18 | ``` 19 | If we were conceptually inside of `foo` (for example, type-checking or linting it) we would use this `ParamEnv` everywhere that we interact with the type system. This would allow things such as normalization (TODO: write a chapter about normalization and link it), evaluating generic constants, and proving where clauses/goals, to rely on `T` being sized, implementing `Trait`, etc. 20 | 21 | A more concrete example: 22 | ```rust 23 | // `foo` would have a `ParamEnv` of: 24 | // `[T: Sized, T: Clone]` 25 | fn foo(a: T) { 26 | // when typechecking `foo` we require all the where clauses on `bar` 27 | // to hold in order for it to be legal to call. This means we have to 28 | // prove `T: Clone`. As we are type checking `foo` we use `foo`'s 29 | // environment when trying to check that `T: Clone` holds. 30 | // 31 | // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized, T: Clone]` 32 | // will trivially succeed as bound we want to prove is in our environment. 33 | requires_clone(a); 34 | } 35 | ``` 36 | 37 | Or alternatively an example that would not compile: 38 | ```rust 39 | // `foo2` would have a `ParamEnv` of: 40 | // `[T: Sized]` 41 | fn foo2(a: T) { 42 | // When typechecking `foo2` we attempt to prove `T: Clone`. 43 | // As we are type checking `foo2` we use `foo2`'s environment 44 | // when trying to prove `T: Clone`. 45 | // 46 | // Trying to prove `T: Clone` with a `ParamEnv` of `[T: Sized]` will 47 | // fail as there is nothing in the environment telling the trait solver 48 | // that `T` implements `Clone` and there exists no user written impl 49 | // that could apply. 50 | requires_clone(a); 51 | } 52 | ``` 53 | 54 | It's very important to use the correct `ParamEnv` when interacting with the type system as otherwise it can lead to ICEs or things compiling when they shouldn't (or vice versa). See [#82159](https://github.com/rust-lang/rust/pull/82159) and [#82067](https://github.com/rust-lang/rust/pull/82067) as examples of PRs that changed rustc to use the correct param env to avoid ICE. Determining how to acquire the correct `ParamEnv` is explained later in this chapter. 55 | 56 | [predicates_of]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/collect/predicates_of/fn.predicates_of.html 57 | [method_pred_entailment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.compare_method_predicate_entailment.html 58 | [pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html 59 | [query]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.param_env 60 | [reveal]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/traits/enum.Reveal.html -------------------------------------------------------------------------------- /src/backend/codegen.md: -------------------------------------------------------------------------------- 1 | # Code generation 2 | 3 | Code generation (or "codegen") is the part of the compiler 4 | that actually generates an executable binary. 5 | Usually, rustc uses LLVM for code generation, 6 | but there is also support for [Cranelift] and [GCC]. 7 | The key is that rustc doesn't implement codegen itself. 8 | It's worth noting, though, that in the Rust source code, 9 | many parts of the backend have `codegen` in their names 10 | (there are no hard boundaries). 11 | 12 | [Cranelift]: https://github.com/bytecodealliance/wasmtime/tree/main/cranelift 13 | [GCC]: https://github.com/rust-lang/rustc_codegen_gcc 14 | 15 | > NOTE: If you are looking for hints on how to debug code generation bugs, 16 | > please see [this section of the debugging chapter][debugging]. 17 | 18 | [debugging]: ./debugging.md 19 | 20 | ## What is LLVM? 21 | 22 | [LLVM](https://llvm.org) is "a collection of modular and reusable compiler and 23 | toolchain technologies". In particular, the LLVM project contains a pluggable 24 | compiler backend (also called "LLVM"), which is used by many compiler projects, 25 | including the `clang` C compiler and our beloved `rustc`. 26 | 27 | LLVM takes input in the form of LLVM IR. It is basically assembly code with 28 | additional low-level types and annotations added. These annotations are helpful 29 | for doing optimizations on the LLVM IR and outputted machine code. The end 30 | result of all this is (at long last) something executable (e.g. an ELF object, 31 | an EXE, or wasm). 32 | 33 | There are a few benefits to using LLVM: 34 | 35 | - We don't have to write a whole compiler backend. This reduces implementation 36 | and maintenance burden. 37 | - We benefit from the large suite of advanced optimizations that the LLVM 38 | project has been collecting. 39 | - We can automatically compile Rust to any of the platforms for which LLVM has 40 | support. For example, as soon as LLVM added support for wasm, voila! rustc, 41 | clang, and a bunch of other languages were able to compile to wasm! (Well, 42 | there was some extra stuff to be done, but we were 90% there anyway). 43 | - We and other compiler projects benefit from each other. For example, when the 44 | [Spectre and Meltdown security vulnerabilities][spectre] were discovered, 45 | only LLVM needed to be patched. 46 | 47 | [spectre]: https://meltdownattack.com/ 48 | 49 | ## Running LLVM, linking, and metadata generation 50 | 51 | Once LLVM IR for all of the functions and statics, etc is built, it is time to 52 | start running LLVM and its optimization passes. LLVM IR is grouped into 53 | "modules". Multiple "modules" can be codegened at the same time to aid in 54 | multi-core utilization. These "modules" are what we refer to as _codegen 55 | units_. These units were established way back during monomorphization 56 | collection phase. 57 | 58 | Once LLVM produces objects from these modules, these objects are passed to the 59 | linker along with, optionally, the metadata object and an archive or an 60 | executable is produced. 61 | 62 | It is not necessarily the codegen phase described above that runs the 63 | optimizations. With certain kinds of LTO, the optimization might happen at the 64 | linking time instead. It is also possible for some optimizations to happen 65 | before objects are passed on to the linker and some to happen during the 66 | linking. 67 | 68 | This all happens towards the very end of compilation. The code for this can be 69 | found in [`rustc_codegen_ssa::back`][ssaback] and 70 | [`rustc_codegen_llvm::back`][llvmback]. Sadly, this piece of code is not 71 | really well-separated into LLVM-dependent code; the [`rustc_codegen_ssa`][ssa] 72 | contains a fair amount of code specific to the LLVM backend. 73 | 74 | Once these components are done with their work you end up with a number of 75 | files in your filesystem corresponding to the outputs you have requested. 76 | 77 | [ssa]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html 78 | [ssaback]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/back/index.html 79 | [llvmback]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/back/index.html 80 | -------------------------------------------------------------------------------- /examples/rustc-driver-example.rs: -------------------------------------------------------------------------------- 1 | #![feature(rustc_private)] 2 | 3 | extern crate rustc_driver; 4 | extern crate rustc_error_codes; 5 | extern crate rustc_errors; 6 | extern crate rustc_hash; 7 | extern crate rustc_hir; 8 | extern crate rustc_interface; 9 | extern crate rustc_session; 10 | extern crate rustc_span; 11 | 12 | use std::{path, process, str, sync::Arc}; 13 | 14 | use rustc_errors::registry; 15 | use rustc_hash::FxHashMap; 16 | use rustc_session::config; 17 | 18 | fn main() { 19 | let out = process::Command::new("rustc") 20 | .arg("--print=sysroot") 21 | .current_dir(".") 22 | .output() 23 | .unwrap(); 24 | let sysroot = str::from_utf8(&out.stdout).unwrap().trim(); 25 | let config = rustc_interface::Config { 26 | // Command line options 27 | opts: config::Options { 28 | maybe_sysroot: Some(path::PathBuf::from(sysroot)), 29 | ..config::Options::default() 30 | }, 31 | // cfg! configuration in addition to the default ones 32 | crate_cfg: Vec::new(), // FxHashSet<(String, Option)> 33 | crate_check_cfg: Vec::new(), // CheckCfg 34 | input: config::Input::Str { 35 | name: rustc_span::FileName::Custom("main.rs".into()), 36 | input: r#" 37 | static HELLO: &str = "Hello, world!"; 38 | fn main() { 39 | println!("{HELLO}"); 40 | } 41 | "# 42 | .into(), 43 | }, 44 | output_dir: None, // Option 45 | output_file: None, // Option 46 | file_loader: None, // Option> 47 | locale_resources: rustc_driver::DEFAULT_LOCALE_RESOURCES, 48 | lint_caps: FxHashMap::default(), // FxHashMap 49 | // This is a callback from the driver that is called when [`ParseSess`] is created. 50 | psess_created: None, //Option> 51 | // This is a callback from the driver that is called when we're registering lints; 52 | // it is called during plugin registration when we have the LintStore in a non-shared state. 53 | // 54 | // Note that if you find a Some here you probably want to call that function in the new 55 | // function being registered. 56 | register_lints: None, // Option> 57 | // This is a callback from the driver that is called just after we have populated 58 | // the list of queries. 59 | // 60 | // The second parameter is local providers and the third parameter is external providers. 61 | override_queries: None, // Option, &mut ty::query::Providers<'_>)> 62 | // Registry of diagnostics codes. 63 | registry: registry::Registry::new(rustc_errors::codes::DIAGNOSTICS), 64 | make_codegen_backend: None, 65 | expanded_args: Vec::new(), 66 | ice_file: None, 67 | hash_untracked_state: None, 68 | using_internal_features: Arc::default(), 69 | }; 70 | rustc_interface::run_compiler(config, |compiler| { 71 | compiler.enter(|queries| { 72 | // Parse the program and print the syntax tree. 73 | let parse = queries.parse().unwrap().get_mut().clone(); 74 | println!("{parse:?}"); 75 | // Analyze the program and inspect the types of definitions. 76 | queries.global_ctxt().unwrap().enter(|tcx| { 77 | for id in tcx.hir().items() { 78 | let hir = tcx.hir(); 79 | let item = hir.item(id); 80 | match item.kind { 81 | rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => { 82 | let name = item.ident; 83 | let ty = tcx.type_of(item.hir_id().owner.def_id); 84 | println!("{name:?}:\t{ty:?}") 85 | } 86 | _ => (), 87 | } 88 | } 89 | }) 90 | }); 91 | }); 92 | } 93 | -------------------------------------------------------------------------------- /ci/date-check/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "0.7.18" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "autocfg" 16 | version = "1.0.1" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 19 | 20 | [[package]] 21 | name = "chrono" 22 | version = "0.4.19" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" 25 | dependencies = [ 26 | "libc", 27 | "num-integer", 28 | "num-traits", 29 | "time", 30 | "winapi", 31 | ] 32 | 33 | [[package]] 34 | name = "date-check" 35 | version = "0.1.0" 36 | dependencies = [ 37 | "chrono", 38 | "glob", 39 | "regex", 40 | ] 41 | 42 | [[package]] 43 | name = "glob" 44 | version = "0.3.0" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" 47 | 48 | [[package]] 49 | name = "libc" 50 | version = "0.2.82" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" 53 | 54 | [[package]] 55 | name = "memchr" 56 | version = "2.5.0" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 59 | 60 | [[package]] 61 | name = "num-integer" 62 | version = "0.1.44" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 65 | dependencies = [ 66 | "autocfg", 67 | "num-traits", 68 | ] 69 | 70 | [[package]] 71 | name = "num-traits" 72 | version = "0.2.14" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 75 | dependencies = [ 76 | "autocfg", 77 | ] 78 | 79 | [[package]] 80 | name = "regex" 81 | version = "1.5.5" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" 84 | dependencies = [ 85 | "aho-corasick", 86 | "memchr", 87 | "regex-syntax", 88 | ] 89 | 90 | [[package]] 91 | name = "regex-syntax" 92 | version = "0.6.26" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" 95 | 96 | [[package]] 97 | name = "time" 98 | version = "0.1.44" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" 101 | dependencies = [ 102 | "libc", 103 | "wasi", 104 | "winapi", 105 | ] 106 | 107 | [[package]] 108 | name = "wasi" 109 | version = "0.10.0+wasi-snapshot-preview1" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 112 | 113 | [[package]] 114 | name = "winapi" 115 | version = "0.3.9" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 118 | dependencies = [ 119 | "winapi-i686-pc-windows-gnu", 120 | "winapi-x86_64-pc-windows-gnu", 121 | ] 122 | 123 | [[package]] 124 | name = "winapi-i686-pc-windows-gnu" 125 | version = "0.4.0" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 128 | 129 | [[package]] 130 | name = "winapi-x86_64-pc-windows-gnu" 131 | version = "0.4.0" 132 | source = "registry+https://github.com/rust-lang/crates.io-index" 133 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 134 | -------------------------------------------------------------------------------- /src/traits/unsize.md: -------------------------------------------------------------------------------- 1 | # [`CoerceUnsized`](https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html) 2 | 3 | `CoerceUnsized` is primarily concerned with data containers. When a struct 4 | (typically, a smart pointer) implements `CoerceUnsized`, that means that the 5 | data it points to is being unsized. 6 | 7 | Some implementors of `CoerceUnsized` include: 8 | * `&T` 9 | * `Arc` 10 | * `Box` 11 | 12 | This trait is (eventually) intended to be implemented by user-written smart 13 | pointers, and there are rules about when a type is allowed to implement 14 | `CoerceUnsized` that are explained in the trait's documentation. 15 | 16 | # [`Unsize`](https://doc.rust-lang.org/std/marker/trait.Unsize.html) 17 | 18 | To contrast, the `Unsize` trait is concerned the actual types that are allowed 19 | to be unsized. 20 | 21 | This is not intended to be implemented by users ever, since `Unsize` does not 22 | instruct the compiler (namely codegen) *how* to unsize a type, just whether it 23 | is allowed to be unsized. This is paired somewhat intimately with codegen 24 | which must understand how types are represented and unsized. 25 | 26 | ## Primitive unsizing implementations 27 | 28 | Built-in implementations are provided for: 29 | * `T` -> `dyn Trait + 'a` when `T: Trait` (and `T: Sized + 'a`, and `Trait` 30 | is object safe). 31 | * `[T; N]` -> `[T]` 32 | 33 | ## Structural implementations 34 | 35 | There are two implementations of `Unsize` which can be thought of as 36 | structural: 37 | * `(A1, A2, .., An): Unsize<(A1, A2, .., U)>` given `An: Unsize`, which 38 | allows the tail field of a tuple to be unsized. This is gated behind the 39 | [`unsized_tuple_coercion`] feature. 40 | * `Struct<.., Pi, .., Pj, ..>: Unsize>` given 41 | `TailField: Unsize`, which allows the tail field of a 42 | struct to be unsized if it is the only field that mentions generic parameters 43 | `Pi`, .., `Pj` (which don't need to be contiguous). 44 | 45 | The rules for the latter implementation are slightly complicated, since they 46 | may allow more than one parameter to be changed (not necessarily unsized) and 47 | are best stated in terms of the tail field of the struct. 48 | 49 | [`unsized_tuple_coercion`]: https://doc.rust-lang.org/beta/unstable-book/language-features/unsized-tuple-coercion.html 50 | 51 | ## Upcasting implementations 52 | 53 | Two things are called "upcasting" internally: 54 | 1. True upcasting `dyn SubTrait` -> `dyn SuperTrait` (this also allows 55 | dropping auto traits and adjusting lifetimes, as below). 56 | 2. Dropping auto traits and adjusting the lifetimes of dyn trait 57 | *without changing the principal[^1]*: 58 | `dyn Trait + AutoTraits... + 'a` -> `dyn Trait + NewAutoTraits... + 'b` 59 | when `AutoTraits` ⊇ `NewAutoTraits`, and `'a: 'b`. 60 | 61 | These may seem like different operations, since (1.) includes adjusting the 62 | vtable of a dyn trait, while (2.) is a no-op. However, to the type system, 63 | these are handled with much the same code. 64 | 65 | This built-in implementation of `Unsize` is the most involved, particularly 66 | after [it was reworked](https://github.com/rust-lang/rust/pull/114036) to 67 | support the complexities of associated types. 68 | 69 | Specifically, the upcasting algorithm involves: For each supertrait of the 70 | source dyn trait's principal (including itself)... 71 | 1. Unify the super trait ref with the principal of the target (making sure 72 | we only ever upcast to a true supertrait, and never [via an impl]). 73 | 2. For every auto trait in the target, check that it's present in the source 74 | (allowing us to drop auto traits, but never gain new ones). 75 | 3. For every projection in the target, check that it unifies with a single 76 | projection in the source (since there may be more than one given 77 | `trait Sub: Sup<.., A = i32> + Sup<.., A = u32>`). 78 | 79 | [via an impl]: https://github.com/rust-lang/rust/blob/f3457dbf84cd86d284454d12705861398ece76c3/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs#L19 80 | 81 | Specifically, (3.) prevents a choice of projection bound to guide inference 82 | unnecessarily, though it may guide inference when it is unambiguous. 83 | 84 | [^1]: The principal is the one non-auto trait of a `dyn Trait`. 85 | 86 | -------------------------------------------------------------------------------- /src/tests/ci.md: -------------------------------------------------------------------------------- 1 | # Testing with CI 2 | 3 | ## Testing infrastructure 4 | 5 | 6 | When a Pull Request is opened on GitHub, [GitHub Actions] will automatically 7 | launch a build that will run all tests on some configurations 8 | (x86_64-gnu-llvm-X linux, x86_64-gnu-tools linux, mingw-check linux and mingw-check-tidy linux). 9 | In essence, each runs `./x test` with various different options. 10 | 11 | The integration bot [bors] is used for coordinating merges to the master branch. 12 | When a PR is approved, it goes into a [queue] where merges are tested one at a 13 | time on a wide set of platforms using GitHub Actions. Due to the limit on the 14 | number of parallel jobs, we run the main CI jobs under the [rust-lang-ci] organization 15 | (in contrast to PR CI jobs, which run under `rust-lang` directly). 16 | Most platforms only run the build steps, some run a restricted set of tests, 17 | only a subset run the full suite of tests (see Rust's [platform tiers]). 18 | 19 | If everything passes, then all the distribution artifacts that were 20 | generated during the CI run are published. 21 | 22 | [GitHub Actions]: https://github.com/rust-lang/rust/actions 23 | [rust-lang-ci]: https://github.com/rust-lang-ci/rust/actions 24 | [bors]: https://github.com/rust-lang/homu 25 | [queue]: https://bors.rust-lang.org/queue/rust 26 | [platform tiers]: https://forge.rust-lang.org/release/platform-support.html#rust-platform-support 27 | 28 | ## Using CI to test 29 | 30 | In some cases, a PR may run into problems with running tests on a particular 31 | platform or configuration. 32 | If you can't run those tests locally, don't hesitate to use CI resources to 33 | try out a fix. 34 | 35 | As mentioned above, opening or updating a PR will only run on a small subset 36 | of configurations. 37 | Only when a PR is approved will it go through the full set of test configurations. 38 | However, you can try one of those configurations in your PR before it is approved. 39 | For example, if a Windows build fails, but you don't have access to a Windows 40 | machine, you can try running the Windows job that failed on CI within your PR 41 | after pushing a possible fix. 42 | 43 | To do this, you'll need to edit [`src/ci/github-actions/jobs.yml`]. It contains three 44 | sections that affect which CI jobs will be executed: 45 | - The `pr` section defines everything that will run after a push to a PR. 46 | - The `try` section defines job(s) that are run when you ask for a try build using `@bors try`. 47 | - The `auto` section defines the full set of tests that are run after a PR is approved and before 48 | it is merged into the main branch. 49 | 50 | You can copy one of the definitions from the `auto` section to the `pr` or `try` sections. 51 | For example, the `x86_64-msvc` job is responsible for running the 64-bit MSVC tests. 52 | You can copy it to the `pr` section to cause it to be executed after a commit is pushed to your 53 | PR, like this: 54 | 55 | ```yaml 56 | pr: 57 | ... 58 | - image: x86_64-gnu-tools 59 | <<: *job-linux-16c 60 | # this item was copied from the `auto` section 61 | # vvvvvvvvvvvvvvvvvv 62 | - image: x86_64-msvc 63 | env: 64 | RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler 65 | SCRIPT: make ci-msvc 66 | <<: *job-windows-8c 67 | ``` 68 | 69 | Then, you can commit the file and push to GitHub. GitHub Actions should launch the tests. 70 | 71 | After you have finished your tests, don't forget to remove any changes you have made to `jobs.yml`. 72 | 73 | If you need to make more complex modifications to CI, you will need to modify 74 | [`.github/workflows/ci.yml`] and possibly also 75 | [`src/ci/github-actions/calculate-job-matrix.py`]. 76 | 77 | Although you are welcome to use CI, just be conscious that this is a shared 78 | resource with limited concurrency. 79 | Try not to enable too many jobs at once (one or two should be sufficient in 80 | most cases). 81 | 82 | [`src/ci/github-actions/jobs.yml`]: https://github.com/rust-lang/rust/blob/master/src/ci/github-actions/jobs.yml 83 | [`.github/workflows/ci.yml`]: https://github.com/rust-lang/rust/blob/master/.github/workflows/ci.yml 84 | [`src/ci/github-actions/calculate-job-matrix.py`]: https://github.com/rust-lang/rust/blob/master/src/ci/github-actions/calculate-job-matrix.py 85 | -------------------------------------------------------------------------------- /src/ty_module/binders.md: -------------------------------------------------------------------------------- 1 | # `Binder` and Higher ranked regions 2 | 3 | Sometimes we define generic parmeters not on an item but as part of a type or a where clauses. As an example the type `for<'a> fn(&'a u32)` or the where clause `for<'a> T: Trait<'a>` both introduce a generic lifetime named `'a`. Currently there is no stable syntax for `for` or `for` but on nightly `feature(non_lifetime_binders)` feature can be used to write where clauses (but not types) using `for`/`for`. 4 | 5 | The `for` is referred to as a "binder" because it brings new names into scope. In rustc we use the `Binder` type to track where these parameters are introduced and what the parameters are (i.e. how many and whether they the parameter is a type/const/region). A type such as `for<'a> fn(&'a u32)` would be 6 | represented in rustc as: 7 | ``` 8 | Binder( 9 | fn(&RegionKind::Bound(DebruijnIndex(0), BoundVar(0)) u32) -> (), 10 | &[BoundVariableKind::Region(...)], 11 | ) 12 | ``` 13 | 14 | Usages of these parameters is represented by the `RegionKind::Bound` (or `TyKind::Bound`/`ConstKind::Bound` variants). These bound regions/types/consts are composed of two main pieces of data: 15 | - A [DebruijnIndex](../appendix/background.md#what-is-a-de-bruijn-index) to specify which binder we are referring to. 16 | - A [`BoundVar`] which specifies which of the parameters the `Binder` introduces we are referring to. 17 | - We also sometimes store some extra information for diagnostics reasons via the [`BoundTyKind`]/[`BoundRegionKind`] but this is not important for type equality or more generally the semantics of `Ty`. (omitted from the above example) 18 | 19 | In debug output (and also informally when talking to eachother) we tend to write these bound variables in the format of `^DebruijnIndex_BoundVar`. The above example would instead be written as `Binder(fn(&'^0_0), &[BoundVariableKind::Region])`. Sometimes when the `DebruijnIndex` is `0` we just omit it and would write `^0`. 20 | 21 | Another concrete example, this time a mixture of `for<'a>` in a where clause and a type: 22 | ``` 23 | where 24 | for<'a> Foo fn(&'a &'b T)>: Trait, 25 | ``` 26 | This would be represented as 27 | ``` 28 | Binder( 29 | Foo: Trait, 33 | [BoundVariableKind::Region(...)] 34 | ) 35 | ``` 36 | 37 | Note how the `'^1_0` refers to the `'a` parameter. We use a `DebruijnIndex` of `1` to refer to the binder one level up from the innermost one, and a var of `0` to refer to the first parameter bound which is `'a`. We also use `'^0` to refer to the `'b` parameter, the `DebruijnIndex` is `0` (referring to the innermost binder) so we omit it, leaving only the boundvar of `0` referring to the first parameter bound which is `'b`. 38 | 39 | We did not always explicitly track the set of bound vars introduced by each `Binder`, this caused a number of bugs (read: ICEs [#81193](https://github.com/rust-lang/rust/issues/81193), [#79949](https://github.com/rust-lang/rust/issues/79949), [#83017](https://github.com/rust-lang/rust/issues/83017)). By tracking these explicitly we can assert when constructing higher ranked where clauses/types that there are no escaping bound variables or variables from a different binder. See the following example of an invalid type inside of a binder: 40 | ``` 41 | Binder( 42 | fn(&'^1_0 &'^1 T/#0), 43 | &[BoundVariarbleKind::Region(...)], 44 | ) 45 | ``` 46 | This would cause all kinds of issues as the region `'^1_0` refers to a binder at a higher level than the outermost binder i.e. it is an escaping bound var. The `'^1` region (also writeable as `'^0_1`) is also ill formed as the binder it refers to does not introduce a second parameter. Modern day rustc will ICE when constructing this binder due to both of those regions, in the past we would have simply allowed this to work and then ran into issues in other parts of the codebase. 47 | 48 | [`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html 49 | [`BoundVar]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.BoundVar.html 50 | [`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html 51 | [`BoundTyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundTyKind.html 52 | -------------------------------------------------------------------------------- /src/borrow_check/two_phase_borrows.md: -------------------------------------------------------------------------------- 1 | # Two-phase borrows 2 | 3 | Two-phase borrows are a more permissive version of mutable borrows that allow 4 | nested method calls such as `vec.push(vec.len())`. Such borrows first act as 5 | shared borrows in a "reservation" phase and can later be "activated" into a 6 | full mutable borrow. 7 | 8 | Only certain implicit mutable borrows can be two-phase, any `&mut` or `ref mut` 9 | in the source code is never a two-phase borrow. The cases where we generate a 10 | two-phase borrow are: 11 | 12 | 1. The autoref borrow when calling a method with a mutable reference receiver. 13 | 2. A mutable reborrow in function arguments. 14 | 3. The implicit mutable borrow in an overloaded compound assignment operator. 15 | 16 | To give some examples: 17 | 18 | ```rust2018 19 | // In the source code 20 | 21 | // Case 1: 22 | let mut v = Vec::new(); 23 | v.push(v.len()); 24 | let r = &mut Vec::new(); 25 | r.push(r.len()); 26 | 27 | // Case 2: 28 | std::mem::replace(r, vec![1, r.len()]); 29 | 30 | // Case 3: 31 | let mut x = std::num::Wrapping(2); 32 | x += x; 33 | ``` 34 | 35 | Expanding these enough to show the two-phase borrows: 36 | 37 | ```rust,ignore 38 | // Case 1: 39 | let mut v = Vec::new(); 40 | let temp1 = &two_phase v; 41 | let temp2 = v.len(); 42 | Vec::push(temp1, temp2); 43 | let r = &mut Vec::new(); 44 | let temp3 = &two_phase *r; 45 | let temp4 = r.len(); 46 | Vec::push(temp3, temp4); 47 | 48 | // Case 2: 49 | let temp5 = &two_phase *r; 50 | let temp6 = vec![1, r.len()]; 51 | std::mem::replace(temp5, temp6); 52 | 53 | // Case 3: 54 | let mut x = std::num::Wrapping(2); 55 | let temp7 = &two_phase x; 56 | let temp8 = x; 57 | std::ops::AddAssign::add_assign(temp7, temp8); 58 | ``` 59 | 60 | Whether a borrow can be two-phase is tracked by a flag on the [`AutoBorrow`] 61 | after type checking, which is then [converted] to a [`BorrowKind`] during MIR 62 | construction. 63 | 64 | Each two-phase borrow is assigned to a temporary that is only used once. As 65 | such we can define: 66 | 67 | * The point where the temporary is assigned to is called the *reservation* 68 | point of the two-phase borrow. 69 | * The point where the temporary is used, which is effectively always a 70 | function call, is called the *activation* point. 71 | 72 | The activation points are found using the [`GatherBorrows`] visitor. The 73 | [`BorrowData`] then holds both the reservation and activation points for the 74 | borrow. 75 | 76 | [`AutoBorrow`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adjustment/enum.AutoBorrow.html 77 | [converted]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/cx/expr/trait.ToBorrowKind.html#method.to_borrow_kind 78 | [`BorrowKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.BorrowKind.html 79 | [`GatherBorrows`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/visit/trait.Visitor.html#method.visit_local 80 | [`BorrowData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/borrow_set/struct.BorrowData.html 81 | 82 | ## Checking two-phase borrows 83 | 84 | Two-phase borrows are treated as if they were mutable borrows with the 85 | following exceptions: 86 | 87 | 1. At every location in the MIR we [check] if any two-phase borrows are 88 | activated at this location. If a live two phase borrow is activated at a 89 | location, then we check that there are no borrows that conflict with the 90 | two-phase borrow. 91 | 2. At the reservation point we error if there are conflicting live *mutable* 92 | borrows. And lint if there are any conflicting shared borrows. 93 | 3. Between the reservation and the activation point, the two-phase borrow acts 94 | as a shared borrow. We determine (in [`is_active`]) if we're at such a point 95 | by using the [`Dominators`] for the MIR graph. 96 | 4. After the activation point, the two-phase borrow acts as a mutable borrow. 97 | 98 | [check]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/struct.MirBorrowckCtxt.html#method.check_activations 99 | [`Dominators`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/dominators/struct.Dominators.html 100 | [`is_active`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/path_utils/fn.is_active.html 101 | -------------------------------------------------------------------------------- /src/solve/canonicalization.md: -------------------------------------------------------------------------------- 1 | # Canonicalization 2 | 3 | Canonicalization is the process of *isolating* a value from its context and is necessary 4 | for global caching of goals which include inference variables. 5 | 6 | The idea is that given the goals `u32: Trait` and `u32: Trait`, where `?x` and `?y` 7 | are two different currently unconstrained inference variables, we should get the same result 8 | for both goals. We can therefore prove *the canonical query* `exists u32: Trait` once 9 | and reuse the result. 10 | 11 | Let's first go over the way canonical queries work and then dive into the specifics of 12 | how canonicalization works. 13 | 14 | ## A walkthrough of canonical queries 15 | 16 | To make this a bit easier, let's use the trait goal `u32: Trait` as an example with the 17 | assumption that the only relevant impl is `impl Trait> for u32`. 18 | 19 | ### Canonicalizing the input 20 | 21 | We start by *canonicalizing* the goal, replacing inference variables with existential and 22 | placeholders with universal bound variables. This would result in the *canonical goal* 23 | `exists u32: Trait`. 24 | 25 | We remember the original values of all bound variables in the original context. Here this would 26 | map `T` back to `?x`. These original values are used later on when dealing with the query 27 | response. 28 | 29 | We now call the canonical query with the canonical goal. 30 | 31 | ### Instantiating the canonical goal inside of the query 32 | 33 | To actually try to prove the canonical goal we start by instantiating the bound variables with 34 | inference variables and placeholders again. 35 | 36 | This happens inside of the query in a completely separate `InferCtxt`. Inside of the query we 37 | now have a goal `u32: Trait`. We also remember which value we've used to instantiate the bound 38 | variables in the canonical goal, which maps `T` to `?0`. 39 | 40 | We now compute the goal `u32: Trait` and figure out that this holds, but we've constrained 41 | `?0` to `Vec`. We finally convert this result to something useful to the caller. 42 | 43 | ### Canonicalizing the query response 44 | 45 | We have to return to the caller both whether the goal holds, and the inference constraints 46 | from inside of the query. 47 | 48 | To return the inference results to the caller we canonicalize the mapping from bound variables 49 | to the instantiated values in the query. This means that the query response is `Certainty::Yes` 50 | and a mapping from `T` to `exists Vec`. 51 | 52 | ### Instantiating the query response 53 | 54 | The caller now has to apply the constraints returned by the query. For this they first 55 | instantiate the bound variables of the canonical response with inference variables and 56 | placeholders again, so the mapping in the response is now from `T` to `Vec`. 57 | 58 | It now equates the original value of `T` (`?x`) with the value for `T` in the 59 | response (`Vec`), which correctly constrains `?x` to `Vec`. 60 | 61 | ## `ExternalConstraints` 62 | 63 | Computing a trait goal may not only constrain inference variables, it can also add region 64 | obligations, e.g. given a goal `(): AOutlivesB<'a, 'b>` we would like to return the fact that 65 | `'a: 'b` has to hold. 66 | 67 | This is done by not only returning the mapping from bound variables to the instantiated values 68 | from the query but also extracting additional `ExternalConstraints` from the `InferCtxt` context 69 | while building the response. 70 | 71 | ## How exactly does canonicalization work 72 | 73 | TODO: link to code once the PR lands and elaborate 74 | 75 | - types and consts: infer to existentially bound var, placeholder to universally bound var, 76 | considering universes 77 | - generic parameters in the input get treated as placeholders in the root universe 78 | - all regions in the input get all mapped to existentially bound vars and we "uniquify" them. 79 | `&'a (): Trait<'a>` gets canonicalized to `exists<'0, '1> &'0 (): Trait<'1>`. We do not care 80 | about their universes and simply put all regions into the highest universe of the input. 81 | - in the output everything in a universe of the caller gets put into the root universe and only 82 | gets its correct universe when we unify the var values with the orig values of the caller 83 | - we do not uniquify regions in the response and don't canonicalize `'static` -------------------------------------------------------------------------------- /src/notification-groups/about.md: -------------------------------------------------------------------------------- 1 | # Notification groups 2 | 3 | The **notification groups** are an easy way to help out with rustc in a 4 | "piece-meal" fashion, without committing to a larger project. 5 | Notification groups are **[easy to join](#join)** (just submit a PR!) 6 | and joining does not entail any particular commitment. 7 | 8 | Once you [join a notification group](#join), you will be added to 9 | a list that receives pings on github whenever a new issue is found 10 | that fits the notification group's criteria. If you are interested, you 11 | can then [claim the issue] and start working on it. 12 | 13 | Of course, you don't have to wait for new issues to be tagged! If you 14 | prefer, you can use the Github label for a notification group to 15 | search for existing issues that haven't been claimed yet. 16 | 17 | [claim the issue]: https://forge.rust-lang.org/triagebot/issue-assignment.html 18 | 19 | ## List of notification groups 20 | 21 | Here's the list of the notification groups: 22 | - [Apple](./apple.md) 23 | - [ARM](./arm.md) 24 | - [Cleanup Crew](./cleanup-crew.md) 25 | - [LLVM](./llvm.md) 26 | - [RISC-V](./risc-v.md) 27 | - [Windows](./windows.md) 28 | - [Rust for Linux](./rust-for-linux.md) 29 | 30 | ## What issues are a good fit for notification groups? 31 | 32 | Notification groups tend to get pinged on **isolated** bugs, 33 | particularly those of **middle priority**: 34 | 35 | - By **isolated**, we mean that we do not expect large-scale refactoring 36 | to be required to fix the bug. 37 | - By **middle priority**, we mean that we'd like to see the bug fixed, 38 | but it's not such a burning problem that we are dropping everything 39 | else to fix it. The danger with such bugs, of course, is that they 40 | can accumulate over time, and the role of the notification group is 41 | to try and stop that from happening! 42 | 43 | 44 | 45 | ## Joining a notification group 46 | 47 | To join a notification group, you just have to open a PR adding your 48 | Github username to the appropriate file in the Rust team repository. 49 | See the "example PRs" below to get a precise idea and to identify the 50 | file to edit. 51 | 52 | Also, if you are not already a member of a Rust team then -- in addition 53 | to adding your name to the file -- you have to checkout the repository and 54 | run the following command: 55 | 56 | ```bash 57 | cargo run add-person $your_user_name 58 | ``` 59 | 60 | Example PRs: 61 | 62 | * [Example of adding yourself to the Apple group.](https://github.com/rust-lang/team/pull/1434) 63 | * [Example of adding yourself to the ARM group.](https://github.com/rust-lang/team/pull/358) 64 | * [Example of adding yourself to the Cleanup Crew.](https://github.com/rust-lang/team/pull/221) 65 | * [Example of adding yourself to the LLVM group.](https://github.com/rust-lang/team/pull/140) 66 | * [Example of adding yourself to the RISC-V group.](https://github.com/rust-lang/team/pull/394) 67 | * [Example of adding yourself to the Windows group.](https://github.com/rust-lang/team/pull/348) 68 | 69 | ## Tagging an issue for a notification group 70 | 71 | To tag an issue as appropriate for a notification group, you give 72 | [rustbot] a [`ping`] command with the name of the notification 73 | group. For example: 74 | 75 | ```text 76 | @rustbot ping apple 77 | @rustbot ping llvm 78 | @rustbot ping cleanup-crew 79 | @rustbot ping windows 80 | @rustbot ping arm 81 | ``` 82 | 83 | To make some commands shorter and easier to remember, there are aliases, 84 | defined in the [`triagebot.toml`] file. For example, all of these commands 85 | are equivalent and will ping the Cleanup Crew: 86 | 87 | ```text 88 | @rustbot ping cleanup 89 | @rustbot ping bisect 90 | @rustbot ping reduce 91 | ``` 92 | 93 | Keep in mind that these aliases are meant to make humans' life easier. 94 | They might be subject to change. If you need to ensure that a command 95 | will always be valid, prefer the full invocations over the aliases. 96 | 97 | **Note though that this should only be done by compiler team members 98 | or contributors, and is typically done as part of compiler team 99 | triage.** 100 | 101 | [rustbot]: https://github.com/rust-lang/triagebot/ 102 | [`ping`]: https://forge.rust-lang.org/triagebot/pinging.html 103 | [`triagebot.toml`]: https://github.com/rust-lang/rust/blob/master/triagebot.toml 104 | -------------------------------------------------------------------------------- /src/notification-groups/cleanup-crew.md: -------------------------------------------------------------------------------- 1 | # Cleanup Crew 2 | 3 | **Github Label:** [ICEBreaker-Cleanup-Crew]
4 | **Ping command:** `@rustbot ping cleanup-crew` 5 | 6 | [ICEBreaker-Cleanup-Crew]: https://github.com/rust-lang/rust/labels/ICEBreaker-Cleanup-Crew 7 | 8 | The "Cleanup Crew" are focused on improving bug reports. Specifically, 9 | the goal is to try to ensure that every bug report has all the 10 | information that will be needed for someone to fix it: 11 | 12 | * a minimal, standalone example that shows the problem 13 | * links to duplicates or related bugs 14 | * if the bug is a regression (something that used to work, but no longer does), 15 | then a bisection to the PR or nightly that caused the regression 16 | 17 | This kind of cleanup is invaluable in getting bugs fixed. Better 18 | still, it can be done by anybody who knows Rust, without any 19 | particularly deep knowledge of the compiler. 20 | 21 | Let's look a bit at the workflow for doing "cleanup crew" actions. 22 | 23 | ## Finding a minimal, standalone example 24 | 25 | Here the ultimate goal is to produce an example that reproduces the same 26 | problem but without relying on any external crates. Such a test ought to contain 27 | as little code as possible, as well. This will make it much easier to isolate the problem. 28 | 29 | However, even if the "ultimate minimal test" cannot be achieved, it's 30 | still useful to post incremental minimizations. For example, if you 31 | can eliminate some of the external dependencies, that is helpful, and 32 | so forth. 33 | 34 | It's particularly useful to reduce to an example that works 35 | in the [Rust playground](https://play.rust-lang.org/), rather than 36 | requiring people to checkout a cargo build. 37 | 38 | There are many resources for how to produce minimized test cases. Here 39 | are a few: 40 | 41 | * The [rust-reduce](https://github.com/jethrogb/rust-reduce) tool can try to reduce 42 | code automatically. 43 | * The [C-reduce](https://github.com/csmith-project/creduce) tool also works 44 | on Rust code, though it requires that you start from a single 45 | file. (A post explaining how to do it can be found [here](https://insaneinside.net/2017/09/12/whole-crate-bug-reduction-with-creduce.html).) 46 | * pnkfelix's [Rust Bug Minimization Patterns] blog post 47 | * This post focuses on "heavy bore" techniques, where you are 48 | starting with a large, complex cargo project that you wish to 49 | narrow down to something standalone. 50 | 51 | [Rust Bug Minimization Patterns]: http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/ 52 | 53 | ## Links to duplicate or related bugs 54 | 55 | If you are on the "Cleanup Crew", you will sometimes see multiple bug 56 | reports that seem very similar. You can link one to the other just by 57 | mentioning the other bug number in a Github comment. Sometimes it is 58 | useful to close duplicate bugs. But if you do so, you should always 59 | copy any test case from the bug you are closing to the other bug that 60 | remains open, as sometimes duplicate-looking bugs will expose 61 | different facets of the same problem. 62 | 63 | ## Bisecting regressions 64 | 65 | For regressions (something that used to work, but no longer does), it 66 | is super useful if we can figure out precisely when the code stopped 67 | working. The gold standard is to be able to identify the precise 68 | **PR** that broke the code, so we can ping the author, but even 69 | narrowing it down to a nightly build is helpful, especially as that 70 | then gives us a range of PRs. (One other challenge is that we 71 | sometimes land "rollup" PRs, which combine multiple PRs into one.) 72 | 73 | ### cargo-bisect-rustc 74 | 75 | To help in figuring out the cause of a regression we have a tool 76 | called [cargo-bisect-rustc]. It will automatically download and test 77 | various builds of rustc. For recent regressions, it is even able to 78 | use the builds from our CI to track down the regression to a specific 79 | PR; for older regressions, it will simply identify a nightly. 80 | 81 | To learn to use [cargo-bisect-rustc], check out [this blog post][learn], which 82 | gives a quick introduction to how it works. Additionally, there is a [Guide] 83 | which goes into more detail on how to use it. You can also ask questions at 84 | the Zulip stream [`#t-compiler/cargo-bisect-rustc`][zcbr], or help in 85 | improving the tool. 86 | 87 | [cargo-bisect-rustc]: https://github.com/rust-lang/cargo-bisect-rustc/ 88 | [learn]: https://blog.rust-lang.org/inside-rust/2019/12/18/bisecting-rust-compiler.html 89 | [zcbr]: https://rust-lang.zulipchat.com/#narrow/stream/217417-t-compiler.2Fcargo-bisect-rustc 90 | [Guide]: https://rust-lang.github.io/cargo-bisect-rustc/ 91 | -------------------------------------------------------------------------------- /src/param_env/param_env_construction_internals.md: -------------------------------------------------------------------------------- 1 | 2 | # How are `ParamEnv`'s constructed internally? 3 | 4 | Creating a [`ParamEnv`][pe] is more complicated than simply using the list of where clauses defined on an item as written by the user. We need to both elaborate supertraits into the env and fully normalize all aliases. This logic is handled by [`traits::normalize_param_env_or_error`][normalize_env_or_error] (even though it does not mention anything about elaboration). 5 | 6 | ## Elaborating supertraits 7 | 8 | When we have a function such as `fn foo()` we would like to be able to prove `T: Clone` inside of the function as the `Copy` trait has a `Clone` supertrait. Constructing a `ParamEnv` looks at all of the trait bounds in the env and explicitly adds new where clauses to the `ParamEnv` for any supertraits found on the traits. 9 | 10 | A concrete example would be the following function: 11 | ```rust 12 | trait Trait: SuperTrait {} 13 | trait SuperTrait: SuperSuperTrait {} 14 | 15 | // `bar`'s unelaborated `ParamEnv` would be: 16 | // `[T: Sized, T: Copy, T: Trait]` 17 | fn bar(a: T) { 18 | requires_impl(a); 19 | } 20 | 21 | fn requires_impl(a: T) {} 22 | ``` 23 | 24 | If we did not elaborate the env then the `requires_impl` call would fail to typecheck as we would not be able to prove `T: Clone` or `T: SuperSuperTrait`. In practice we elaborate the env which means that `bar`'s `ParamEnv` is actually: 25 | `[T: Sized, T: Copy, T: Clone, T: Trait, T: SuperTrait, T: SuperSuperTrait]` 26 | This allows us to prove `T: Clone` and `T: SuperSuperTrait` when type checking `bar`. 27 | 28 | The `Clone` trait has a `Sized` supertrait however we do not end up with two `T: Sized` bounds in the env (one for the supertrait and one for the implicitly added `T: Sized` bound). This is because the elaboration process (implemented via [`util::elaborate`][elaborate]) deduplicates the where clauses to avoid this. 29 | 30 | As a side effect this also means that even if no actual elaboration of supertraits takes place, the existing where clauses in the env are _also_ deduplicated. See the following example: 31 | ```rust 32 | trait Trait {} 33 | // The unelaborated `ParamEnv` would be: 34 | // `[T: Sized, T: Trait, T: Trait]` 35 | // but after elaboration it would be: 36 | // `[T: Sized, T: Trait]` 37 | fn foo() {} 38 | ``` 39 | 40 | The [next-gen trait solver][next-gen-solver] also requires this elaboration to take place. 41 | 42 | [elaborate]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/traits/util/fn.elaborate.html 43 | [next-gen-solver]: https://rustc-dev-guide.rust-lang.org/solve/trait-solving.html 44 | 45 | ## Normalizing all bounds 46 | 47 | In the old trait solver the where clauses stored in `ParamEnv` are required to be fully normalized or else the trait solver will not function correctly. A concrete example of needing to normalize the `ParamEnv` is the following: 48 | ```rust 49 | trait Trait { 50 | type Assoc; 51 | } 52 | 53 | trait Other { 54 | type Bar; 55 | } 56 | 57 | impl Other for T { 58 | type Bar = u32; 59 | } 60 | 61 | // `foo`'s unnormalized `ParamEnv` would be: 62 | // `[T: Sized, U: Sized, U: Trait]` 63 | fn foo(a: U) 64 | where 65 | U: Trait<::Bar>, 66 | { 67 | requires_impl(a); 68 | } 69 | 70 | fn requires_impl>(_: U) {} 71 | ``` 72 | 73 | As humans we can tell that `::Bar` is equal to `u32` so the trait bound on `U` is equivalent to `U: Trait`. In practice trying to prove `U: Trait` in the old solver in this environment would fail as it is unable to determine that `::Bar` is equal to `u32`. 74 | 75 | To work around this we normalize `ParamEnv`'s after constructing them so that `foo`'s `ParamEnv` is actually: `[T: Sized, U: Sized, U: Trait]` which means the trait solver is now able to use the `U: Trait` in the `ParamEnv` to determine that the trait bound `U: Trait` holds. 76 | 77 | This workaround does not work in all cases as normalizing associated types requires a `ParamEnv` which introduces a bootstrapping problem. We need a normalized `ParamEnv` in order for normalization to give correct results, but we need to normalize to get that `ParamEnv`. Currently we normalize the `ParamEnv` once using the unnormalized param env and it tends to give okay results in practice even though there are some examples where this breaks ([example]). 78 | 79 | In the next-gen trait solver the requirement for all where clauses in the `ParamEnv` to be fully normalized is not present and so we do not normalize when constructing `ParamEnv`s. 80 | 81 | [example]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e6933265ea3e84eaa47019465739992c 82 | [pe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html 83 | [normalize_env_or_error]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/fn.normalize_param_env_or_error.html -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CI](https://github.com/rust-lang/rustc-dev-guide/actions/workflows/ci.yml/badge.svg)](https://github.com/rust-lang/rustc-dev-guide/actions/workflows/ci.yml) 2 | 3 | 4 | This is a collaborative effort to build a guide that explains how rustc 5 | works. The aim of the guide is to help new contributors get oriented 6 | to rustc, as well as to help more experienced folks in figuring out 7 | some new part of the compiler that they haven't worked on before. 8 | 9 | [You can read the latest version of the guide here.](https://rustc-dev-guide.rust-lang.org/) 10 | 11 | You may also find the rustdocs [for the compiler itself][rustdocs] useful. 12 | Note that these are not intended as a guide; it's recommended that you search 13 | for the docs you're looking for instead of reading them top to bottom. 14 | 15 | [rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc 16 | 17 | For documentation on developing the standard library, see 18 | [`std-dev-guide`](https://std-dev-guide.rust-lang.org/). 19 | 20 | ### Contributing to the guide 21 | 22 | The guide is useful today, but it has a lot of work still to go. 23 | 24 | If you'd like to help improve the guide, we'd love to have you! You can find 25 | plenty of issues on the [issue 26 | tracker](https://github.com/rust-lang/rustc-dev-guide/issues). Just post a 27 | comment on the issue you would like to work on to make sure that we don't 28 | accidentally duplicate work. If you think something is missing, please open an 29 | issue about it! 30 | 31 | **In general, if you don't know how the compiler works, that is not a 32 | problem!** In that case, what we will do is to schedule a bit of time 33 | for you to talk with someone who **does** know the code, or who wants 34 | to pair with you and figure it out. Then you can work on writing up 35 | what you learned. 36 | 37 | In general, when writing about a particular part of the compiler's code, we 38 | recommend that you link to the relevant parts of the [rustc 39 | rustdocs][rustdocs]. 40 | 41 | ### Build Instructions 42 | 43 | To build a local static HTML site, install [`mdbook`](https://github.com/rust-lang/mdBook) with: 44 | 45 | ``` 46 | > cargo install mdbook mdbook-linkcheck mdbook-toc mdbook-mermaid 47 | ``` 48 | 49 | and execute the following command in the root of the repository: 50 | 51 | ``` 52 | > mdbook build --open 53 | ``` 54 | 55 | The build files are found in the `book/html` directory. 56 | 57 | ### Link Validations 58 | 59 | We use `mdbook-linkcheck` to validate URLs included in our documentation. 60 | `linkcheck` will be run automatically when you build with the instructions in the section above. 61 | 62 | ### Table of Contents 63 | 64 | We use `mdbook-toc` to auto-generate TOCs for long sections. You can invoke the preprocessor by 65 | including the `` marker at the place where you want the TOC. 66 | 67 | ## How to fix toolstate failures 68 | 69 | > **NOTE**: Currently, we do not track the rustc-dev-guide toolstate due to 70 | [spurious failures](https://github.com/rust-lang/rust/pull/71731), 71 | but we leave these instructions for when we do it again in the future. 72 | 73 | 1. You will get a ping from the toolstate commit. e.g. https://github.com/rust-lang-nursery/rust-toolstate/commit/8ffa0e4c30ac9ba8546b7046e5c4ccc2b96ebdd4 74 | 75 | 2. The commit contains a link to the PR that caused the breakage. e.g. https://github.com/rust-lang/rust/pull/64321 76 | 77 | 3. If you go to that PR's thread, there is a post from bors with a link to the CI status: https://github.com/rust-lang/rust/pull/64321#issuecomment-529763807 78 | 79 | 4. Follow the check-actions link to get to the Actions page for that build 80 | 81 | 5. There will be approximately 1 billion different jobs for the build. They are for different configurations and platforms. The rustc-dev-guide build only runs on the Linux x86_64-gnu-tools job. So click on that job in the list, which is about 60% down in the list. 82 | 83 | 6. Click the Run build step in the job to get the console log for the step. 84 | 85 | 7. Click on the log and Ctrl-f to get a search box in the log 86 | 87 | 8. Search for rustc-dev-guide. This gets you to the place where the links are checked. It is usually ~11K lines into the log. 88 | 89 | 9. Look at the links in the log near that point in the log 90 | 91 | 10. Fix those links in the rustc-dev-guide (by making a PR in the rustc-dev-guide repo) 92 | 93 | 11. Make a PR on the rust-lang/rust repo to update the rustc-dev-guide git submodule in src/docs/rustc-dev-guide. 94 | To make a PR, the following steps are useful. 95 | 96 | ```bash 97 | # Assuming you already cloned the rust-lang/rust repo and you're in the correct directory 98 | git submodule update --remote src/doc/rustc-dev-guide 99 | git add -u 100 | git commit -m "Update rustc-dev-guide" 101 | # Note that you can use -i, which is short for --incremental, in the following command 102 | ./x test --incremental src/doc/rustc-dev-guide # This is optional and should succeed anyway 103 | # Open a PR in rust-lang/rust 104 | ``` 105 | 106 | 12. Wait for PR to merge 107 | 108 | Voilà! 109 | --------------------------------------------------------------------------------