├── triagebot.toml ├── src-zh ├── diagnostics │ └── json-format.md ├── mir │ ├── optimizations.md │ ├── mir_overview.dot │ ├── mir_detailed.dot │ ├── visitor.md │ ├── debugging.md │ ├── passes.md │ └── mir_overview.svg ├── hir-debugging.md ├── traits │ ├── regions.md │ ├── bibliography.md │ ├── specialization.md │ ├── lowering-module.md │ ├── index.md │ ├── caching.md │ └── hrtb.md ├── profiling.md ├── borrow_check │ ├── type_check.md │ ├── moves_and_initialization.md │ └── two_phase_borrows.md ├── part-1-intro.md ├── part-2-intro.md ├── important-links.md ├── crates-io.md ├── build-install-distribution-artifacts.md ├── param_env.md ├── about-this-guide.md ├── existential-types.md ├── compiler-documenting.md ├── const-eval.md ├── type-checking.md ├── kinds.md ├── codegen.md ├── the-parser.md ├── lowering.md ├── borrow_check.md ├── rustc-driver.md ├── incrcomp-debugging.md ├── tests │ └── running.md ├── method-lookup.md └── name-resolution.md ├── src ├── diagnostics │ └── json-format.md ├── mir │ ├── optimizations.md │ ├── mir_overview.dot │ ├── mir_detailed.dot │ ├── visitor.md │ ├── debugging.md │ ├── passes.md │ └── mir_overview.svg ├── borrow_check │ ├── region_inference │ │ ├── error_reporting.md │ │ └── closure_constraints.md │ ├── type_check.md │ ├── moves_and_initialization.md │ └── two_phase_borrows.md ├── hir-debugging.md ├── traits │ ├── regions.md │ ├── bibliography.md │ ├── specialization.md │ ├── lowering-module.md │ ├── index.md │ ├── caching.md │ └── hrtb.md ├── part-1-intro.md ├── profiling.md ├── part-2-intro.md ├── important-links.md ├── crates-io.md ├── build-install-distribution-artifacts.md ├── param_env.md ├── about-this-guide.md ├── existential-types.md ├── compiler-documenting.md ├── const-eval.md ├── type-checking.md ├── kinds.md ├── codegen.md ├── the-parser.md ├── lowering.md ├── borrow_check.md ├── rustc-driver.md ├── appendix │ └── background.md ├── incrcomp-debugging.md ├── tests │ └── running.md ├── ty.md ├── method-lookup.md ├── name-resolution.md └── compiler-team.md ├── .gitignore ├── .gitattributes ├── .editorconfig ├── .github └── ISSUE_TEMPLATE │ └── ----.md ├── book.toml ├── ci ├── install.sh └── check_line_lengths.sh ├── LICENSE-MIT ├── .travis.yml ├── README.md └── CODE_OF_CONDUCT.md /triagebot.toml: -------------------------------------------------------------------------------- 1 | [assign] 2 | -------------------------------------------------------------------------------- /src-zh/diagnostics/json-format.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/diagnostics/json-format.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | .vscode 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /src/mir/optimizations.md: -------------------------------------------------------------------------------- 1 | # MIR optimizations 2 | -------------------------------------------------------------------------------- /src-zh/mir/optimizations.md: -------------------------------------------------------------------------------- 1 | # MIR optimizations 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [src/*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [ci/*.sh] 8 | indent_style = space 9 | indent_size = 2 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/----.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 翻译任务 3 | about: 用于创建翻译任务 4 | title: "[从 `src-zh` 之后开始的文件名,如 `appendix\\glossary.md`]" 5 | labels: translation 6 | assignees: '' 7 | 8 | --- 9 | 10 | - [ ] 翻译 11 | - [ ] 校对 12 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /src-zh/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 | } -------------------------------------------------------------------------------- /src/hir-debugging.md: -------------------------------------------------------------------------------- 1 | # HIR Debugging 2 | 3 | The `-Zunpretty=hir-tree` flag will dump out the HIR. 4 | 5 | If you are trying to correlate `NodeId`s or `DefId`s with source code, the 6 | `--pretty expanded,identified` flag may be useful. 7 | 8 | TODO: anything else? 9 | -------------------------------------------------------------------------------- /src-zh/hir-debugging.md: -------------------------------------------------------------------------------- 1 | # HIR Debugging 2 | 3 | The `-Zunpretty=hir-tree` flag will dump out the HIR. 4 | 5 | If you are trying to correlate `NodeId`s or `DefId`s with source code, the 6 | `--pretty expanded,identified` flag may be useful. 7 | 8 | TODO: anything else? 9 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | title = "Rustc 开发指南" 3 | author = "Rustc 开发者" 4 | description = "Rustc 开发指南" 5 | src = "src-zh" 6 | 7 | [output.html] 8 | 9 | [output.html.search] 10 | 11 | [output.linkcheck] 12 | follow-web-links = true 13 | exclude = [ "crates\\.io", "gcc\\.godbolt\\.org" ] 14 | -------------------------------------------------------------------------------- /src/traits/regions.md: -------------------------------------------------------------------------------- 1 | # Region constraints 2 | 3 | *To be written.* 4 | 5 | Chalk does not have the concept of region constraints, and as of this 6 | writing, work on rustc was not far enough to worry about them. 7 | 8 | In the meantime, you can read about region constraints in the 9 | [type inference](../type-inference.html#region-constraints) section. 10 | -------------------------------------------------------------------------------- /src-zh/traits/regions.md: -------------------------------------------------------------------------------- 1 | # Region constraints 2 | 3 | *To be written.* 4 | 5 | Chalk does not have the concept of region constraints, and as of this 6 | writing, work on rustc was not far enough to worry about them. 7 | 8 | In the meantime, you can read about region constraints in the 9 | [type inference](../type-inference.html#region-constraints) section. 10 | -------------------------------------------------------------------------------- /src/part-1-intro.md: -------------------------------------------------------------------------------- 1 | # Part 1: Building, debugging, and contributing to Rustc 2 | 3 | This section of the rustc-guide contains knowledge that should be useful to you 4 | regardless of what part of the compiler you are working on. This includes both 5 | technical info and tips (e.g. how to compile and debug the compiler) and info 6 | about processes in the Rust project (e.g. stabilization and info about the 7 | compiler team). 8 | -------------------------------------------------------------------------------- /src-zh/profiling.md: -------------------------------------------------------------------------------- 1 | # Profiling the compiler 2 | 3 | This discussion talks about how profile the compiler and find out 4 | where it spends its time. If you just want to get a general overview, 5 | it is often a good idea to just add `-Zself-profile` option to the 6 | rustc command line. This will break down time spent into various 7 | categories. But if you want a more detailed look, you probably want 8 | to break out a custom profiler. 9 | 10 | -------------------------------------------------------------------------------- /src/profiling.md: -------------------------------------------------------------------------------- 1 | # Profiling the compiler 2 | 3 | This discussion talks about how profile the compiler and find out 4 | where it spends its time. If you just want to get a general overview, 5 | it is often a good idea to just add `-Zself-profile` option to the 6 | rustc command line. This will break down time spent into various 7 | categories. But if you want a more detailed look, you probably want 8 | to break out a custom profiler. 9 | 10 | -------------------------------------------------------------------------------- /src-zh/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_mir/borrow_check/nll/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 | -------------------------------------------------------------------------------- /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_mir/borrow_check/nll/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 | -------------------------------------------------------------------------------- /src-zh/part-1-intro.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | # 第一部分:构建、调试并为 Rustc 做贡献 12 | 13 | rustc 指南的这部分内容包含了对您有用的知识,不论您所从事的是编译器哪部分的工作。 14 | 包括技术的信息和技巧(例如:如何编译和调试编译器),以及关于 Rust 项目进度的消息(例如:关于编译器团队的稳定性和消息)。 15 | -------------------------------------------------------------------------------- /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-zh/part-2-intro.md: -------------------------------------------------------------------------------- 1 | # Part 2: How rustc works 2 | 3 | This part of the guide describes how the compiler works. It goes through 4 | everything from high-level structure of the compiler to how each stage of 5 | compilation works. 6 | 7 | This section should be friendly to both readers interested in the end-to-end 8 | process of compilation _and_ readers interested in learning about a specific 9 | system they wish to contribute to. If anything is unclear, feel free to file 10 | an issue on the [rustc-guide repo](https://github.com/rust-lang/rustc-guide) 11 | or contact the compiler team, as detailed in [this chapter from Part 12 | 1](./compiler-team.md). 13 | -------------------------------------------------------------------------------- /src/part-2-intro.md: -------------------------------------------------------------------------------- 1 | # Part 2: How rustc works 2 | 3 | This part of the guide describes how the compiler works. It goes through 4 | everything from high-level structure of the compiler to how each stage of 5 | compilation works. 6 | 7 | This section should be friendly to both readers interested in the end-to-end 8 | process of compilation _and_ readers interested in learning about a specific 9 | system they wish to contribute to. If anything is unclear, feel free to file 10 | an issue on the [rustc-guide repo](https://github.com/rust-lang/rustc-guide) 11 | or contact the compiler team, as detailed in [this chapter from Part 12 | 1](./compiler-team.md). 13 | -------------------------------------------------------------------------------- /ci/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | function cargo_install() { 6 | local name=$1 7 | local version=$2 8 | 9 | if command -v $name >/dev/null 2>&1; then 10 | local installed_version=`$name --version | sed -E 's/[a-zA-Z_-]+ v?//g'` 11 | if [ "$installed_version" == "$version" ]; then 12 | echo "$name $version is already installed at $(command -v $name)" 13 | else 14 | echo "Forcing install $name $version" 15 | cargo install $name --version $version --force 16 | fi 17 | else 18 | echo "Installing $name $version" 19 | cargo install $name --version $version 20 | fi 21 | } 22 | 23 | cargo_install mdbook 0.3.0 24 | cargo_install mdbook-linkcheck 0.3.0 25 | -------------------------------------------------------------------------------- /src-zh/important-links.md: -------------------------------------------------------------------------------- 1 | # Ignore me 2 | 3 | This file is a collection of links that are not link-checked by anyone else, 4 | but we want them to work. For example, the stabilization guide link is often 5 | posted to tracking issues on GitHub, which might break later if the guide is 6 | changed. 7 | 8 | [Skip this file. Or read it; I'm a book, not a cop.](https://imgur.com/gallery/mSHi8) 9 | 10 | [link](https://forge.rust-lang.org/stabilization-guide.html) 11 | [link](https://forge.rust-lang.org/stabilization-guide.html#updating-documentation) 12 | [link](https://forge.rust-lang.org/stabilization-guide.html#documentation-prs) 13 | 14 | [link](https://rust-lang.github.io/rustc-guide/stabilization_guide.html) 15 | [link](https://rust-lang.github.io/rustc-guide/stabilization_guide.html#updating-documentation) 16 | [link](https://rust-lang.github.io/rustc-guide/stabilization_guide.html#documentation-prs) 17 | -------------------------------------------------------------------------------- /src/important-links.md: -------------------------------------------------------------------------------- 1 | # Ignore me 2 | 3 | This file is a collection of links that are not link-checked by anyone else, 4 | but we want them to work. For example, the stabilization guide link is often 5 | posted to tracking issues on GitHub, which might break later if the guide is 6 | changed. 7 | 8 | [Skip this file. Or read it; I'm a book, not a cop.](https://imgur.com/gallery/mSHi8) 9 | 10 | [link](https://forge.rust-lang.org/stabilization-guide.html) 11 | [link](https://forge.rust-lang.org/stabilization-guide.html#updating-documentation) 12 | [link](https://forge.rust-lang.org/stabilization-guide.html#documentation-prs) 13 | 14 | [link](https://rust-lang.github.io/rustc-guide/stabilization_guide.html) 15 | [link](https://rust-lang.github.io/rustc-guide/stabilization_guide.html#updating-documentation) 16 | [link](https://rust-lang.github.io/rustc-guide/stabilization_guide.html#documentation-prs) 17 | -------------------------------------------------------------------------------- /src/crates-io.md: -------------------------------------------------------------------------------- 1 | # crates.io Dependencies 2 | 3 | The rust compiler supports building with some dependencies from `crates.io`. 4 | For example, `log` and `env_logger` come from `crates.io`. 5 | 6 | In general, you should avoid adding dependencies to the compiler for several 7 | reasons: 8 | 9 | - The dependency may not be high quality or well-maintained, whereas we want 10 | the compiler to be high-quality. 11 | - The dependency may not be using a compatible license. 12 | - The dependency may have transitive dependencies that have one of the above 13 | problems. 14 | 15 | TODO: what is the vetting process? 16 | 17 | ## Whitelist 18 | 19 | The `tidy` tool has a [whitelist] of crates that are allowed. To add a 20 | dependency that is not already in the compiler, you will need to add it to this 21 | whitelist. 22 | 23 | [whitelist]: https://github.com/rust-lang/rust/blob/659994627234ce7d95a1a52ad8756ce661059adf/src/tools/tidy/src/deps.rs#L56 24 | -------------------------------------------------------------------------------- /src-zh/crates-io.md: -------------------------------------------------------------------------------- 1 | # crates.io Dependencies 2 | 3 | The rust compiler supports building with some dependencies from `crates.io`. 4 | For example, `log` and `env_logger` come from `crates.io`. 5 | 6 | In general, you should avoid adding dependencies to the compiler for several 7 | reasons: 8 | 9 | - The dependency may not be high quality or well-maintained, whereas we want 10 | the compiler to be high-quality. 11 | - The dependency may not be using a compatible license. 12 | - The dependency may have transitive dependencies that have one of the above 13 | problems. 14 | 15 | TODO: what is the vetting process? 16 | 17 | ## Whitelist 18 | 19 | The `tidy` tool has a [whitelist] of crates that are allowed. To add a 20 | dependency that is not already in the compiler, you will need to add it to this 21 | whitelist. 22 | 23 | [whitelist]: https://github.com/rust-lang/rust/blob/659994627234ce7d95a1a52ad8756ce661059adf/src/tools/tidy/src/deps.rs#L56 24 | -------------------------------------------------------------------------------- /src-zh/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/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-zh/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.py 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.py 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.py 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/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.py 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.py 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.py 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 -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ci/check_line_lengths.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" == "--help" ]; then 4 | echo 'Usage:' 5 | echo ' MAX_LINE_LENGTH=100' "$0" 'src/**/*.md' 6 | exit 1 7 | fi 8 | 9 | if [ "$MAX_LINE_LENGTH" == "" ]; then 10 | echo '`MAX_LINE_LENGTH` environment variable not set. Try --help.' 11 | exit 1 12 | fi 13 | 14 | if [ "$1" == "" ]; then 15 | echo 'No files provided.' 16 | exit 1 17 | fi 18 | 19 | echo "Checking line lengths in all source files <= $MAX_LINE_LENGTH chars..." 20 | 21 | echo "Offending files and lines:" 22 | (( bad_lines = 0 )) 23 | (( inside_block = 0 )) 24 | for file in "$@" ; do 25 | echo "$file" 26 | (( line_no = 0 )) 27 | while IFS="" read -r line || [[ -n "$line" ]] ; do 28 | (( line_no++ )) 29 | if [[ "$line" =~ ^'```' ]] ; then 30 | (( inside_block = !$inside_block )) 31 | continue 32 | fi 33 | if ! (( $inside_block )) \ 34 | && ! [[ "$line" =~ " | "|"-|-"|"://"|"]:"|\[\^[^\ ]+\]: ]] \ 35 | && (( "${#line}" > $MAX_LINE_LENGTH )) ; then 36 | (( bad_lines++ )) 37 | echo -e "\t$line_no : $line" 38 | fi 39 | done < "$file" 40 | done 41 | 42 | echo "$bad_lines offending lines found." 43 | (( $bad_lines == 0 )) 44 | -------------------------------------------------------------------------------- /src-zh/traits/bibliography.md: -------------------------------------------------------------------------------- 1 | # Bibliography 2 | 3 | If you'd like to read more background material, here are some 4 | recommended texts and papers: 5 | 6 | [Programming with Higher-order Logic][phl], by Dale Miller and Gopalan 7 | Nadathur, covers the key concepts of Lambda prolog. Although it's a 8 | slim little volume, it's the kind of book where you learn something 9 | new every time you open it. 10 | 11 | [phl]: https://www.amazon.com/Programming-Higher-Order-Logic-Dale-Miller/dp/052187940X 12 | 13 | 14 | 15 | ["A proof procedure for the logic of Hereditary Harrop formulas"][pphhf], 16 | by Gopalan Nadathur. This paper covers the basics of universes, 17 | environments, and Lambda Prolog-style proof search. Quite readable. 18 | 19 | [pphhf]: https://dl.acm.org/citation.cfm?id=868380 20 | 21 | 22 | 23 | ["A new formulation of tabled resolution with delay"][nftrd], by 24 | [Theresa Swift]. This paper gives a kind of abstract treatment of the 25 | SLG formulation that is the basis for our on-demand solver. 26 | 27 | [nftrd]: https://dl.acm.org/citation.cfm?id=651202 28 | [ts]: http://www3.cs.stonybrook.edu/~tswift/ 29 | [Theresa Swift]: http://www3.cs.stonybrook.edu/~tswift/ 30 | -------------------------------------------------------------------------------- /src/traits/bibliography.md: -------------------------------------------------------------------------------- 1 | # Bibliography 2 | 3 | If you'd like to read more background material, here are some 4 | recommended texts and papers: 5 | 6 | [Programming with Higher-order Logic][phl], by Dale Miller and Gopalan 7 | Nadathur, covers the key concepts of Lambda prolog. Although it's a 8 | slim little volume, it's the kind of book where you learn something 9 | new every time you open it. 10 | 11 | [phl]: https://www.amazon.com/Programming-Higher-Order-Logic-Dale-Miller/dp/052187940X 12 | 13 | 14 | 15 | ["A proof procedure for the logic of Hereditary Harrop formulas"][pphhf], 16 | by Gopalan Nadathur. This paper covers the basics of universes, 17 | environments, and Lambda Prolog-style proof search. Quite readable. 18 | 19 | [pphhf]: https://dl.acm.org/citation.cfm?id=868380 20 | 21 | 22 | 23 | ["A new formulation of tabled resolution with delay"][nftrd], by 24 | [Theresa Swift]. This paper gives a kind of abstract treatment of the 25 | SLG formulation that is the basis for our on-demand solver. 26 | 27 | [nftrd]: https://dl.acm.org/citation.cfm?id=651202 28 | [ts]: http://www3.cs.stonybrook.edu/~tswift/ 29 | [Theresa Swift]: http://www3.cs.stonybrook.edu/~tswift/ 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - nightly 4 | cache: 5 | - cargo 6 | before_install: 7 | - shopt -s globstar 8 | - MAX_LINE_LENGTH=100 bash ci/check_line_lengths.sh src/**/*.md 9 | install: 10 | - source ~/.cargo/env || true 11 | - bash ci/install.sh 12 | script: 13 | - mdbook build 14 | - mdbook test 15 | notifications: 16 | email: 17 | on_success: never 18 | env: 19 | global: 20 | - secure: myJlqevjvj/AfJ7aHcQ+DrAh5YUw0JWARAVAX6lMI9AYl30ht3eJJ82mLkiLBVKgLqUuXQVvEYfRYORFLfKbDhlufUW+5xOxYTdeLY2Q+4aPwsJNFZ7WHbcIGrdgKioDgDvpL2QOTKw7sfy+vq+02XiGwUAHvh5B08lD6Cn7EtrNEgZx3kKivY6HJ0k8VU8vBKKN4iW/etXS7E+OyFIcTbTJX16HZgGy1uLgSyoTv15BD0I+7fPa0PNmjzzpoky/+M+lVhYEx9lPRdKOgVknoXoAxqSJUUzVMBb1SSPFSMf8xEBGUhnRCe0sz/wGDpfpBvG4b3sL+cG6VfjSVEEtICimjlz7mQVf9C8VtDBq3jwNwsRf9UYoEwY12bWS4CsPQftclUysn4Ww5G/uDIv8U6BQrOWMP1evBJg1vq20r4m58f9E+pptLN2QdR+B+10jRWtY8lUAwGGlS4U3eNhhzlSuOTlrWBUuTzvFifIpoLrOowgE+Vebtu2W0Lii90yADTns1tCvy7Aa72JxxnlzAZ60OQznLXJtSW4I5oD0b+Wi6YRIqBDjcewQVQJIkIc4qZiOZ5zMD9gpQZgp8EcH3FASnMXDOFUbuEijKKXEH9VnP/j9WN8+fbTa1WX3YwnbrhbXTE0c6kwvYpwrdzZDbHf/sqFiMypJeBEclSoOhy8= 21 | deploy: 22 | provider: pages 23 | skip-cleanup: true 24 | github-token: "$GITHUB_TOKEN" 25 | local-dir: book/html 26 | on: 27 | branch: master 28 | -------------------------------------------------------------------------------- /src/param_env.md: -------------------------------------------------------------------------------- 1 | # Parameter Environment 2 | 3 | When working with associated and/or or generic items (types, constants, 4 | functions/methods) it is often relevant to have more information about the 5 | `Self` or generic parameters. Trait bounds and similar information is encoded in 6 | the `ParamEnv`. Often this is not enough information to obtain things like the 7 | type's `Layout`, but you can do all kinds of other checks on it (e.g. whether a 8 | type implements `Copy`) or you can evaluate an associated constant whose value 9 | does not depend on anything from the parameter environment. 10 | 11 | For example if you have a function 12 | 13 | ```rust 14 | fn foo(t: T) { 15 | } 16 | ``` 17 | 18 | the parameter environment for that function is `[T: Copy]`. This means any 19 | evaluation within this function will, when accessing the type `T`, know about 20 | its `Copy` bound via the parameter environment. 21 | 22 | Although you can obtain a valid `ParamEnv` for any item via 23 | `tcx.param_env(def_id)`, this `ParamEnv` can be too generic for your use case. 24 | Using the `ParamEnv` from the surrounding context can allow you to evaluate more 25 | things. 26 | 27 | Another great thing about `ParamEnv` is that you can use it to bundle the thing 28 | depending on generic parameters (e.g. a `Ty`) by calling `param_env.and(ty)`. 29 | This will produce a `ParamEnvAnd`, making clear that you should probably not 30 | be using the inner value without taking care to also use the `ParamEnv`. 31 | -------------------------------------------------------------------------------- /src-zh/param_env.md: -------------------------------------------------------------------------------- 1 | # Parameter Environment 2 | 3 | When working with associated and/or or generic items (types, constants, 4 | functions/methods) it is often relevant to have more information about the 5 | `Self` or generic parameters. Trait bounds and similar information is encoded in 6 | the `ParamEnv`. Often this is not enough information to obtain things like the 7 | type's `Layout`, but you can do all kinds of other checks on it (e.g. whether a 8 | type implements `Copy`) or you can evaluate an associated constant whose value 9 | does not depend on anything from the parameter environment. 10 | 11 | For example if you have a function 12 | 13 | ```rust 14 | fn foo(t: T) { 15 | } 16 | ``` 17 | 18 | the parameter environment for that function is `[T: Copy]`. This means any 19 | evaluation within this function will, when accessing the type `T`, know about 20 | its `Copy` bound via the parameter environment. 21 | 22 | Although you can obtain a valid `ParamEnv` for any item via 23 | `tcx.param_env(def_id)`, this `ParamEnv` can be too generic for your use case. 24 | Using the `ParamEnv` from the surrounding context can allow you to evaluate more 25 | things. 26 | 27 | Another great thing about `ParamEnv` is that you can use it to bundle the thing 28 | depending on generic parameters (e.g. a `Ty`) by calling `param_env.and(ty)`. 29 | This will produce a `ParamEnvAnd`, making clear that you should probably not 30 | be using the inner value without taking care to also use the `ParamEnv`. 31 | -------------------------------------------------------------------------------- /src/about-this-guide.md: -------------------------------------------------------------------------------- 1 | # About this guide 2 | 3 | This guide is meant to help document how rustc – the Rust compiler – 4 | works, as well as to help new contributors get involved in rustc 5 | development. It is not meant to replace code documentation – each 6 | chapter gives only high-level details – the kinds of things that 7 | (ideally) don't change frequently. 8 | 9 | There are three parts to this guide. Part 1 contains information that should 10 | be useful no matter how you are contributing. Part 2 contains information 11 | about how the compiler works. Finally, there are some appendices at the 12 | end with useful reference information. 13 | 14 | The guide itself is of course open-source as well, and the sources can 15 | be found at the [GitHub repository]. If you find any mistakes in the 16 | guide, please file an issue about it, or even better, open a PR 17 | with a correction! 18 | 19 | ## Other places to find information 20 | 21 | You might also find the following sites useful: 22 | 23 | - [Rustc API docs] -- rustdoc documentation for the compiler 24 | - [Forge] -- contains documentation about rust infrastructure, team procedures, and more 25 | - [compiler-team] -- the home-base for the rust compiler team, with description 26 | of the team procedures, active working groups, and the team calendar. 27 | 28 | [GitHub repository]: https://github.com/rust-lang/rustc-guide/ 29 | [Rustc API docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ 30 | [Forge]: https://forge.rust-lang.org/ 31 | [compiler-team]: https://github.com/rust-lang/compiler-team/ 32 | -------------------------------------------------------------------------------- /src-zh/about-this-guide.md: -------------------------------------------------------------------------------- 1 | # About this guide 2 | 3 | This guide is meant to help document how rustc – the Rust compiler – 4 | works, as well as to help new contributors get involved in rustc 5 | development. It is not meant to replace code documentation – each 6 | chapter gives only high-level details – the kinds of things that 7 | (ideally) don't change frequently. 8 | 9 | There are three parts to this guide. Part 1 contains information that should 10 | be useful no matter how you are contributing. Part 2 contains information 11 | about how the compiler works. Finally, there are some appendices at the 12 | end with useful reference information. 13 | 14 | The guide itself is of course open-source as well, and the sources can 15 | be found at the [GitHub repository]. If you find any mistakes in the 16 | guide, please file an issue about it, or even better, open a PR 17 | with a correction! 18 | 19 | ## Other places to find information 20 | 21 | You might also find the following sites useful: 22 | 23 | - [Rustc API docs] -- rustdoc documentation for the compiler 24 | - [Forge] -- contains documentation about rust infrastructure, team procedures, and more 25 | - [compiler-team] -- the home-base for the rust compiler team, with description 26 | of the team procedures, active working groups, and the team calendar. 27 | 28 | [GitHub repository]: https://github.com/rust-lang/rustc-guide/ 29 | [Rustc API docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ 30 | [Forge]: https://forge.rust-lang.org/ 31 | [compiler-team]: https://github.com/rust-lang/compiler-team/ 32 | -------------------------------------------------------------------------------- /src/existential-types.md: -------------------------------------------------------------------------------- 1 | # Existential Types 2 | 3 | Existential types are essentially strong type aliases which only expose 4 | a specific set of traits as their interface and the concrete type in the 5 | background is inferred from a certain set of use sites of the existential 6 | type. 7 | 8 | In the language they are expressed via 9 | 10 | ```rust,ignore 11 | existential type Foo: Bar; 12 | ``` 13 | 14 | This is in existential type named `Foo` which can be interacted with via 15 | the `Bar` trait's interface. 16 | 17 | Since there needs to be a concrete background type, you can currently 18 | express that type by using the existential type in a "defining use site". 19 | 20 | ```rust,ignore 21 | struct Struct; 22 | impl Bar for Struct { /* stuff */ } 23 | fn foo() -> Foo { 24 | Struct 25 | } 26 | ``` 27 | 28 | Any other "defining use site" needs to produce the exact same type. 29 | 30 | ## Defining use site(s) 31 | 32 | Currently only the return value of a function inside can 33 | be a defining use site of an existential type (and only if the return 34 | type of that function contains the existential type). 35 | 36 | The defining use of an existential type can be any code *within* the parent 37 | of the existential type definition. This includes any siblings of the 38 | existential type and all children of the siblings. 39 | 40 | The initiative for *"not causing fatal brain damage to developers due to 41 | accidentally running infinite loops in their brain while trying to 42 | comprehend what the type system is doing"* has decided to disallow children 43 | of existential types to be defining use sites. 44 | 45 | ### Associated existential types 46 | 47 | Associated existential types can be defined by any other associated item 48 | on the same trait `impl` or a child of these associated items. 49 | -------------------------------------------------------------------------------- /src-zh/existential-types.md: -------------------------------------------------------------------------------- 1 | # Existential Types 2 | 3 | Existential types are essentially strong type aliases which only expose 4 | a specific set of traits as their interface and the concrete type in the 5 | background is inferred from a certain set of use sites of the existential 6 | type. 7 | 8 | In the language they are expressed via 9 | 10 | ```rust,ignore 11 | existential type Foo: Bar; 12 | ``` 13 | 14 | This is in existential type named `Foo` which can be interacted with via 15 | the `Bar` trait's interface. 16 | 17 | Since there needs to be a concrete background type, you can currently 18 | express that type by using the existential type in a "defining use site". 19 | 20 | ```rust,ignore 21 | struct Struct; 22 | impl Bar for Struct { /* stuff */ } 23 | fn foo() -> Foo { 24 | Struct 25 | } 26 | ``` 27 | 28 | Any other "defining use site" needs to produce the exact same type. 29 | 30 | ## Defining use site(s) 31 | 32 | Currently only the return value of a function inside can 33 | be a defining use site of an existential type (and only if the return 34 | type of that function contains the existential type). 35 | 36 | The defining use of an existential type can be any code *within* the parent 37 | of the existential type definition. This includes any siblings of the 38 | existential type and all children of the siblings. 39 | 40 | The initiative for *"not causing fatal brain damage to developers due to 41 | accidentally running infinite loops in their brain while trying to 42 | comprehend what the type system is doing"* has decided to disallow children 43 | of existential types to be defining use sites. 44 | 45 | ### Associated existential types 46 | 47 | Associated existential types can be defined by any other associated item 48 | on the same trait `impl` or a child of these associated items. 49 | -------------------------------------------------------------------------------- /src-zh/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/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/compiler-documenting.md: -------------------------------------------------------------------------------- 1 | # Documenting rustc 2 | 3 | You might want to build documentation of the various components 4 | available like the standard library. There’s two ways to go about this. 5 | You can run rustdoc directly on the file to make sure the HTML is 6 | correct, which is fast. Alternatively, you can build the documentation 7 | as part of the build process through x.py. Both are viable methods 8 | since documentation is more about the content. 9 | 10 | ## Document everything 11 | 12 | ```bash 13 | ./x.py doc 14 | ``` 15 | 16 | ## If you want to avoid the whole Stage 2 build 17 | 18 | ```bash 19 | ./x.py doc --stage 1 20 | ``` 21 | 22 | First the compiler and rustdoc get built to make sure everything is okay 23 | and then it documents the files. 24 | 25 | ## Document specific components 26 | 27 | ```bash 28 | ./x.py doc src/doc/book 29 | ./x.py doc src/doc/nomicon 30 | ./x.py doc src/doc/book src/libstd 31 | ``` 32 | 33 | Much like individual tests or building certain components you can build only 34 | the documentation you want. 35 | 36 | ## Document internal rustc items 37 | 38 | Compiler documentation is not built by default. There's a flag in 39 | config.toml for achieving the same. 40 | But, when enabled, compiler documentation does include internal items. 41 | 42 | Next open up config.toml and make sure these two lines are set to true: 43 | 44 | ```bash 45 | docs = true 46 | compiler-docs = true 47 | ``` 48 | 49 | When you want to build the compiler docs as well run this command: 50 | 51 | ```bash 52 | ./x.py doc 53 | ``` 54 | 55 | This will see that the docs and compiler-docs options are set to true 56 | and build the normally hidden compiler docs! 57 | 58 | ### Compiler Documentation 59 | 60 | The documentation for the rust components are found at [rustc doc]. 61 | 62 | [rustc doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ -------------------------------------------------------------------------------- /src-zh/compiler-documenting.md: -------------------------------------------------------------------------------- 1 | # Documenting rustc 2 | 3 | You might want to build documentation of the various components 4 | available like the standard library. There’s two ways to go about this. 5 | You can run rustdoc directly on the file to make sure the HTML is 6 | correct, which is fast. Alternatively, you can build the documentation 7 | as part of the build process through x.py. Both are viable methods 8 | since documentation is more about the content. 9 | 10 | ## Document everything 11 | 12 | ```bash 13 | ./x.py doc 14 | ``` 15 | 16 | ## If you want to avoid the whole Stage 2 build 17 | 18 | ```bash 19 | ./x.py doc --stage 1 20 | ``` 21 | 22 | First the compiler and rustdoc get built to make sure everything is okay 23 | and then it documents the files. 24 | 25 | ## Document specific components 26 | 27 | ```bash 28 | ./x.py doc src/doc/book 29 | ./x.py doc src/doc/nomicon 30 | ./x.py doc src/doc/book src/libstd 31 | ``` 32 | 33 | Much like individual tests or building certain components you can build only 34 | the documentation you want. 35 | 36 | ## Document internal rustc items 37 | 38 | Compiler documentation is not built by default. There's a flag in 39 | config.toml for achieving the same. 40 | But, when enabled, compiler documentation does include internal items. 41 | 42 | Next open up config.toml and make sure these two lines are set to true: 43 | 44 | ```bash 45 | docs = true 46 | compiler-docs = true 47 | ``` 48 | 49 | When you want to build the compiler docs as well run this command: 50 | 51 | ```bash 52 | ./x.py doc 53 | ``` 54 | 55 | This will see that the docs and compiler-docs options are set to true 56 | and build the normally hidden compiler docs! 57 | 58 | ### Compiler Documentation 59 | 60 | The documentation for the rust components are found at [rustc doc]. 61 | 62 | [rustc doc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a collaborative effort to build a guide that explains how rustc 2 | works. The aim of the guide is to help new contributors get oriented 3 | to rustc, as well as to help more experienced folks in figuring out 4 | some new part of the compiler that they haven't worked on before. 5 | 6 | [You can read the latest version of the guide here.](https://rust-lang-nursery.github.io/rustc-guide/) 7 | 8 | You may also find the rustdocs [for the compiler itself][rustdocs] useful. 9 | 10 | [rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ 11 | 12 | ### Contributing to the guide 13 | 14 | The guide is useful today, but it has a lot of work still go. 15 | 16 | If you'd like to help improve the guide, we'd love to have you! You can find 17 | plenty of issues on the [issue 18 | tracker](https://github.com/rust-lang/rustc-guide/issues). Just post a 19 | comment on the issue you would like to work on to make sure that we don't 20 | accidentally duplicate work. If you think something is missing, please open an 21 | issue about it! 22 | 23 | **In general, if you don't know how the compiler works, that is not a 24 | problem!** In that case, what we will do is to schedule a bit of time 25 | for you to talk with someone who **does** know the code, or who wants 26 | to pair with you and figure it out. Then you can work on writing up 27 | what you learned. 28 | 29 | In general, when writing about a particular part of the compiler's code, we 30 | recommend that you link to the relevant parts of the [rustc 31 | rustdocs][rustdocs]. 32 | 33 | To help prevent accidentally introducing broken links, we use the 34 | `mdbook-linkcheck`. If installed on your machine `mdbook` will automatically 35 | invoke this link checker, otherwise it will emit a warning saying it couldn't 36 | be found. 37 | 38 | ```bash 39 | > cargo install mdbook-linkcheck 40 | ``` 41 | 42 | You will need `mdbook` version `>= 0.2`. `linkcheck` will be run automatically 43 | when you run `mdbook build`. 44 | -------------------------------------------------------------------------------- /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 | Constant evaluation can be done by calling the `const_eval` query of `TyCtxt`. 24 | 25 | The `const_eval` query takes a [`ParamEnv`](./param_env.html) of environment in 26 | which the constant is evaluated (e.g. the function within which the constant is 27 | used) and a `GlobalId`. The `GlobalId` is made up of an 28 | `Instance` referring to a constant or static or of an 29 | `Instance` of a function and an index into the function's `Promoted` table. 30 | 31 | Constant evaluation returns a `Result` with either the error, or the simplest 32 | representation of the constant. "simplest" meaning if it is representable as an 33 | integer or fat pointer, it will directly yield the value (via `ConstValue::Scalar` or 34 | `ConstValue::ScalarPair`), instead of referring to the [`miri`](./miri.html) virtual 35 | memory allocation (via `ConstValue::ByRef`). This means that the `const_eval` 36 | function cannot be used to create miri-pointers to the evaluated constant or 37 | static. If you need that, you need to directly work with the functions in 38 | [src/librustc_mir/const_eval.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/const_eval/index.html). 39 | -------------------------------------------------------------------------------- /src-zh/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 | Constant evaluation can be done by calling the `const_eval` query of `TyCtxt`. 24 | 25 | The `const_eval` query takes a [`ParamEnv`](./param_env.html) of environment in 26 | which the constant is evaluated (e.g. the function within which the constant is 27 | used) and a `GlobalId`. The `GlobalId` is made up of an 28 | `Instance` referring to a constant or static or of an 29 | `Instance` of a function and an index into the function's `Promoted` table. 30 | 31 | Constant evaluation returns a `Result` with either the error, or the simplest 32 | representation of the constant. "simplest" meaning if it is representable as an 33 | integer or fat pointer, it will directly yield the value (via `ConstValue::Scalar` or 34 | `ConstValue::ScalarPair`), instead of referring to the [`miri`](./miri.html) virtual 35 | memory allocation (via `ConstValue::ByRef`). This means that the `const_eval` 36 | function cannot be used to create miri-pointers to the evaluated constant or 37 | static. If you need that, you need to directly work with the functions in 38 | [src/librustc_mir/const_eval.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/const_eval/index.html). 39 | -------------------------------------------------------------------------------- /src/type-checking.md: -------------------------------------------------------------------------------- 1 | # Type checking 2 | 3 | The [`rustc_typeck`][typeck] crate contains the source for "type collection" 4 | and "type checking", as well as a few other bits of related functionality. (It 5 | draws heavily on the [type inference] and [trait solving].) 6 | 7 | [typeck]: https://github.com/rust-lang/rust/tree/master/src/librustc_typeck 8 | [type inference]: type-inference.html 9 | [trait solving]: traits/resolution.html 10 | 11 | ## Type collection 12 | 13 | Type "collection" is the process of converting the types found in the HIR 14 | (`hir::Ty`), which represent the syntactic things that the user wrote, into the 15 | **internal representation** used by the compiler (`Ty<'tcx>`) – we also do 16 | similar conversions for where-clauses and other bits of the function signature. 17 | 18 | To try and get a sense for the difference, consider this function: 19 | 20 | ```rust,ignore 21 | struct Foo { } 22 | fn foo(x: Foo, y: self::Foo) { ... } 23 | // ^^^ ^^^^^^^^^ 24 | ``` 25 | 26 | Those two parameters `x` and `y` each have the same type: but they will have 27 | distinct `hir::Ty` nodes. Those nodes will have different spans, and of course 28 | they encode the path somewhat differently. But once they are "collected" into 29 | `Ty<'tcx>` nodes, they will be represented by the exact same internal type. 30 | 31 | Collection is defined as a bundle of [queries] for computing information about 32 | the various functions, traits, and other items in the crate being compiled. 33 | Note that each of these queries is concerned with *interprocedural* things – 34 | for example, for a function definition, collection will figure out the type and 35 | signature of the function, but it will not visit the *body* of the function in 36 | any way, nor examine type annotations on local variables (that's the job of 37 | type *checking*). 38 | 39 | For more details, see the [`collect`][collect] module. 40 | 41 | [queries]: query.html 42 | [collect]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/collect/ 43 | 44 | **TODO**: actually talk about type checking... 45 | -------------------------------------------------------------------------------- /src-zh/type-checking.md: -------------------------------------------------------------------------------- 1 | # Type checking 2 | 3 | The [`rustc_typeck`][typeck] crate contains the source for "type collection" 4 | and "type checking", as well as a few other bits of related functionality. (It 5 | draws heavily on the [type inference] and [trait solving].) 6 | 7 | [typeck]: https://github.com/rust-lang/rust/tree/master/src/librustc_typeck 8 | [type inference]: type-inference.html 9 | [trait solving]: traits/resolution.html 10 | 11 | ## Type collection 12 | 13 | Type "collection" is the process of converting the types found in the HIR 14 | (`hir::Ty`), which represent the syntactic things that the user wrote, into the 15 | **internal representation** used by the compiler (`Ty<'tcx>`) – we also do 16 | similar conversions for where-clauses and other bits of the function signature. 17 | 18 | To try and get a sense for the difference, consider this function: 19 | 20 | ```rust,ignore 21 | struct Foo { } 22 | fn foo(x: Foo, y: self::Foo) { ... } 23 | // ^^^ ^^^^^^^^^ 24 | ``` 25 | 26 | Those two parameters `x` and `y` each have the same type: but they will have 27 | distinct `hir::Ty` nodes. Those nodes will have different spans, and of course 28 | they encode the path somewhat differently. But once they are "collected" into 29 | `Ty<'tcx>` nodes, they will be represented by the exact same internal type. 30 | 31 | Collection is defined as a bundle of [queries] for computing information about 32 | the various functions, traits, and other items in the crate being compiled. 33 | Note that each of these queries is concerned with *interprocedural* things – 34 | for example, for a function definition, collection will figure out the type and 35 | signature of the function, but it will not visit the *body* of the function in 36 | any way, nor examine type annotations on local variables (that's the job of 37 | type *checking*). 38 | 39 | For more details, see the [`collect`][collect] module. 40 | 41 | [queries]: query.html 42 | [collect]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/collect/ 43 | 44 | **TODO**: actually talk about type checking... 45 | -------------------------------------------------------------------------------- /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::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/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 NoLandingPads { 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 [`NoLandingPads`]. 41 | That visitor doesn't even require any state: it just visits all 42 | terminators and removes their `unwind` successors. 43 | 44 | [`NoLandingPads`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/no_landing_pads/struct.NoLandingPads.html 45 | 46 | ## Traversal 47 | 48 | In addition the visitor, [the `rustc::mir::traversal` module][t] 49 | contains useful functions for walking the MIR CFG in 50 | [different standard orders][traversal] (e.g. pre-order, reverse 51 | post-order, and so forth). 52 | 53 | [t]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/traversal/index.html 54 | [traversal]: https://en.wikipedia.org/wiki/Tree_traversal 55 | 56 | -------------------------------------------------------------------------------- /src-zh/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::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/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<'cx, 'tcx, '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 NoLandingPads { 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 [`NoLandingPads`]. 41 | That visitor doesn't even require any state: it just visits all 42 | terminators and removes their `unwind` successors. 43 | 44 | [`NoLandingPads`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/no_landing_pads/struct.NoLandingPads.html 45 | 46 | ## Traversal 47 | 48 | In addition the visitor, [the `rustc::mir::traversal` module][t] 49 | contains useful functions for walking the MIR CFG in 50 | [different standard orders][traversal] (e.g. pre-order, reverse 51 | post-order, and so forth). 52 | 53 | [t]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/traversal/index.html 54 | [traversal]: https://en.wikipedia.org/wiki/Tree_traversal 55 | 56 | -------------------------------------------------------------------------------- /src/kinds.md: -------------------------------------------------------------------------------- 1 | # Kinds 2 | A `ty::subst::Kind<'tcx>` represents some entity in the type system: a type 3 | (`Ty<'tcx>`), lifetime (`ty::Region<'tcx>`) or constant (`ty::Const<'tcx>`). 4 | `Kind` is used to perform substitutions of generic parameters for concrete 5 | arguments, such as when calling a function with generic parameters explicitly 6 | with type arguments. Substitutions are represented using the 7 | [`Subst` type](#subst) as described below. 8 | 9 | ## `Subst` 10 | `ty::subst::Subst<'tcx>` is intuitively simply a slice of `Kind<'tcx>`s, 11 | acting as an ordered list of substitutions from generic parameters to 12 | concrete arguments (such as types, lifetimes and consts). 13 | 14 | For example, given a `HashMap` with two type parameters, `K` and `V`, an 15 | instantiation of the parameters, for example `HashMap`, would be 16 | represented by the substitution `&'tcx [tcx.types.i32, tcx.types.u32]`. 17 | 18 | `Subst` provides various convenience methods to instantiant substitutions 19 | given item definitions, which should generally be used rather than explicitly 20 | constructing such substitution slices. 21 | 22 | ## `Kind` 23 | The actual `Kind` struct is optimised for space, storing the type, lifetime or 24 | const as an interned pointer containing a tag identifying its kind (in the 25 | lowest 2 bits). Unless you are working with the `Subst` implementation 26 | specifically, you should generally not have to deal with `Kind` and instead 27 | make use of the safe [`UnpackedKind`](#unpackedkind) abstraction. 28 | 29 | ## `UnpackedKind` 30 | As `Kind` itself is not type-safe, the `UnpackedKind` enum provides a more 31 | convenient and safe interface for dealing with kinds. An `UnpackedKind` can 32 | be converted to a raw `Kind` using `Kind::from()` (or simply `.into()` when 33 | the context is clear). As mentioned earlier, substition lists store raw 34 | `Kind`s, so before dealing with them, it is preferable to convert them to 35 | `UnpackedKind`s first. This is done by calling the `.unpack()` method. 36 | 37 | ```rust,ignore 38 | // An example of unpacking and packing a kind. 39 | fn deal_with_kind<'tcx>(kind: Kind<'tcx>) -> Kind<'tcx> { 40 | // Unpack a raw `Kind` to deal with it safely. 41 | let new_kind: UnpackedKind<'tcx> = match kind.unpack() { 42 | UnpackedKind::Type(ty) => { /* ... */ } 43 | UnpackedKind::Lifetime(lt) => { /* ... */ } 44 | UnpackedKind::Const(ct) => { /* ... */ } 45 | }; 46 | // Pack the `UnpackedKind` to store it in a substitution list. 47 | new_kind.into() 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /src-zh/kinds.md: -------------------------------------------------------------------------------- 1 | # Kinds 2 | A `ty::subst::Kind<'tcx>` represents some entity in the type system: a type 3 | (`Ty<'tcx>`), lifetime (`ty::Region<'tcx>`) or constant (`ty::Const<'tcx>`). 4 | `Kind` is used to perform substitutions of generic parameters for concrete 5 | arguments, such as when calling a function with generic parameters explicitly 6 | with type arguments. Substitutions are represented using the 7 | [`Subst` type](#subst) as described below. 8 | 9 | ## `Subst` 10 | `ty::subst::Subst<'tcx>` is intuitively simply a slice of `Kind<'tcx>`s, 11 | acting as an ordered list of substitutions from generic parameters to 12 | concrete arguments (such as types, lifetimes and consts). 13 | 14 | For example, given a `HashMap` with two type parameters, `K` and `V`, an 15 | instantiation of the parameters, for example `HashMap`, would be 16 | represented by the substitution `&'tcx [tcx.types.i32, tcx.types.u32]`. 17 | 18 | `Subst` provides various convenience methods to instantiant substitutions 19 | given item definitions, which should generally be used rather than explicitly 20 | constructing such substitution slices. 21 | 22 | ## `Kind` 23 | The actual `Kind` struct is optimised for space, storing the type, lifetime or 24 | const as an interned pointer containing a tag identifying its kind (in the 25 | lowest 2 bits). Unless you are working with the `Subst` implementation 26 | specifically, you should generally not have to deal with `Kind` and instead 27 | make use of the safe [`UnpackedKind`](#unpackedkind) abstraction. 28 | 29 | ## `UnpackedKind` 30 | As `Kind` itself is not type-safe, the `UnpackedKind` enum provides a more 31 | convenient and safe interface for dealing with kinds. An `UnpackedKind` can 32 | be converted to a raw `Kind` using `Kind::from()` (or simply `.into()` when 33 | the context is clear). As mentioned earlier, substition lists store raw 34 | `Kind`s, so before dealing with them, it is preferable to convert them to 35 | `UnpackedKind`s first. This is done by calling the `.unpack()` method. 36 | 37 | ```rust,ignore 38 | // An example of unpacking and packing a kind. 39 | fn deal_with_kind<'tcx>(kind: Kind<'tcx>) -> Kind<'tcx> { 40 | // Unpack a raw `Kind` to deal with it safely. 41 | let new_kind: UnpackedKind<'tcx> = match kind.unpack() { 42 | UnpackedKind::Type(ty) => { /* ... */ } 43 | UnpackedKind::Lifetime(lt) => { /* ... */ } 44 | UnpackedKind::Const(ct) => { /* ... */ } 45 | }; 46 | // Pack the `UnpackedKind` to store it in a substitution list. 47 | new_kind.into() 48 | } 49 | ``` 50 | -------------------------------------------------------------------------------- /src-zh/codegen.md: -------------------------------------------------------------------------------- 1 | # Code generation 2 | 3 | Code generation or "codegen" is the part of the compiler that actually 4 | generates an executable binary. rustc uses LLVM for code generation. 5 | 6 | > NOTE: If you are looking for hints on how to debug code generation bugs, 7 | > please see [this section of the debugging chapter][debugging]. 8 | 9 | [debugging]: codegen/debugging.html 10 | 11 | ## What is LLVM? 12 | 13 | All of the preceding chapters of this guide have one thing in common: we never 14 | generated any executable machine code at all! With this chapter, all of that 15 | changes. 16 | 17 | Like most compilers, rustc is composed of a "frontend" and a "backend". The 18 | "frontend" is responsible for taking raw source code, checking it for 19 | correctness, and getting it into a format `X` from which we can generate 20 | executable machine code. The "backend" then takes that format `X` and produces 21 | (possibly optimized) executable machine code for some platform. All of the 22 | previous chapters deal with rustc's frontend. 23 | 24 | rustc's backend is [LLVM](https://llvm.org), "a collection of modular and 25 | reusable compiler and toolchain technologies". In particular, the LLVM project 26 | contains a pluggable compiler backend (also called "LLVM"), which is used by 27 | many compiler projects, including the `clang` C compiler and our beloved 28 | `rustc`. 29 | 30 | LLVM's "format `X`" is called LLVM IR. It is basically assembly code with 31 | additional low-level types and annotations added. These annotations are helpful 32 | for doing optimizations on the LLVM IR and outputted machine code. The end 33 | result of all this is (at long last) something executable (e.g. an ELF object 34 | or wasm). 35 | 36 | There are a few benefits to using LLVM: 37 | 38 | - We don't have to write a whole compiler backend. This reduces implementation 39 | and maintenance burden. 40 | - We benefit from the large suite of advanced optimizations that the LLVM 41 | project has been collecting. 42 | - We automatically can compile Rust to any of the platforms for which LLVM has 43 | support. For example, as soon as LLVM added support for wasm, voila! rustc, 44 | clang, and a bunch of other languages were able to compile to wasm! (Well, 45 | there was some extra stuff to be done, but we were 90% there anyway). 46 | - We and other compiler projects benefit from each other. For example, when the 47 | [Spectre and Meltdown security vulnerabilities][spectre] were discovered, 48 | only LLVM needed to be patched. 49 | 50 | [spectre]: https://meltdownattack.com/ 51 | 52 | ## Generating LLVM IR 53 | 54 | TODO 55 | -------------------------------------------------------------------------------- /src/codegen.md: -------------------------------------------------------------------------------- 1 | # Code generation 2 | 3 | Code generation or "codegen" is the part of the compiler that actually 4 | generates an executable binary. rustc uses LLVM for code generation. 5 | 6 | > NOTE: If you are looking for hints on how to debug code generation bugs, 7 | > please see [this section of the debugging chapter][debugging]. 8 | 9 | [debugging]: codegen/debugging.html 10 | 11 | ## What is LLVM? 12 | 13 | All of the preceding chapters of this guide have one thing in common: we never 14 | generated any executable machine code at all! With this chapter, all of that 15 | changes. 16 | 17 | Like most compilers, rustc is composed of a "frontend" and a "backend". The 18 | "frontend" is responsible for taking raw source code, checking it for 19 | correctness, and getting it into a format `X` from which we can generate 20 | executable machine code. The "backend" then takes that format `X` and produces 21 | (possibly optimized) executable machine code for some platform. All of the 22 | previous chapters deal with rustc's frontend. 23 | 24 | rustc's backend is [LLVM](https://llvm.org), "a collection of modular and 25 | reusable compiler and toolchain technologies". In particular, the LLVM project 26 | contains a pluggable compiler backend (also called "LLVM"), which is used by 27 | many compiler projects, including the `clang` C compiler and our beloved 28 | `rustc`. 29 | 30 | LLVM's "format `X`" is called LLVM IR. It is basically assembly code with 31 | additional low-level types and annotations added. These annotations are helpful 32 | for doing optimizations on the LLVM IR and outputted machine code. The end 33 | result of all this is (at long last) something executable (e.g. an ELF object 34 | or wasm). 35 | 36 | There are a few benefits to using LLVM: 37 | 38 | - We don't have to write a whole compiler backend. This reduces implementation 39 | and maintenance burden. 40 | - We benefit from the large suite of advanced optimizations that the LLVM 41 | project has been collecting. 42 | - We automatically can compile Rust to any of the platforms for which LLVM has 43 | support. For example, as soon as LLVM added support for wasm, voila! rustc, 44 | clang, and a bunch of other languages were able to compile to wasm! (Well, 45 | there was some extra stuff to be done, but we were 90% there anyway). 46 | - We and other compiler projects benefit from each other. For example, when the 47 | [Spectre and Meltdown security vulnerabilities][spectre] were discovered, 48 | only LLVM needed to be patched. 49 | 50 | [spectre]: https://meltdownattack.com/ 51 | 52 | ## Generating LLVM IR 53 | 54 | TODO 55 | -------------------------------------------------------------------------------- /src-zh/the-parser.md: -------------------------------------------------------------------------------- 1 | # The Parser 2 | 3 | The parser is responsible for converting raw Rust source code into a structured 4 | form which is easier for the compiler to work with, usually called an [*Abstract 5 | Syntax Tree*][ast]. An AST mirrors the structure of a Rust program in memory, 6 | using a `Span` to link a particular AST node back to its source text. 7 | 8 | The bulk of the parser lives in the [libsyntax] crate. 9 | 10 | Like most parsers, the parsing process is composed of two main steps, 11 | 12 | - lexical analysis – turn a stream of characters into a stream of token trees 13 | - parsing – turn the token trees into an AST 14 | 15 | The `syntax` crate contains several main players, 16 | 17 | - a [`SourceMap`] for mapping AST nodes to their source code 18 | - the [ast module] contains types corresponding to each AST node 19 | - a [`StringReader`] for lexing source code into tokens 20 | - the [parser module] and [`Parser`] struct are in charge of actually parsing 21 | tokens into AST nodes, 22 | - and a [visit module] for walking the AST and inspecting or mutating the AST 23 | nodes. 24 | 25 | The main entrypoint to the parser is via the various `parse_*` functions in the 26 | [parser module]. They let you do things like turn a [`SourceFile`][sourcefile] 27 | (e.g. the source in a single file) into a token stream, create a parser from 28 | the token stream, and then execute the parser to get a `Crate` (the root AST 29 | node). 30 | 31 | To minimise the amount of copying that is done, both the `StringReader` and 32 | `Parser` have lifetimes which bind them to the parent `ParseSess`. This contains 33 | all the information needed while parsing, as well as the `SourceMap` itself. 34 | 35 | [libsyntax]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/index.html 36 | [rustc_errors]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html 37 | [ast]: https://en.wikipedia.org/wiki/Abstract_syntax_tree 38 | [`SourceMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceMap.html 39 | [ast module]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast/index.html 40 | [parser module]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/index.html 41 | [`Parser`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/parser/struct.Parser.html 42 | [`StringReader`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/lexer/struct.StringReader.html 43 | [visit module]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/visit/index.html 44 | [sourcefile]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceFile.html 45 | -------------------------------------------------------------------------------- /src/the-parser.md: -------------------------------------------------------------------------------- 1 | # The Parser 2 | 3 | The parser is responsible for converting raw Rust source code into a structured 4 | form which is easier for the compiler to work with, usually called an [*Abstract 5 | Syntax Tree*][ast]. An AST mirrors the structure of a Rust program in memory, 6 | using a `Span` to link a particular AST node back to its source text. 7 | 8 | The bulk of the parser lives in the [libsyntax] crate. 9 | 10 | Like most parsers, the parsing process is composed of two main steps, 11 | 12 | - lexical analysis – turn a stream of characters into a stream of token trees 13 | - parsing – turn the token trees into an AST 14 | 15 | The `syntax` crate contains several main players, 16 | 17 | - a [`SourceMap`] for mapping AST nodes to their source code 18 | - the [ast module] contains types corresponding to each AST node 19 | - a [`StringReader`] for lexing source code into tokens 20 | - the [parser module] and [`Parser`] struct are in charge of actually parsing 21 | tokens into AST nodes, 22 | - and a [visit module] for walking the AST and inspecting or mutating the AST 23 | nodes. 24 | 25 | The main entrypoint to the parser is via the various `parse_*` functions in the 26 | [parser module]. They let you do things like turn a [`SourceFile`][sourcefile] 27 | (e.g. the source in a single file) into a token stream, create a parser from 28 | the token stream, and then execute the parser to get a `Crate` (the root AST 29 | node). 30 | 31 | To minimise the amount of copying that is done, both the `StringReader` and 32 | `Parser` have lifetimes which bind them to the parent `ParseSess`. This contains 33 | all the information needed while parsing, as well as the `SourceMap` itself. 34 | 35 | [libsyntax]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/index.html 36 | [rustc_errors]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html 37 | [ast]: https://en.wikipedia.org/wiki/Abstract_syntax_tree 38 | [`SourceMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceMap.html 39 | [ast module]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/ast/index.html 40 | [parser module]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/index.html 41 | [`Parser`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/parser/struct.Parser.html 42 | [`StringReader`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/parse/lexer/struct.StringReader.html 43 | [visit module]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/visit/index.html 44 | [sourcefile]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceFile.html 45 | -------------------------------------------------------------------------------- /src/lowering.md: -------------------------------------------------------------------------------- 1 | # Lowering 2 | 3 | The 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 `src/librustc/hir/map/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 | -------------------------------------------------------------------------------- /src-zh/lowering.md: -------------------------------------------------------------------------------- 1 | # Lowering 2 | 3 | The 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 `src/librustc/hir/map/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 | -------------------------------------------------------------------------------- /src-zh/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 trans 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/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 trans 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-zh/traits/lowering-module.md: -------------------------------------------------------------------------------- 1 | # The lowering module in rustc 2 | 3 | The program clauses described in the 4 | [lowering rules](./lowering-rules.html) section are actually 5 | created in the [`rustc_traits::lowering`][lowering] module. 6 | 7 | [lowering]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_traits/lowering/ 8 | 9 | ## The `program_clauses_for` query 10 | 11 | The main entry point is the `program_clauses_for` [query], which – 12 | given a def-id – produces a set of Chalk program clauses. These 13 | queries are tested using a 14 | [dedicated unit-testing mechanism, described below](#unit-tests). The 15 | query is invoked on a `DefId` that identifies something like a trait, 16 | an impl, or an associated item definition. It then produces and 17 | returns a vector of program clauses. 18 | 19 | [query]: ../query.html 20 | 21 | 22 | 23 | ## Unit tests 24 | 25 | Unit tests are located in [`src/test/ui/chalkify`][chalkify]. A good 26 | example test is [the `lower_impl` test][lower_impl]. At the time of 27 | this writing, it looked like this: 28 | 29 | ```rust,ignore 30 | #![feature(rustc_attrs)] 31 | 32 | trait Foo { } 33 | 34 | #[rustc_dump_program_clauses] //~ ERROR program clause dump 35 | impl Foo for T where T: Iterator { } 36 | 37 | fn main() { 38 | println!("hello"); 39 | } 40 | ``` 41 | 42 | The `#[rustc_dump_program_clauses]` annotation can be attached to 43 | anything with a def-id. (It requires the `rustc_attrs` feature.) The 44 | compiler will then invoke the `program_clauses_for` query on that 45 | item, and emit compiler errors that dump the clauses produced. These 46 | errors just exist for unit-testing, as we can then leverage the 47 | standard [ui test] mechanisms to check them. In this case, there is a 48 | `//~ ERROR program clause dump` annotation which is always the same for 49 | `#[rustc_dump_program_clauses]`, but [the stderr file] contains 50 | the full details: 51 | 52 | ```text 53 | error: program clause dump 54 | --> $DIR/lower_impl.rs:5:1 55 | | 56 | LL | #[rustc_dump_program_clauses] 57 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 58 | | 59 | = note: forall { Implemented(T: Foo) :- ProjectionEq(::Item == i32), TypeOutlives(T: 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). } 60 | ``` 61 | 62 | [chalkify]: https://github.com/rust-lang/rust/tree/master/src/test/ui/chalkify 63 | [lower_impl]: https://github.com/rust-lang/rust/tree/master/src/test/ui/chalkify/lower_impl.rs 64 | [the stderr file]: https://github.com/rust-lang/rust/tree/master/src/test/ui/chalkify/lower_impl.stderr 65 | [ui test]: ../tests/adding.html#guide-to-the-ui-tests 66 | -------------------------------------------------------------------------------- /src/traits/lowering-module.md: -------------------------------------------------------------------------------- 1 | # The lowering module in rustc 2 | 3 | The program clauses described in the 4 | [lowering rules](./lowering-rules.html) section are actually 5 | created in the [`rustc_traits::lowering`][lowering] module. 6 | 7 | [lowering]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_traits/lowering/ 8 | 9 | ## The `program_clauses_for` query 10 | 11 | The main entry point is the `program_clauses_for` [query], which – 12 | given a def-id – produces a set of Chalk program clauses. These 13 | queries are tested using a 14 | [dedicated unit-testing mechanism, described below](#unit-tests). The 15 | query is invoked on a `DefId` that identifies something like a trait, 16 | an impl, or an associated item definition. It then produces and 17 | returns a vector of program clauses. 18 | 19 | [query]: ../query.html 20 | 21 | 22 | 23 | ## Unit tests 24 | 25 | Unit tests are located in [`src/test/ui/chalkify`][chalkify]. A good 26 | example test is [the `lower_impl` test][lower_impl]. At the time of 27 | this writing, it looked like this: 28 | 29 | ```rust,ignore 30 | #![feature(rustc_attrs)] 31 | 32 | trait Foo { } 33 | 34 | #[rustc_dump_program_clauses] //~ ERROR program clause dump 35 | impl Foo for T where T: Iterator { } 36 | 37 | fn main() { 38 | println!("hello"); 39 | } 40 | ``` 41 | 42 | The `#[rustc_dump_program_clauses]` annotation can be attached to 43 | anything with a def-id. (It requires the `rustc_attrs` feature.) The 44 | compiler will then invoke the `program_clauses_for` query on that 45 | item, and emit compiler errors that dump the clauses produced. These 46 | errors just exist for unit-testing, as we can then leverage the 47 | standard [ui test] mechanisms to check them. In this case, there is a 48 | `//~ ERROR program clause dump` annotation which is always the same for 49 | `#[rustc_dump_program_clauses]`, but [the stderr file] contains 50 | the full details: 51 | 52 | ```text 53 | error: program clause dump 54 | --> $DIR/lower_impl.rs:5:1 55 | | 56 | LL | #[rustc_dump_program_clauses] 57 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 58 | | 59 | = note: forall { Implemented(T: Foo) :- ProjectionEq(::Item == i32), TypeOutlives(T: 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). } 60 | ``` 61 | 62 | [chalkify]: https://github.com/rust-lang/rust/tree/master/src/test/ui/chalkify 63 | [lower_impl]: https://github.com/rust-lang/rust/tree/master/src/test/ui/chalkify/lower_impl.rs 64 | [the stderr file]: https://github.com/rust-lang/rust/tree/master/src/test/ui/chalkify/lower_impl.stderr 65 | [ui test]: ../tests/adding.html#guide-to-the-ui-tests 66 | -------------------------------------------------------------------------------- /src/mir/debugging.md: -------------------------------------------------------------------------------- 1 | # MIR Debugging 2 | 3 | The `-Zdump-mir` flag can be used to dump a text representation of the MIR. The 4 | `-Zdump-mir-graphviz` flag can be used to dump a `.dot` file that represents 5 | MIR as a control-flow graph. 6 | 7 | `-Zdump-mir=F` is a handy compiler options that will let you view the MIR for 8 | each function at each stage of compilation. `-Zdump-mir` takes a **filter** `F` 9 | which allows you to control which functions and which passes you are 10 | interesting in. For example: 11 | 12 | ```bash 13 | > rustc -Zdump-mir=foo ... 14 | ``` 15 | 16 | This will dump the MIR for any function whose name contains `foo`; it 17 | will dump the MIR both before and after every pass. Those files will 18 | be created in the `mir_dump` directory. There will likely be quite a 19 | lot of them! 20 | 21 | ```bash 22 | > cat > foo.rs 23 | fn main() { 24 | println!("Hello, world!"); 25 | } 26 | ^D 27 | > rustc -Zdump-mir=main foo.rs 28 | > ls mir_dump/* | wc -l 29 | 161 30 | ``` 31 | 32 | The files have names like `rustc.main.000-000.CleanEndRegions.after.mir`. These 33 | names have a number of parts: 34 | 35 | ```text 36 | rustc.main.000-000.CleanEndRegions.after.mir 37 | ---- --- --- --------------- ----- either before or after 38 | | | | name of the pass 39 | | | index of dump within the pass (usually 0, but some passes dump intermediate states) 40 | | index of the pass 41 | def-path to the function etc being dumped 42 | ``` 43 | 44 | You can also make more selective filters. For example, `main & CleanEndRegions` 45 | will select for things that reference *both* `main` and the pass 46 | `CleanEndRegions`: 47 | 48 | ```bash 49 | > rustc -Zdump-mir='main & CleanEndRegions' foo.rs 50 | > ls mir_dump 51 | rustc.main.000-000.CleanEndRegions.after.mir rustc.main.000-000.CleanEndRegions.before.mir 52 | ``` 53 | 54 | Filters can also have `|` parts to combine multiple sets of 55 | `&`-filters. For example `main & CleanEndRegions | main & 56 | NoLandingPads` will select *either* `main` and `CleanEndRegions` *or* 57 | `main` and `NoLandingPads`: 58 | 59 | ```bash 60 | > rustc -Zdump-mir='main & CleanEndRegions | main & NoLandingPads' foo.rs 61 | > ls mir_dump 62 | rustc.main-promoted[0].002-000.NoLandingPads.after.mir 63 | rustc.main-promoted[0].002-000.NoLandingPads.before.mir 64 | rustc.main-promoted[0].002-006.NoLandingPads.after.mir 65 | rustc.main-promoted[0].002-006.NoLandingPads.before.mir 66 | rustc.main-promoted[1].002-000.NoLandingPads.after.mir 67 | rustc.main-promoted[1].002-000.NoLandingPads.before.mir 68 | rustc.main-promoted[1].002-006.NoLandingPads.after.mir 69 | rustc.main-promoted[1].002-006.NoLandingPads.before.mir 70 | rustc.main.000-000.CleanEndRegions.after.mir 71 | rustc.main.000-000.CleanEndRegions.before.mir 72 | rustc.main.002-000.NoLandingPads.after.mir 73 | rustc.main.002-000.NoLandingPads.before.mir 74 | rustc.main.002-006.NoLandingPads.after.mir 75 | rustc.main.002-006.NoLandingPads.before.mir 76 | ``` 77 | 78 | (Here, the `main-promoted[0]` files refer to the MIR for "promoted constants" 79 | that appeared within the `main` function.) 80 | 81 | TODO: anything else? 82 | -------------------------------------------------------------------------------- /src-zh/mir/debugging.md: -------------------------------------------------------------------------------- 1 | # MIR Debugging 2 | 3 | The `-Zdump-mir` flag can be used to dump a text representation of the MIR. The 4 | `-Zdump-mir-graphviz` flag can be used to dump a `.dot` file that represents 5 | MIR as a control-flow graph. 6 | 7 | `-Zdump-mir=F` is a handy compiler options that will let you view the MIR for 8 | each function at each stage of compilation. `-Zdump-mir` takes a **filter** `F` 9 | which allows you to control which functions and which passes you are 10 | interesting in. For example: 11 | 12 | ```bash 13 | > rustc -Zdump-mir=foo ... 14 | ``` 15 | 16 | This will dump the MIR for any function whose name contains `foo`; it 17 | will dump the MIR both before and after every pass. Those files will 18 | be created in the `mir_dump` directory. There will likely be quite a 19 | lot of them! 20 | 21 | ```bash 22 | > cat > foo.rs 23 | fn main() { 24 | println!("Hello, world!"); 25 | } 26 | ^D 27 | > rustc -Zdump-mir=main foo.rs 28 | > ls mir_dump/* | wc -l 29 | 161 30 | ``` 31 | 32 | The files have names like `rustc.main.000-000.CleanEndRegions.after.mir`. These 33 | names have a number of parts: 34 | 35 | ```text 36 | rustc.main.000-000.CleanEndRegions.after.mir 37 | ---- --- --- --------------- ----- either before or after 38 | | | | name of the pass 39 | | | index of dump within the pass (usually 0, but some passes dump intermediate states) 40 | | index of the pass 41 | def-path to the function etc being dumped 42 | ``` 43 | 44 | You can also make more selective filters. For example, `main & CleanEndRegions` 45 | will select for things that reference *both* `main` and the pass 46 | `CleanEndRegions`: 47 | 48 | ```bash 49 | > rustc -Zdump-mir='main & CleanEndRegions' foo.rs 50 | > ls mir_dump 51 | rustc.main.000-000.CleanEndRegions.after.mir rustc.main.000-000.CleanEndRegions.before.mir 52 | ``` 53 | 54 | Filters can also have `|` parts to combine multiple sets of 55 | `&`-filters. For example `main & CleanEndRegions | main & 56 | NoLandingPads` will select *either* `main` and `CleanEndRegions` *or* 57 | `main` and `NoLandingPads`: 58 | 59 | ```bash 60 | > rustc -Zdump-mir='main & CleanEndRegions | main & NoLandingPads' foo.rs 61 | > ls mir_dump 62 | rustc.main-promoted[0].002-000.NoLandingPads.after.mir 63 | rustc.main-promoted[0].002-000.NoLandingPads.before.mir 64 | rustc.main-promoted[0].002-006.NoLandingPads.after.mir 65 | rustc.main-promoted[0].002-006.NoLandingPads.before.mir 66 | rustc.main-promoted[1].002-000.NoLandingPads.after.mir 67 | rustc.main-promoted[1].002-000.NoLandingPads.before.mir 68 | rustc.main-promoted[1].002-006.NoLandingPads.after.mir 69 | rustc.main-promoted[1].002-006.NoLandingPads.before.mir 70 | rustc.main.000-000.CleanEndRegions.after.mir 71 | rustc.main.000-000.CleanEndRegions.before.mir 72 | rustc.main.002-000.NoLandingPads.after.mir 73 | rustc.main.002-000.NoLandingPads.before.mir 74 | rustc.main.002-006.NoLandingPads.after.mir 75 | rustc.main.002-006.NoLandingPads.before.mir 76 | ``` 77 | 78 | (Here, the `main-promoted[0]` files refer to the MIR for "promoted constants" 79 | that appeared within the `main` function.) 80 | 81 | TODO: anything else? 82 | -------------------------------------------------------------------------------- /src/traits/index.md: -------------------------------------------------------------------------------- 1 | # Trait solving (new-style) 2 | 3 | > 🚧 This chapter describes "new-style" trait solving. This is still in the 4 | > [process of being implemented][wg]; this chapter serves as a kind of 5 | > in-progress design document. If you would prefer to read about how the 6 | > current trait solver works, check out 7 | > [this other chapter](./resolution.html). 🚧 8 | > 9 | > By the way, if you would like to help in hacking on the new solver, you will 10 | > find instructions for getting involved in the 11 | > [Traits Working Group tracking issue][wg]! 12 | 13 | [wg]: https://github.com/rust-lang/rust/issues/48416 14 | 15 | The new-style trait solver is based on the work done in [chalk][chalk]. Chalk 16 | recasts Rust's trait system explicitly in terms of logic programming. It does 17 | this by "lowering" Rust code into a kind of logic program we can then execute 18 | queries against. 19 | 20 | You can read more about chalk itself in the 21 | [Overview of Chalk](./chalk-overview.md) section. 22 | 23 | Trait solving in rustc is based around a few key ideas: 24 | 25 | - [Lowering to logic](./lowering-to-logic.html), which expresses 26 | Rust traits in terms of standard logical terms. 27 | - The [goals and clauses](./goals-and-clauses.html) chapter 28 | describes the precise form of rules we use, and 29 | [lowering rules](./lowering-rules.html) gives the complete set of 30 | lowering rules in a more reference-like form. 31 | - [Lazy normalization](./associated-types.html), which is the 32 | technique we use to accommodate associated types when figuring out 33 | whether types are equal. 34 | - [Region constraints](./regions.html), which are accumulated 35 | during trait solving but mostly ignored. This means that trait 36 | solving effectively ignores the precise regions involved, always – 37 | but we still remember the constraints on them so that those 38 | constraints can be checked by the type checker. 39 | - [Canonical queries](./canonical-queries.html), which allow us 40 | to solve trait problems (like "is `Foo` implemented for the type 41 | `Bar`?") once, and then apply that same result independently in many 42 | different inference contexts. 43 | 44 | > This is not a complete list of topics. See the sidebar for more. 45 | 46 | ## Ongoing work 47 | The design of the new-style trait solving currently happens in two places: 48 | 49 | **chalk**. The [chalk][chalk] repository is where we experiment with new ideas 50 | and designs for the trait system. It primarily consists of two parts: 51 | * a unit testing framework 52 | for the correctness and feasibility of the logical rules defining the 53 | new-style trait system. 54 | * the [`chalk_engine`][chalk_engine] crate, which 55 | defines the new-style trait solver used both in the unit testing framework 56 | and in rustc. 57 | 58 | **rustc**. Once we are happy with the logical rules, we proceed to 59 | implementing them in rustc. This mainly happens in 60 | [`librustc_traits`][librustc_traits]. 61 | 62 | [chalk]: https://github.com/rust-lang-nursery/chalk 63 | [chalk_engine]: https://github.com/rust-lang-nursery/chalk/tree/master/chalk-engine 64 | [librustc_traits]: https://github.com/rust-lang/rust/tree/master/src/librustc_traits 65 | -------------------------------------------------------------------------------- /src-zh/traits/index.md: -------------------------------------------------------------------------------- 1 | # Trait solving (new-style) 2 | 3 | > 🚧 This chapter describes "new-style" trait solving. This is still in the 4 | > [process of being implemented][wg]; this chapter serves as a kind of 5 | > in-progress design document. If you would prefer to read about how the 6 | > current trait solver works, check out 7 | > [this other chapter](./resolution.html). 🚧 8 | > 9 | > By the way, if you would like to help in hacking on the new solver, you will 10 | > find instructions for getting involved in the 11 | > [Traits Working Group tracking issue][wg]! 12 | 13 | [wg]: https://github.com/rust-lang/rust/issues/48416 14 | 15 | The new-style trait solver is based on the work done in [chalk][chalk]. Chalk 16 | recasts Rust's trait system explicitly in terms of logic programming. It does 17 | this by "lowering" Rust code into a kind of logic program we can then execute 18 | queries against. 19 | 20 | You can read more about chalk itself in the 21 | [Overview of Chalk](./chalk-overview.md) section. 22 | 23 | Trait solving in rustc is based around a few key ideas: 24 | 25 | - [Lowering to logic](./lowering-to-logic.html), which expresses 26 | Rust traits in terms of standard logical terms. 27 | - The [goals and clauses](./goals-and-clauses.html) chapter 28 | describes the precise form of rules we use, and 29 | [lowering rules](./lowering-rules.html) gives the complete set of 30 | lowering rules in a more reference-like form. 31 | - [Lazy normalization](./associated-types.html), which is the 32 | technique we use to accommodate associated types when figuring out 33 | whether types are equal. 34 | - [Region constraints](./regions.html), which are accumulated 35 | during trait solving but mostly ignored. This means that trait 36 | solving effectively ignores the precise regions involved, always – 37 | but we still remember the constraints on them so that those 38 | constraints can be checked by the type checker. 39 | - [Canonical queries](./canonical-queries.html), which allow us 40 | to solve trait problems (like "is `Foo` implemented for the type 41 | `Bar`?") once, and then apply that same result independently in many 42 | different inference contexts. 43 | 44 | > This is not a complete list of topics. See the sidebar for more. 45 | 46 | ## Ongoing work 47 | The design of the new-style trait solving currently happens in two places: 48 | 49 | **chalk**. The [chalk][chalk] repository is where we experiment with new ideas 50 | and designs for the trait system. It primarily consists of two parts: 51 | * a unit testing framework 52 | for the correctness and feasibility of the logical rules defining the 53 | new-style trait system. 54 | * the [`chalk_engine`][chalk_engine] crate, which 55 | defines the new-style trait solver used both in the unit testing framework 56 | and in rustc. 57 | 58 | **rustc**. Once we are happy with the logical rules, we proceed to 59 | implementing them in rustc. This mainly happens in 60 | [`librustc_traits`][librustc_traits]. 61 | 62 | [chalk]: https://github.com/rust-lang-nursery/chalk 63 | [chalk_engine]: https://github.com/rust-lang-nursery/chalk/tree/master/chalk-engine 64 | [librustc_traits]: https://github.com/rust-lang/rust/tree/master/src/librustc_traits 65 | -------------------------------------------------------------------------------- /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 serious 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.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-zh/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 serious 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.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/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 shared borrowed. 12 | - etc 13 | 14 | At the time of this writing, the code is in a state of transition. The 15 | "main" borrow checker still works by processing [the HIR](hir.html), 16 | but that is being phased out in favor of the MIR-based borrow checker. 17 | Accordingly, this documentation focuses on the new, MIR-based borrow 18 | checker. 19 | 20 | Doing borrow checking on MIR has several advantages: 21 | 22 | - The MIR is *far* less complex than the HIR; the radical desugaring 23 | helps prevent bugs in the borrow checker. (If you're curious, you 24 | can see 25 | [a list of bugs that the MIR-based borrow checker fixes here][47366].) 26 | - Even more importantly, using the MIR enables ["non-lexical lifetimes"][nll], 27 | which are regions derived from the control-flow graph. 28 | 29 | [47366]: https://github.com/rust-lang/rust/issues/47366 30 | [nll]: http://rust-lang.github.io/rfcs/2094-nll.html 31 | 32 | ### Major phases of the borrow checker 33 | 34 | The borrow checker source is found in 35 | [the `rustc_mir::borrow_check` module][b_c]. The main entry point is 36 | the [`mir_borrowck`] query. 37 | 38 | [b_c]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/index.html 39 | [`mir_borrowck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/fn.mir_borrowck.html 40 | 41 | - We first create a **local copy** of the MIR. In the coming steps, 42 | we will modify this copy in place to modify the types and things to 43 | include references to the new regions that we are computing. 44 | - We then invoke [`replace_regions_in_mir`] to modify our local MIR. 45 | Among other things, this function will replace all of the [regions](./appendix/glossary.html) in 46 | the MIR with fresh [inference variables](./appendix/glossary.html). 47 | - Next, we perform a number of 48 | [dataflow analyses](./appendix/background.html#dataflow) that 49 | compute what data is moved and when. 50 | - We then do a [second type check](borrow_check/type_check.html) across the MIR: 51 | the purpose of this type check is to determine all of the constraints between 52 | different regions. 53 | - Next, we do [region inference](borrow_check/region_inference.html), which computes 54 | the values of each region — basically, the points in the control-flow graph where 55 | each lifetime must be valid according to the constraints we collected. 56 | - At this point, we can compute the "borrows in scope" at each point. 57 | - Finally, we do a second walk over the MIR, looking at the actions it 58 | does and reporting errors. For example, if we see a statement like 59 | `*a + 1`, then we would check that the variable `a` is initialized 60 | and that it is not mutably borrowed, as either of those would 61 | require an error to be reported. Doing this check requires the results of all 62 | the previous analyses. 63 | 64 | [`replace_regions_in_mir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/fn.replace_regions_in_mir.html 65 | -------------------------------------------------------------------------------- /src-zh/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 shared borrowed. 12 | - etc 13 | 14 | At the time of this writing, the code is in a state of transition. The 15 | "main" borrow checker still works by processing [the HIR](hir.html), 16 | but that is being phased out in favor of the MIR-based borrow checker. 17 | Accordingly, this documentation focuses on the new, MIR-based borrow 18 | checker. 19 | 20 | Doing borrow checking on MIR has several advantages: 21 | 22 | - The MIR is *far* less complex than the HIR; the radical desugaring 23 | helps prevent bugs in the borrow checker. (If you're curious, you 24 | can see 25 | [a list of bugs that the MIR-based borrow checker fixes here][47366].) 26 | - Even more importantly, using the MIR enables ["non-lexical lifetimes"][nll], 27 | which are regions derived from the control-flow graph. 28 | 29 | [47366]: https://github.com/rust-lang/rust/issues/47366 30 | [nll]: http://rust-lang.github.io/rfcs/2094-nll.html 31 | 32 | ### Major phases of the borrow checker 33 | 34 | The borrow checker source is found in 35 | [the `rustc_mir::borrow_check` module][b_c]. The main entry point is 36 | the [`mir_borrowck`] query. 37 | 38 | [b_c]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/index.html 39 | [`mir_borrowck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/fn.mir_borrowck.html 40 | 41 | - We first create a **local copy** of the MIR. In the coming steps, 42 | we will modify this copy in place to modify the types and things to 43 | include references to the new regions that we are computing. 44 | - We then invoke [`replace_regions_in_mir`] to modify our local MIR. 45 | Among other things, this function will replace all of the [regions](./appendix/glossary.html) in 46 | the MIR with fresh [inference variables](./appendix/glossary.html). 47 | - Next, we perform a number of 48 | [dataflow analyses](./appendix/background.html#dataflow) that 49 | compute what data is moved and when. 50 | - We then do a [second type check](borrow_check/type_check.html) across the MIR: 51 | the purpose of this type check is to determine all of the constraints between 52 | different regions. 53 | - Next, we do [region inference](borrow_check/region_inference.html), which computes 54 | the values of each region — basically, the points in the control-flow graph where 55 | each lifetime must be valid according to the constraints we collected. 56 | - At this point, we can compute the "borrows in scope" at each point. 57 | - Finally, we do a second walk over the MIR, looking at the actions it 58 | does and reporting errors. For example, if we see a statement like 59 | `*a + 1`, then we would check that the variable `a` is initialized 60 | and that it is not mutably borrowed, as either of those would 61 | require an error to be reported. Doing this check requires the results of all 62 | the previous analyses. 63 | 64 | [`replace_regions_in_mir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/nll/fn.replace_regions_in_mir.html 65 | -------------------------------------------------------------------------------- /src/rustc-driver.md: -------------------------------------------------------------------------------- 1 | # The Rustc Driver and 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 | analysing a crate or emulating the compiler in-process (e.g. the RLS or rustdoc). 11 | 12 | For those using `rustc` as a library, the `interface::run_compiler()` function is the main 13 | entrypoint to the compiler. It takes a configuration for the compiler and a closure that 14 | takes a [`Compiler`]. `run_compiler` creates a `Compiler` from the configuration and passes 15 | it to the closure. Inside the closure, you can use the `Compiler` to drive queries to compile 16 | a crate and get the results. This is what the `rustc_driver` does too. 17 | 18 | You can see what queries are currently available through the rustdocs for [`Compiler`]. 19 | You can see an example of how to use them by looking at the `rustc_driver` implementation, 20 | specifically the [`rustc_driver::run_compiler` function][rd_rc] (not to be confused with 21 | `interface::run_compiler`). The `rustc_driver::run_compiler` function takes a bunch of 22 | command-line args and some other configurations and drives the compilation to completion. 23 | 24 | `rustc_driver::run_compiler` also takes a [`Callbacks`][cb]. In the past, when 25 | the `rustc_driver::run_compiler` was the primary way to use the compiler as a 26 | library, these callbacks were used to have some custom code run after different 27 | phases of the compilation. If you read [Appendix A], you may notice the use of the 28 | types `CompilerCalls` and `CompileController`, which no longer exist. `Callbacks` 29 | replaces this functionality. 30 | 31 | > **Warning:** By its very nature, the internal compiler APIs are always going 32 | > to be unstable. That said, we do try not to break things unnecessarily. 33 | 34 | ## A Note On Lifetimes 35 | 36 | The Rust compiler is a fairly large program containing lots of big data 37 | structures (e.g. the AST, HIR, and the type system) and as such, arenas and 38 | references are heavily relied upon to minimize unnecessary memory use. This 39 | manifests itself in the way people can plug into the compiler, preferring a 40 | "push"-style API (callbacks) instead of the more Rust-ic "pull" style (think 41 | the `Iterator` trait). 42 | 43 | Thread-local storage and interning are used a lot through the compiler to reduce 44 | duplication while also preventing a lot of the ergonomic issues due to many 45 | pervasive lifetimes. The `rustc::ty::tls` module is used to access these 46 | thread-locals, although you should rarely need to touch it. 47 | 48 | [cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html 49 | [rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html 50 | [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html 51 | [`rustc_driver`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/ 52 | [`Compiler`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Compiler.html 53 | [`Session`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/session/struct.Session.html 54 | [`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.TyCtxt.html 55 | [`SourceMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceMap.html 56 | [stupid-stats]: https://github.com/nrc/stupid-stats 57 | [Appendix A]: appendix/stupid-stats.html 58 | -------------------------------------------------------------------------------- /src-zh/rustc-driver.md: -------------------------------------------------------------------------------- 1 | # The Rustc Driver and 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 | analysing a crate or emulating the compiler in-process (e.g. the RLS or rustdoc). 11 | 12 | For those using `rustc` as a library, the `interface::run_compiler()` function is the main 13 | entrypoint to the compiler. It takes a configuration for the compiler and a closure that 14 | takes a [`Compiler`]. `run_compiler` creates a `Compiler` from the configuration and passes 15 | it to the closure. Inside the closure, you can use the `Compiler` to drive queries to compile 16 | a crate and get the results. This is what the `rustc_driver` does too. 17 | 18 | You can see what queries are currently available through the rustdocs for [`Compiler`]. 19 | You can see an example of how to use them by looking at the `rustc_driver` implementation, 20 | specifically the [`rustc_driver::run_compiler` function][rd_rc] (not to be confused with 21 | `interface::run_compiler`). The `rustc_driver::run_compiler` function takes a bunch of 22 | command-line args and some other configurations and drives the compilation to completion. 23 | 24 | `rustc_driver::run_compiler` also takes a [`Callbacks`][cb]. In the past, when 25 | the `rustc_driver::run_compiler` was the primary way to use the compiler as a 26 | library, these callbacks were used to have some custom code run after different 27 | phases of the compilation. If you read [Appendix A], you may notice the use of the 28 | types `CompilerCalls` and `CompileController`, which no longer exist. `Callbacks` 29 | replaces this functionality. 30 | 31 | > **Warning:** By its very nature, the internal compiler APIs are always going 32 | > to be unstable. That said, we do try not to break things unnecessarily. 33 | 34 | ## A Note On Lifetimes 35 | 36 | The Rust compiler is a fairly large program containing lots of big data 37 | structures (e.g. the AST, HIR, and the type system) and as such, arenas and 38 | references are heavily relied upon to minimize unnecessary memory use. This 39 | manifests itself in the way people can plug into the compiler, preferring a 40 | "push"-style API (callbacks) instead of the more Rust-ic "pull" style (think 41 | the `Iterator` trait). 42 | 43 | Thread-local storage and interning are used a lot through the compiler to reduce 44 | duplication while also preventing a lot of the ergonomic issues due to many 45 | pervasive lifetimes. The `rustc::ty::tls` module is used to access these 46 | thread-locals, although you should rarely need to touch it. 47 | 48 | [cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html 49 | [rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html 50 | [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html 51 | [`rustc_driver`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/ 52 | [`Compiler`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Compiler.html 53 | [`Session`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/session/struct.Session.html 54 | [`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/struct.TyCtxt.html 55 | [`SourceMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/syntax/source_map/struct.SourceMap.html 56 | [stupid-stats]: https://github.com/nrc/stupid-stats 57 | [Appendix A]: appendix/stupid-stats.html 58 | -------------------------------------------------------------------------------- /src/appendix/background.md: -------------------------------------------------------------------------------- 1 | # Appendix B: Background topics 2 | 3 | This section covers a numbers of common compiler terms that arise in 4 | this guide. We try to give the general definition while providing some 5 | Rust-specific context. 6 | 7 | 8 | 9 | ## What is a control-flow graph? 10 | 11 | A control-flow graph is a common term from compilers. If you've ever 12 | used a flow-chart, then the concept of a control-flow graph will be 13 | pretty familiar to you. It's a representation of your program that 14 | exposes the underlying control flow in a very clear way. 15 | 16 | A control-flow graph is structured as a set of **basic blocks** 17 | connected by edges. The key idea of a basic block is that it is a set 18 | of statements that execute "together" – that is, whenever you branch 19 | to a basic block, you start at the first statement and then execute 20 | all the remainder. Only at the end of the block is there the 21 | possibility of branching to more than one place (in MIR, we call that 22 | final statement the **terminator**): 23 | 24 | ```mir 25 | bb0: { 26 | statement0; 27 | statement1; 28 | statement2; 29 | ... 30 | terminator; 31 | } 32 | ``` 33 | 34 | Many expressions that you are used to in Rust compile down to multiple 35 | basic blocks. For example, consider an if statement: 36 | 37 | ```rust,ignore 38 | a = 1; 39 | if some_variable { 40 | b = 1; 41 | } else { 42 | c = 1; 43 | } 44 | d = 1; 45 | ``` 46 | 47 | This would compile into four basic blocks: 48 | 49 | ```mir 50 | BB0: { 51 | a = 1; 52 | if some_variable { goto BB1 } else { goto BB2 } 53 | } 54 | 55 | BB1: { 56 | b = 1; 57 | goto BB3; 58 | } 59 | 60 | BB2: { 61 | c = 1; 62 | goto BB3; 63 | } 64 | 65 | BB3: { 66 | d = 1; 67 | ...; 68 | } 69 | ``` 70 | 71 | When using a control-flow graph, a loop simply appears as a cycle in 72 | the graph, and the `break` keyword translates into a path out of that 73 | cycle. 74 | 75 | 76 | 77 | ## What is a dataflow analysis? 78 | 79 | [*Static Program Analysis*](https://cs.au.dk/~amoeller/spa/) by Anders Møller 80 | and Michael I. Schwartzbach is an incredible resource! 81 | 82 | *to be written* 83 | 84 | 85 | 86 | ## What is "universally quantified"? What about "existentially quantified"? 87 | 88 | *to be written* 89 | 90 | 91 | 92 | ## What is co- and contra-variance? 93 | 94 | Check out the subtyping chapter from the 95 | [Rust Nomicon](https://doc.rust-lang.org/nomicon/subtyping.html). 96 | 97 | See the [variance](../variance.html) chapter of this guide for more info on how 98 | the type checker handles variance. 99 | 100 | 101 | 102 | ## What is a "free region" or a "free variable"? What about "bound region"? 103 | 104 | Let's describe the concepts of free vs bound in terms of program 105 | variables, since that's the thing we're most familiar with. 106 | 107 | - Consider this expression, which creates a closure: `|a, 108 | b| a + b`. Here, the `a` and `b` in `a + b` refer to the arguments 109 | that the closure will be given when it is called. We say that the 110 | `a` and `b` there are **bound** to the closure, and that the closure 111 | signature `|a, b|` is a **binder** for the names `a` and `b` 112 | (because any references to `a` or `b` within refer to the variables 113 | that it introduces). 114 | - Consider this expression: `a + b`. In this expression, `a` and `b` 115 | refer to local variables that are defined *outside* of the 116 | expression. We say that those variables **appear free** in the 117 | expression (i.e., they are **free**, not **bound** (tied up)). 118 | 119 | So there you have it: a variable "appears free" in some 120 | expression/statement/whatever if it refers to something defined 121 | outside of that expressions/statement/whatever. Equivalently, we can 122 | then refer to the "free variables" of an expression – which is just 123 | the set of variables that "appear free". 124 | 125 | So what does this have to do with regions? Well, we can apply the 126 | analogous concept to type and regions. For example, in the type `&'a 127 | u32`, `'a` appears free. But in the type `for<'a> fn(&'a u32)`, it 128 | does not. 129 | -------------------------------------------------------------------------------- /src-zh/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 | ```rust 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/ty/adjustment/enum.AutoBorrow.html 77 | [converted]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/hair/cx/expr/trait.ToBorrowKind.html#method.to_borrow_kind 78 | [`BorrowKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/enum.BorrowKind.html 79 | [`GatherBorrows`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/visit/trait.Visitor.html#method.visit_local 80 | [`BorrowData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/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_mir/borrow_check/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_mir/borrow_check/path_utils/fn.is_active.html 101 | -------------------------------------------------------------------------------- /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/ty/adjustment/enum.AutoBorrow.html 77 | [converted]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/hair/cx/expr/trait.ToBorrowKind.html#method.to_borrow_kind 78 | [`BorrowKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/enum.BorrowKind.html 79 | [`GatherBorrows`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/mir/visit/trait.Visitor.html#method.visit_local 80 | [`BorrowData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/borrow_check/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_mir/borrow_check/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_mir/borrow_check/path_utils/fn.is_active.html 101 | -------------------------------------------------------------------------------- /src/incrcomp-debugging.md: -------------------------------------------------------------------------------- 1 | # Debugging and Testing Dependencies 2 | 3 | ## Testing the dependency graph 4 | 5 | There are various ways to write tests against the dependency graph. 6 | The simplest mechanisms are the `#[rustc_if_this_changed]` and 7 | `#[rustc_then_this_would_need]` annotations. These are used in compile-fail 8 | tests to test whether the expected set of paths exist in the dependency graph. 9 | As an example, see `src/test/compile-fail/dep-graph-caller-callee.rs`. 10 | 11 | The idea is that you can annotate a test like: 12 | 13 | ```rust,ignore 14 | #[rustc_if_this_changed] 15 | fn foo() { } 16 | 17 | #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK 18 | fn bar() { foo(); } 19 | 20 | #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path 21 | fn baz() { } 22 | ``` 23 | 24 | This will check whether there is a path in the dependency graph from `Hir(foo)` 25 | to `TypeckTables(bar)`. An error is reported for each 26 | `#[rustc_then_this_would_need]` annotation that indicates whether a path 27 | exists. `//~ ERROR` annotations can then be used to test if a path is found (as 28 | demonstrated above). 29 | 30 | ## Debugging the dependency graph 31 | 32 | ### Dumping the graph 33 | 34 | The compiler is also capable of dumping the dependency graph for your 35 | debugging pleasure. To do so, pass the `-Z dump-dep-graph` flag. The 36 | graph will be dumped to `dep_graph.{txt,dot}` in the current 37 | directory. You can override the filename with the `RUST_DEP_GRAPH` 38 | environment variable. 39 | 40 | Frequently, though, the full dep graph is quite overwhelming and not 41 | particularly helpful. Therefore, the compiler also allows you to filter 42 | the graph. You can filter in three ways: 43 | 44 | 1. All edges originating in a particular set of nodes (usually a single node). 45 | 2. All edges reaching a particular set of nodes. 46 | 3. All edges that lie between given start and end nodes. 47 | 48 | To filter, use the `RUST_DEP_GRAPH_FILTER` environment variable, which should 49 | look like one of the following: 50 | 51 | ```text 52 | source_filter // nodes originating from source_filter 53 | -> target_filter // nodes that can reach target_filter 54 | source_filter -> target_filter // nodes in between source_filter and target_filter 55 | ``` 56 | 57 | `source_filter` and `target_filter` are a `&`-separated list of strings. 58 | A node is considered to match a filter if all of those strings appear in its 59 | label. So, for example: 60 | 61 | ```text 62 | RUST_DEP_GRAPH_FILTER='-> TypeckTables' 63 | ``` 64 | 65 | would select the predecessors of all `TypeckTables` nodes. Usually though you 66 | want the `TypeckTables` node for some particular fn, so you might write: 67 | 68 | ```text 69 | RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar' 70 | ``` 71 | 72 | This will select only the predecessors of `TypeckTables` nodes for functions 73 | with `bar` in their name. 74 | 75 | Perhaps you are finding that when you change `foo` you need to re-type-check 76 | `bar`, but you don't think you should have to. In that case, you might do: 77 | 78 | ```text 79 | RUST_DEP_GRAPH_FILTER='Hir & foo -> TypeckTables & bar' 80 | ``` 81 | 82 | This will dump out all the nodes that lead from `Hir(foo)` to 83 | `TypeckTables(bar)`, from which you can (hopefully) see the source 84 | of the erroneous edge. 85 | 86 | ### Tracking down incorrect edges 87 | 88 | Sometimes, after you dump the dependency graph, you will find some 89 | path that should not exist, but you will not be quite sure how it came 90 | to be. **When the compiler is built with debug assertions,** it can 91 | help you track that down. Simply set the `RUST_FORBID_DEP_GRAPH_EDGE` 92 | environment variable to a filter. Every edge created in the dep-graph 93 | will be tested against that filter – if it matches, a `bug!` is 94 | reported, so you can easily see the backtrace (`RUST_BACKTRACE=1`). 95 | 96 | The syntax for these filters is the same as described in the previous 97 | section. However, note that this filter is applied to every **edge** 98 | and doesn't handle longer paths in the graph, unlike the previous 99 | section. 100 | 101 | Example: 102 | 103 | You find that there is a path from the `Hir` of `foo` to the type 104 | check of `bar` and you don't think there should be. You dump the 105 | dep-graph as described in the previous section and open `dep-graph.txt` 106 | to see something like: 107 | 108 | ```text 109 | Hir(foo) -> Collect(bar) 110 | Collect(bar) -> TypeckTables(bar) 111 | ``` 112 | 113 | That first edge looks suspicious to you. So you set 114 | `RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and 115 | then observe the backtrace. Voila, bug fixed! 116 | -------------------------------------------------------------------------------- /src-zh/incrcomp-debugging.md: -------------------------------------------------------------------------------- 1 | # Debugging and Testing Dependencies 2 | 3 | ## Testing the dependency graph 4 | 5 | There are various ways to write tests against the dependency graph. 6 | The simplest mechanisms are the `#[rustc_if_this_changed]` and 7 | `#[rustc_then_this_would_need]` annotations. These are used in compile-fail 8 | tests to test whether the expected set of paths exist in the dependency graph. 9 | As an example, see `src/test/compile-fail/dep-graph-caller-callee.rs`. 10 | 11 | The idea is that you can annotate a test like: 12 | 13 | ```rust,ignore 14 | #[rustc_if_this_changed] 15 | fn foo() { } 16 | 17 | #[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK 18 | fn bar() { foo(); } 19 | 20 | #[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path 21 | fn baz() { } 22 | ``` 23 | 24 | This will check whether there is a path in the dependency graph from `Hir(foo)` 25 | to `TypeckTables(bar)`. An error is reported for each 26 | `#[rustc_then_this_would_need]` annotation that indicates whether a path 27 | exists. `//~ ERROR` annotations can then be used to test if a path is found (as 28 | demonstrated above). 29 | 30 | ## Debugging the dependency graph 31 | 32 | ### Dumping the graph 33 | 34 | The compiler is also capable of dumping the dependency graph for your 35 | debugging pleasure. To do so, pass the `-Z dump-dep-graph` flag. The 36 | graph will be dumped to `dep_graph.{txt,dot}` in the current 37 | directory. You can override the filename with the `RUST_DEP_GRAPH` 38 | environment variable. 39 | 40 | Frequently, though, the full dep graph is quite overwhelming and not 41 | particularly helpful. Therefore, the compiler also allows you to filter 42 | the graph. You can filter in three ways: 43 | 44 | 1. All edges originating in a particular set of nodes (usually a single node). 45 | 2. All edges reaching a particular set of nodes. 46 | 3. All edges that lie between given start and end nodes. 47 | 48 | To filter, use the `RUST_DEP_GRAPH_FILTER` environment variable, which should 49 | look like one of the following: 50 | 51 | ```text 52 | source_filter // nodes originating from source_filter 53 | -> target_filter // nodes that can reach target_filter 54 | source_filter -> target_filter // nodes in between source_filter and target_filter 55 | ``` 56 | 57 | `source_filter` and `target_filter` are a `&`-separated list of strings. 58 | A node is considered to match a filter if all of those strings appear in its 59 | label. So, for example: 60 | 61 | ```text 62 | RUST_DEP_GRAPH_FILTER='-> TypeckTables' 63 | ``` 64 | 65 | would select the predecessors of all `TypeckTables` nodes. Usually though you 66 | want the `TypeckTables` node for some particular fn, so you might write: 67 | 68 | ```text 69 | RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar' 70 | ``` 71 | 72 | This will select only the predecessors of `TypeckTables` nodes for functions 73 | with `bar` in their name. 74 | 75 | Perhaps you are finding that when you change `foo` you need to re-type-check 76 | `bar`, but you don't think you should have to. In that case, you might do: 77 | 78 | ```text 79 | RUST_DEP_GRAPH_FILTER='Hir & foo -> TypeckTables & bar' 80 | ``` 81 | 82 | This will dump out all the nodes that lead from `Hir(foo)` to 83 | `TypeckTables(bar)`, from which you can (hopefully) see the source 84 | of the erroneous edge. 85 | 86 | ### Tracking down incorrect edges 87 | 88 | Sometimes, after you dump the dependency graph, you will find some 89 | path that should not exist, but you will not be quite sure how it came 90 | to be. **When the compiler is built with debug assertions,** it can 91 | help you track that down. Simply set the `RUST_FORBID_DEP_GRAPH_EDGE` 92 | environment variable to a filter. Every edge created in the dep-graph 93 | will be tested against that filter – if it matches, a `bug!` is 94 | reported, so you can easily see the backtrace (`RUST_BACKTRACE=1`). 95 | 96 | The syntax for these filters is the same as described in the previous 97 | section. However, note that this filter is applied to every **edge** 98 | and doesn't handle longer paths in the graph, unlike the previous 99 | section. 100 | 101 | Example: 102 | 103 | You find that there is a path from the `Hir` of `foo` to the type 104 | check of `bar` and you don't think there should be. You dump the 105 | dep-graph as described in the previous section and open `dep-graph.txt` 106 | to see something like: 107 | 108 | ```text 109 | Hir(foo) -> Collect(bar) 110 | Collect(bar) -> TypeckTables(bar) 111 | ``` 112 | 113 | That first edge looks suspicious to you. So you set 114 | `RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and 115 | then observe the backtrace. Voila, bug fixed! 116 | -------------------------------------------------------------------------------- /src-zh/mir/passes.md: -------------------------------------------------------------------------------- 1 | # MIR passes 2 | 3 | If you would like to get the MIR for a function (or constant, etc), 4 | you can use the `optimized_mir(def_id)` query. This will give you back 5 | the final, optimized MIR. For foreign def-ids, we simply read the MIR 6 | from the other crate's metadata. But for local def-ids, the query will 7 | construct the MIR and then iteratively optimize it by applying a 8 | series of passes. This section describes how those passes work and how 9 | you can extend them. 10 | 11 | To produce the `optimized_mir(D)` for a given def-id `D`, the MIR 12 | passes through several suites of optimizations, each represented by a 13 | query. Each suite consists of multiple optimizations and 14 | transformations. These suites represent useful intermediate points 15 | where we want to access the MIR for type checking or other purposes: 16 | 17 | - `mir_build(D)` – not a query, but this constructs the initial MIR 18 | - `mir_const(D)` – applies some simple transformations to make MIR ready for 19 | constant evaluation; 20 | - `mir_validated(D)` – applies some more transformations, making MIR ready for 21 | borrow checking; 22 | - `optimized_mir(D)` – the final state, after all optimizations have been 23 | performed. 24 | 25 | ### Implementing and registering a pass 26 | 27 | A `MirPass` is some bit of code that processes the MIR, typically – 28 | but not always – transforming it along the way somehow. For example, 29 | it might perform an optimization. The `MirPass` trait itself is found 30 | in in [the `rustc_mir::transform` module][mirtransform], and it 31 | basically consists of one method, `run_pass`, that simply gets an 32 | `&mut Mir` (along with the tcx and some information about where it 33 | came from). The MIR is therefore modified in place (which helps to 34 | keep things efficient). 35 | 36 | A good example of a basic MIR pass is [`NoLandingPads`], which walks 37 | the MIR and removes all edges that are due to unwinding – this is 38 | used when configured with `panic=abort`, which never unwinds. As you 39 | can see from its source, a MIR pass is defined by first defining a 40 | dummy type, a struct with no fields, something like: 41 | 42 | ```rust 43 | struct MyPass; 44 | ``` 45 | 46 | for which you then implement the `MirPass` trait. You can then insert 47 | this pass into the appropriate list of passes found in a query like 48 | `optimized_mir`, `mir_validated`, etc. (If this is an optimization, it 49 | should go into the `optimized_mir` list.) 50 | 51 | If you are writing a pass, there's a good chance that you are going to 52 | want to use a [MIR visitor]. MIR visitors are a handy way to walk all 53 | the parts of the MIR, either to search for something or to make small 54 | edits. 55 | 56 | ### Stealing 57 | 58 | The intermediate queries `mir_const()` and `mir_validated()` yield up 59 | a `&'tcx Steal>`, allocated using 60 | `tcx.alloc_steal_mir()`. This indicates that the result may be 61 | **stolen** by the next suite of optimizations – this is an 62 | optimization to avoid cloning the MIR. Attempting to use a stolen 63 | result will cause a panic in the compiler. Therefore, it is important 64 | that you do not read directly from these intermediate queries except as 65 | part of the MIR processing pipeline. 66 | 67 | Because of this stealing mechanism, some care must also be taken to 68 | ensure that, before the MIR at a particular phase in the processing 69 | pipeline is stolen, anyone who may want to read from it has already 70 | done so. Concretely, this means that if you have some query `foo(D)` 71 | that wants to access the result of `mir_const(D)` or 72 | `mir_validated(D)`, you need to have the successor pass "force" 73 | `foo(D)` using `ty::queries::foo::force(...)`. This will force a query 74 | to execute even though you don't directly require its result. 75 | 76 | As an example, consider MIR const qualification. It wants to read the 77 | result produced by the `mir_const()` suite. However, that result will 78 | be **stolen** by the `mir_validated()` suite. If nothing was done, 79 | then `mir_const_qualif(D)` would succeed if it came before 80 | `mir_validated(D)`, but fail otherwise. Therefore, `mir_validated(D)` 81 | will **force** `mir_const_qualif` before it actually steals, thus 82 | ensuring that the reads have already happened (remember that 83 | [queries are memoized](../query.html), so executing a query twice 84 | simply loads from a cache the second time): 85 | 86 | ```text 87 | mir_const(D) --read-by--> mir_const_qualif(D) 88 | | ^ 89 | stolen-by | 90 | | (forces) 91 | v | 92 | mir_validated(D) ------------+ 93 | ``` 94 | 95 | This mechanism is a bit dodgy. There is a discussion of more elegant 96 | alternatives in [rust-lang/rust#41710]. 97 | 98 | [rust-lang/rust#41710]: https://github.com/rust-lang/rust/issues/41710 99 | [mirtransform]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/ 100 | [`NoLandingPads`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/no_landing_pads/struct.NoLandingPads.html 101 | [MIR visitor]: ./visitor.html 102 | -------------------------------------------------------------------------------- /src/mir/passes.md: -------------------------------------------------------------------------------- 1 | # MIR passes 2 | 3 | If you would like to get the MIR for a function (or constant, etc), 4 | you can use the `optimized_mir(def_id)` query. This will give you back 5 | the final, optimized MIR. For foreign def-ids, we simply read the MIR 6 | from the other crate's metadata. But for local def-ids, the query will 7 | construct the MIR and then iteratively optimize it by applying a 8 | series of passes. This section describes how those passes work and how 9 | you can extend them. 10 | 11 | To produce the `optimized_mir(D)` for a given def-id `D`, the MIR 12 | passes through several suites of optimizations, each represented by a 13 | query. Each suite consists of multiple optimizations and 14 | transformations. These suites represent useful intermediate points 15 | where we want to access the MIR for type checking or other purposes: 16 | 17 | - `mir_build(D)` – not a query, but this constructs the initial MIR 18 | - `mir_const(D)` – applies some simple transformations to make MIR ready for 19 | constant evaluation; 20 | - `mir_validated(D)` – applies some more transformations, making MIR ready for 21 | borrow checking; 22 | - `optimized_mir(D)` – the final state, after all optimizations have been 23 | performed. 24 | 25 | ### Implementing and registering a pass 26 | 27 | A `MirPass` is some bit of code that processes the MIR, typically – 28 | but not always – transforming it along the way somehow. For example, 29 | it might perform an optimization. The `MirPass` trait itself is found 30 | in in [the `rustc_mir::transform` module][mirtransform], and it 31 | basically consists of one method, `run_pass`, that simply gets an 32 | `&mut Mir` (along with the tcx and some information about where it 33 | came from). The MIR is therefore modified in place (which helps to 34 | keep things efficient). 35 | 36 | A good example of a basic MIR pass is [`NoLandingPads`], which walks 37 | the MIR and removes all edges that are due to unwinding – this is 38 | used when configured with `panic=abort`, which never unwinds. As you 39 | can see from its source, a MIR pass is defined by first defining a 40 | dummy type, a struct with no fields, something like: 41 | 42 | ```rust 43 | struct MyPass; 44 | ``` 45 | 46 | for which you then implement the `MirPass` trait. You can then insert 47 | this pass into the appropriate list of passes found in a query like 48 | `optimized_mir`, `mir_validated`, etc. (If this is an optimization, it 49 | should go into the `optimized_mir` list.) 50 | 51 | If you are writing a pass, there's a good chance that you are going to 52 | want to use a [MIR visitor]. MIR visitors are a handy way to walk all 53 | the parts of the MIR, either to search for something or to make small 54 | edits. 55 | 56 | ### Stealing 57 | 58 | The intermediate queries `mir_const()` and `mir_validated()` yield up 59 | a `&'tcx Steal>`, allocated using 60 | `tcx.alloc_steal_mir()`. This indicates that the result may be 61 | **stolen** by the next suite of optimizations – this is an 62 | optimization to avoid cloning the MIR. Attempting to use a stolen 63 | result will cause a panic in the compiler. Therefore, it is important 64 | that you do not read directly from these intermediate queries except as 65 | part of the MIR processing pipeline. 66 | 67 | Because of this stealing mechanism, some care must also be taken to 68 | ensure that, before the MIR at a particular phase in the processing 69 | pipeline is stolen, anyone who may want to read from it has already 70 | done so. Concretely, this means that if you have some query `foo(D)` 71 | that wants to access the result of `mir_const(D)` or 72 | `mir_validated(D)`, you need to have the successor pass "force" 73 | `foo(D)` using `ty::queries::foo::force(...)`. This will force a query 74 | to execute even though you don't directly require its result. 75 | 76 | As an example, consider MIR const qualification. It wants to read the 77 | result produced by the `mir_const()` suite. However, that result will 78 | be **stolen** by the `mir_validated()` suite. If nothing was done, 79 | then `mir_const_qualif(D)` would succeed if it came before 80 | `mir_validated(D)`, but fail otherwise. Therefore, `mir_validated(D)` 81 | will **force** `mir_const_qualif` before it actually steals, thus 82 | ensuring that the reads have already happened (remember that 83 | [queries are memoized](../query.html), so executing a query twice 84 | simply loads from a cache the second time): 85 | 86 | ```text 87 | mir_const(D) --read-by--> mir_const_qualif(D) 88 | | ^ 89 | stolen-by | 90 | | (forces) 91 | v | 92 | mir_validated(D) ------------+ 93 | ``` 94 | 95 | This mechanism is a bit dodgy. There is a discussion of more elegant 96 | alternatives in [rust-lang/rust#41710]. 97 | 98 | [rust-lang/rust#41710]: https://github.com/rust-lang/rust/issues/41710 99 | [mirtransform]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/ 100 | [`NoLandingPads`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/no_landing_pads/struct.NoLandingPads.html 101 | [MIR visitor]: ./visitor.html 102 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # The Rust Code of Conduct 2 | 3 | A version of this document [can be found online](https://www.rust-lang.org/conduct.html). 4 | 5 | ## Conduct 6 | 7 | **Contact**: [rust-mods@rust-lang.org](mailto:rust-mods@rust-lang.org) 8 | 9 | * We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic. 10 | * On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all. 11 | * Please be kind and courteous. There's no need to be mean or rude. 12 | * Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer. 13 | * Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works. 14 | * We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behaviour. We interpret the term "harassment" as including the definition in the Citizen Code of Conduct; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups. 15 | * Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team](/team.html#Moderation) immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back. 16 | * Likewise any spamming, trolling, flaming, baiting or other attention-stealing behaviour is not welcome. 17 | 18 | ## Moderation 19 | 20 | 21 | These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team](/team.html#Moderation). 22 | 23 | 1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.) 24 | 2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed. 25 | 3. Moderators will first respond to such remarks with a warning. 26 | 4. If the warning is unheeded, the user will be "kicked," i.e. kicked out of the communication channel to cool off. 27 | 5. If the user comes back and continues to make trouble, they will be banned, i.e. indefinitely excluded. 28 | 6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology. 29 | 7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, **in private**. Complaints about bans in-channel are not allowed. 30 | 8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others. 31 | 32 | In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely. 33 | 34 | And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could've communicated better — remember that it's your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust. 35 | 36 | The enforcement policies listed above apply to all official Rust venues; including official IRC channels (#rust, #rust-internals, #rust-tools, #rust-libs, #rustc, #rust-beginners, #rust-docs, #rust-community, #rust-lang, and #cargo); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion. 37 | 38 | *Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](http://contributor-covenant.org/version/1/3/0/).* 39 | -------------------------------------------------------------------------------- /src-zh/traits/hrtb.md: -------------------------------------------------------------------------------- 1 | # Higher-ranked trait bounds 2 | 3 | One of the more subtle concepts in trait resolution is *higher-ranked trait 4 | bounds*. An example of such a bound is `for<'a> MyTrait<&'a isize>`. 5 | Let's walk through how selection on higher-ranked trait references 6 | works. 7 | 8 | ## Basic matching and placeholder leaks 9 | 10 | Suppose we have a trait `Foo`: 11 | 12 | ```rust 13 | trait Foo { 14 | fn foo(&self, x: X) { } 15 | } 16 | ``` 17 | 18 | Let's say we have a function `want_hrtb` that wants a type which 19 | implements `Foo<&'a isize>` for any `'a`: 20 | 21 | ```rust,ignore 22 | fn want_hrtb() where T : for<'a> Foo<&'a isize> { ... } 23 | ``` 24 | 25 | Now we have a struct `AnyInt` that implements `Foo<&'a isize>` for any 26 | `'a`: 27 | 28 | ```rust,ignore 29 | struct AnyInt; 30 | impl<'a> Foo<&'a isize> for AnyInt { } 31 | ``` 32 | 33 | And the question is, does `AnyInt : for<'a> Foo<&'a isize>`? We want the 34 | answer to be yes. The algorithm for figuring it out is closely related 35 | to the subtyping for higher-ranked types (which is described [here][hrsubtype] 36 | and also in a [paper by SPJ]. If you wish to understand higher-ranked 37 | subtyping, we recommend you read the paper). There are a few parts: 38 | 39 | 1. Replace bound regions in the obligation with placeholders. 40 | 2. Match the impl against the [placeholder] obligation. 41 | 3. Check for _placeholder leaks_. 42 | 43 | [placeholder]: ../appendix/glossary.html#appendix-c-glossary 44 | [hrsubtype]: https://github.com/rust-lang/rust/tree/master/src/librustc/infer/higher_ranked/README.md 45 | [paper by SPJ]: http://research.microsoft.com/en-us/um/people/simonpj/papers/higher-rank/ 46 | 47 | So let's work through our example. 48 | 49 | 1. The first thing we would do is to 50 | replace the bound region in the obligation with a placeholder, yielding 51 | `AnyInt : Foo<&'0 isize>` (here `'0` represents placeholder region #0). 52 | Note that we now have no quantifiers; 53 | in terms of the compiler type, this changes from a `ty::PolyTraitRef` 54 | to a `TraitRef`. We would then create the `TraitRef` from the impl, 55 | using fresh variables for it's bound regions (and thus getting 56 | `Foo<&'$a isize>`, where `'$a` is the inference variable for `'a`). 57 | 58 | 2. Next 59 | we relate the two trait refs, yielding a graph with the constraint 60 | that `'0 == '$a`. 61 | 62 | 3. Finally, we check for placeholder "leaks" – a 63 | leak is basically any attempt to relate a placeholder region to another 64 | placeholder region, or to any region that pre-existed the impl match. 65 | The leak check is done by searching from the placeholder region to find 66 | the set of regions that it is related to in any way. This is called 67 | the "taint" set. To pass the check, that set must consist *solely* of 68 | itself and region variables from the impl. If the taint set includes 69 | any other region, then the match is a failure. In this case, the taint 70 | set for `'0` is `{'0, '$a}`, and hence the check will succeed. 71 | 72 | Let's consider a failure case. Imagine we also have a struct 73 | 74 | ```rust,ignore 75 | struct StaticInt; 76 | impl Foo<&'static isize> for StaticInt; 77 | ``` 78 | 79 | We want the obligation `StaticInt : for<'a> Foo<&'a isize>` to be 80 | considered unsatisfied. The check begins just as before. `'a` is 81 | replaced with a placeholder `'0` and the impl trait reference is instantiated to 82 | `Foo<&'static isize>`. When we relate those two, we get a constraint 83 | like `'static == '0`. This means that the taint set for `'0` is `{'0, 84 | 'static}`, which fails the leak check. 85 | 86 | **TODO**: This is because `'static` is not a region variable but is in the 87 | taint set, right? 88 | 89 | ## Higher-ranked trait obligations 90 | 91 | Once the basic matching is done, we get to another interesting topic: 92 | how to deal with impl obligations. I'll work through a simple example 93 | here. Imagine we have the traits `Foo` and `Bar` and an associated impl: 94 | 95 | ```rust 96 | trait Foo { 97 | fn foo(&self, x: X) { } 98 | } 99 | 100 | trait Bar { 101 | fn bar(&self, x: X) { } 102 | } 103 | 104 | impl Foo for F 105 | where F : Bar 106 | { 107 | } 108 | ``` 109 | 110 | Now let's say we have a obligation `Baz: for<'a> Foo<&'a isize>` and we match 111 | this impl. What obligation is generated as a result? We want to get 112 | `Baz: for<'a> Bar<&'a isize>`, but how does that happen? 113 | 114 | After the matching, we are in a position where we have a placeholder 115 | substitution like `X => &'0 isize`. If we apply this substitution to the 116 | impl obligations, we get `F : Bar<&'0 isize>`. Obviously this is not 117 | directly usable because the placeholder region `'0` cannot leak out of 118 | our computation. 119 | 120 | What we do is to create an inverse mapping from the taint set of `'0` 121 | back to the original bound region (`'a`, here) that `'0` resulted 122 | from. (This is done in `higher_ranked::plug_leaks`). We know that the 123 | leak check passed, so this taint set consists solely of the placeholder 124 | region itself plus various intermediate region variables. We then walk 125 | the trait-reference and convert every region in that taint set back to 126 | a late-bound region, so in this case we'd wind up with 127 | `Baz: for<'a> Bar<&'a isize>`. 128 | -------------------------------------------------------------------------------- /src/traits/hrtb.md: -------------------------------------------------------------------------------- 1 | # Higher-ranked trait bounds 2 | 3 | One of the more subtle concepts in trait resolution is *higher-ranked trait 4 | bounds*. An example of such a bound is `for<'a> MyTrait<&'a isize>`. 5 | Let's walk through how selection on higher-ranked trait references 6 | works. 7 | 8 | ## Basic matching and placeholder leaks 9 | 10 | Suppose we have a trait `Foo`: 11 | 12 | ```rust 13 | trait Foo { 14 | fn foo(&self, x: X) { } 15 | } 16 | ``` 17 | 18 | Let's say we have a function `want_hrtb` that wants a type which 19 | implements `Foo<&'a isize>` for any `'a`: 20 | 21 | ```rust,ignore 22 | fn want_hrtb() where T : for<'a> Foo<&'a isize> { ... } 23 | ``` 24 | 25 | Now we have a struct `AnyInt` that implements `Foo<&'a isize>` for any 26 | `'a`: 27 | 28 | ```rust,ignore 29 | struct AnyInt; 30 | impl<'a> Foo<&'a isize> for AnyInt { } 31 | ``` 32 | 33 | And the question is, does `AnyInt : for<'a> Foo<&'a isize>`? We want the 34 | answer to be yes. The algorithm for figuring it out is closely related 35 | to the subtyping for higher-ranked types (which is described [here][hrsubtype] 36 | and also in a [paper by SPJ]. If you wish to understand higher-ranked 37 | subtyping, we recommend you read the paper). There are a few parts: 38 | 39 | 1. Replace bound regions in the obligation with placeholders. 40 | 2. Match the impl against the [placeholder] obligation. 41 | 3. Check for _placeholder leaks_. 42 | 43 | [placeholder]: ../appendix/glossary.html#appendix-c-glossary 44 | [hrsubtype]: https://github.com/rust-lang/rust/tree/master/src/librustc/infer/higher_ranked/README.md 45 | [paper by SPJ]: http://research.microsoft.com/en-us/um/people/simonpj/papers/higher-rank/ 46 | 47 | So let's work through our example. 48 | 49 | 1. The first thing we would do is to 50 | replace the bound region in the obligation with a placeholder, yielding 51 | `AnyInt : Foo<&'0 isize>` (here `'0` represents placeholder region #0). 52 | Note that we now have no quantifiers; 53 | in terms of the compiler type, this changes from a `ty::PolyTraitRef` 54 | to a `TraitRef`. We would then create the `TraitRef` from the impl, 55 | using fresh variables for it's bound regions (and thus getting 56 | `Foo<&'$a isize>`, where `'$a` is the inference variable for `'a`). 57 | 58 | 2. Next 59 | we relate the two trait refs, yielding a graph with the constraint 60 | that `'0 == '$a`. 61 | 62 | 3. Finally, we check for placeholder "leaks" – a 63 | leak is basically any attempt to relate a placeholder region to another 64 | placeholder region, or to any region that pre-existed the impl match. 65 | The leak check is done by searching from the placeholder region to find 66 | the set of regions that it is related to in any way. This is called 67 | the "taint" set. To pass the check, that set must consist *solely* of 68 | itself and region variables from the impl. If the taint set includes 69 | any other region, then the match is a failure. In this case, the taint 70 | set for `'0` is `{'0, '$a}`, and hence the check will succeed. 71 | 72 | Let's consider a failure case. Imagine we also have a struct 73 | 74 | ```rust,ignore 75 | struct StaticInt; 76 | impl Foo<&'static isize> for StaticInt; 77 | ``` 78 | 79 | We want the obligation `StaticInt : for<'a> Foo<&'a isize>` to be 80 | considered unsatisfied. The check begins just as before. `'a` is 81 | replaced with a placeholder `'0` and the impl trait reference is instantiated to 82 | `Foo<&'static isize>`. When we relate those two, we get a constraint 83 | like `'static == '0`. This means that the taint set for `'0` is `{'0, 84 | 'static}`, which fails the leak check. 85 | 86 | **TODO**: This is because `'static` is not a region variable but is in the 87 | taint set, right? 88 | 89 | ## Higher-ranked trait obligations 90 | 91 | Once the basic matching is done, we get to another interesting topic: 92 | how to deal with impl obligations. I'll work through a simple example 93 | here. Imagine we have the traits `Foo` and `Bar` and an associated impl: 94 | 95 | ```rust 96 | trait Foo { 97 | fn foo(&self, x: X) { } 98 | } 99 | 100 | trait Bar { 101 | fn bar(&self, x: X) { } 102 | } 103 | 104 | impl Foo for F 105 | where F : Bar 106 | { 107 | } 108 | ``` 109 | 110 | Now let's say we have a obligation `Baz: for<'a> Foo<&'a isize>` and we match 111 | this impl. What obligation is generated as a result? We want to get 112 | `Baz: for<'a> Bar<&'a isize>`, but how does that happen? 113 | 114 | After the matching, we are in a position where we have a placeholder 115 | substitution like `X => &'0 isize`. If we apply this substitution to the 116 | impl obligations, we get `F : Bar<&'0 isize>`. Obviously this is not 117 | directly usable because the placeholder region `'0` cannot leak out of 118 | our computation. 119 | 120 | What we do is to create an inverse mapping from the taint set of `'0` 121 | back to the original bound region (`'a`, here) that `'0` resulted 122 | from. (This is done in `higher_ranked::plug_leaks`). We know that the 123 | leak check passed, so this taint set consists solely of the placeholder 124 | region itself plus various intermediate region variables. We then walk 125 | the trait-reference and convert every region in that taint set back to 126 | a late-bound region, so in this case we'd wind up with 127 | `Baz: for<'a> Bar<&'a isize>`. 128 | -------------------------------------------------------------------------------- /src-zh/tests/running.md: -------------------------------------------------------------------------------- 1 | # Running tests 2 | 3 | You can run the tests using `x.py`. The most basic command – which 4 | you will almost never want to use! – is as follows: 5 | 6 | ```bash 7 | > ./x.py test 8 | ``` 9 | 10 | This will build the full stage 2 compiler and then run the whole test 11 | suite. You probably don't want to do this very often, because it takes 12 | a very long time, and anyway bors / travis will do it for you. (Often, 13 | I will run this command in the background after opening a PR that I 14 | think is done, but rarely otherwise. -nmatsakis) 15 | 16 | The test results are cached and previously successful tests are 17 | `ignored` during testing. The stdout/stderr contents as well as a 18 | timestamp file for every test can be found under `build/ARCH/test/`. 19 | To force-rerun a test (e.g. in case the test runner fails to notice 20 | a change) you can simply remove the timestamp file. 21 | 22 | Note that some tests require a Python-enabled gdb. You can test if 23 | your gdb install supports Python by using the `python` command from 24 | within gdb. Once invoked you can type some Python code (e.g. 25 | `print("hi")`) followed by return and then `CTRL+D` to execute it. 26 | If you are building gdb from source, you will need to configure with 27 | `--with-python=`. 28 | 29 | ## Running a subset of the test suites 30 | 31 | When working on a specific PR, you will usually want to run a smaller 32 | set of tests, and with a stage 1 build. For example, a good "smoke 33 | test" that can be used after modifying rustc to see if things are 34 | generally working correctly would be the following: 35 | 36 | ```bash 37 | > ./x.py test --stage 1 src/test/{ui,compile-fail,run-pass} 38 | ``` 39 | 40 | This will run the `ui`, `compile-fail`, and `run-pass` test suites, 41 | and only with the stage 1 build. Of course, the choice of test suites 42 | is somewhat arbitrary, and may not suit the task you are doing. For 43 | example, if you are hacking on debuginfo, you may be better off with 44 | the debuginfo test suite: 45 | 46 | ```bash 47 | > ./x.py test --stage 1 src/test/debuginfo 48 | ``` 49 | 50 | If you only need to test a specific subdirectory of tests for any 51 | given test suite, you can pass that directory to `x.py test`: 52 | 53 | ```bash 54 | > ./x.py test --stage 1 src/test/ui/const-generics 55 | ``` 56 | 57 | Likewise, you can test a single file by passing its path: 58 | 59 | ```bash 60 | > ./x.py test --stage 1 src/test/ui/const-generics/const-test.rs 61 | ``` 62 | 63 | ### Run only the tidy script 64 | 65 | ```bash 66 | > ./x.py test src/tools/tidy 67 | ``` 68 | 69 | ### Run tests on the standard library 70 | 71 | ```bash 72 | > ./x.py test src/libstd 73 | ``` 74 | 75 | ### Run tests on the standard library and run the tidy script 76 | 77 | ```bash 78 | > ./x.py test src/libstd src/tools/tidy 79 | ``` 80 | 81 | ### Run tests on the standard library using a stage 1 compiler 82 | 83 | ```bash 84 | > ./x.py test src/libstd --stage 1 85 | ``` 86 | 87 | By listing which test suites you want to run you avoid having to run 88 | tests for components you did not change at all. 89 | 90 | **Warning:** Note that bors only runs the tests with the full stage 2 91 | build; therefore, while the tests **usually** work fine with stage 1, 92 | there are some limitations. In particular, the stage1 compiler doesn't 93 | work well with procedural macros or custom derive tests. 94 | 95 | ## Running an individual test 96 | 97 | Another common thing that people want to do is to run an **individual 98 | test**, often the test they are trying to fix. As mentioned earlier, 99 | you may pass the full file path to achieve this, or alternatively one 100 | may invoke `x.py` with the `--test-args` option: 101 | 102 | ```bash 103 | > ./x.py test --stage 1 src/test/ui --test-args issue-1234 104 | ``` 105 | 106 | Under the hood, the test runner invokes the standard rust test runner 107 | (the same one you get with `#[test]`), so this command would wind up 108 | filtering for tests that include "issue-1234" in the name. (Thus 109 | `--test-args` is a good way to run a collection of related tests.) 110 | 111 | ## Using incremental compilation 112 | 113 | You can further enable the `--incremental` flag to save additional 114 | time in subsequent rebuilds: 115 | 116 | ```bash 117 | > ./x.py test --stage 1 src/test/ui --incremental --test-args issue-1234 118 | ``` 119 | 120 | If you don't want to include the flag with every command, you can 121 | enable it in the `config.toml`, too: 122 | 123 | ```toml 124 | # Whether to always use incremental compilation when building rustc 125 | incremental = true 126 | ``` 127 | 128 | Note that incremental compilation will use more disk space than usual. 129 | If disk space is a concern for you, you might want to check the size 130 | of the `build` directory from time to time. 131 | 132 | ## Running tests manually 133 | 134 | Sometimes it's easier and faster to just run the test by hand. Most tests are 135 | just `rs` files, so you can do something like 136 | 137 | ```bash 138 | > rustc +stage1 src/test/ui/issue-1234.rs 139 | ``` 140 | 141 | This is much faster, but doesn't always work. For example, some tests 142 | include directives that specify specific compiler flags, or which rely 143 | on other crates, and they may not run the same without those options. 144 | -------------------------------------------------------------------------------- /src/tests/running.md: -------------------------------------------------------------------------------- 1 | # Running tests 2 | 3 | You can run the tests using `x.py`. The most basic command – which 4 | you will almost never want to use! – is as follows: 5 | 6 | ```bash 7 | > ./x.py test 8 | ``` 9 | 10 | This will build the full stage 2 compiler and then run the whole test 11 | suite. You probably don't want to do this very often, because it takes 12 | a very long time, and anyway bors / travis will do it for you. (Often, 13 | I will run this command in the background after opening a PR that I 14 | think is done, but rarely otherwise. -nmatsakis) 15 | 16 | The test results are cached and previously successful tests are 17 | `ignored` during testing. The stdout/stderr contents as well as a 18 | timestamp file for every test can be found under `build/ARCH/test/`. 19 | To force-rerun a test (e.g. in case the test runner fails to notice 20 | a change) you can simply remove the timestamp file. 21 | 22 | Note that some tests require a Python-enabled gdb. You can test if 23 | your gdb install supports Python by using the `python` command from 24 | within gdb. Once invoked you can type some Python code (e.g. 25 | `print("hi")`) followed by return and then `CTRL+D` to execute it. 26 | If you are building gdb from source, you will need to configure with 27 | `--with-python=`. 28 | 29 | ## Running a subset of the test suites 30 | 31 | When working on a specific PR, you will usually want to run a smaller 32 | set of tests, and with a stage 1 build. For example, a good "smoke 33 | test" that can be used after modifying rustc to see if things are 34 | generally working correctly would be the following: 35 | 36 | ```bash 37 | > ./x.py test --stage 1 src/test/{ui,compile-fail,run-pass} 38 | ``` 39 | 40 | This will run the `ui`, `compile-fail`, and `run-pass` test suites, 41 | and only with the stage 1 build. Of course, the choice of test suites 42 | is somewhat arbitrary, and may not suit the task you are doing. For 43 | example, if you are hacking on debuginfo, you may be better off with 44 | the debuginfo test suite: 45 | 46 | ```bash 47 | > ./x.py test --stage 1 src/test/debuginfo 48 | ``` 49 | 50 | If you only need to test a specific subdirectory of tests for any 51 | given test suite, you can pass that directory to `x.py test`: 52 | 53 | ```bash 54 | > ./x.py test --stage 1 src/test/ui/const-generics 55 | ``` 56 | 57 | Likewise, you can test a single file by passing its path: 58 | 59 | ```bash 60 | > ./x.py test --stage 1 src/test/ui/const-generics/const-test.rs 61 | ``` 62 | 63 | ### Run only the tidy script 64 | 65 | ```bash 66 | > ./x.py test src/tools/tidy 67 | ``` 68 | 69 | ### Run tests on the standard library 70 | 71 | ```bash 72 | > ./x.py test src/libstd 73 | ``` 74 | 75 | ### Run tests on the standard library and run the tidy script 76 | 77 | ```bash 78 | > ./x.py test src/libstd src/tools/tidy 79 | ``` 80 | 81 | ### Run tests on the standard library using a stage 1 compiler 82 | 83 | ```bash 84 | > ./x.py test src/libstd --stage 1 85 | ``` 86 | 87 | By listing which test suites you want to run you avoid having to run 88 | tests for components you did not change at all. 89 | 90 | **Warning:** Note that bors only runs the tests with the full stage 2 91 | build; therefore, while the tests **usually** work fine with stage 1, 92 | there are some limitations. In particular, the stage1 compiler doesn't 93 | work well with procedural macros or custom derive tests. 94 | 95 | ## Running an individual test 96 | 97 | Another common thing that people want to do is to run an **individual 98 | test**, often the test they are trying to fix. As mentioned earlier, 99 | you may pass the full file path to achieve this, or alternatively one 100 | may invoke `x.py` with the `--test-args` option: 101 | 102 | ```bash 103 | > ./x.py test --stage 1 src/test/ui --test-args issue-1234 104 | ``` 105 | 106 | Under the hood, the test runner invokes the standard rust test runner 107 | (the same one you get with `#[test]`), so this command would wind up 108 | filtering for tests that include "issue-1234" in the name. (Thus 109 | `--test-args` is a good way to run a collection of related tests.) 110 | 111 | ## Using incremental compilation 112 | 113 | You can further enable the `--incremental` flag to save additional 114 | time in subsequent rebuilds: 115 | 116 | ```bash 117 | > ./x.py test --stage 1 src/test/ui --incremental --test-args issue-1234 118 | ``` 119 | 120 | If you don't want to include the flag with every command, you can 121 | enable it in the `config.toml`, too: 122 | 123 | ```toml 124 | # Whether to always use incremental compilation when building rustc 125 | incremental = true 126 | ``` 127 | 128 | Note that incremental compilation will use more disk space than usual. 129 | If disk space is a concern for you, you might want to check the size 130 | of the `build` directory from time to time. 131 | 132 | ## Running tests manually 133 | 134 | Sometimes it's easier and faster to just run the test by hand. Most tests are 135 | just `rs` files, so you can do something like 136 | 137 | ```bash 138 | > rustc +stage1 src/test/ui/issue-1234.rs 139 | ``` 140 | 141 | This is much faster, but doesn't always work. For example, some tests 142 | include directives that specify specific compiler flags, or which rely 143 | on other crates, and they may not run the same without those options. 144 | -------------------------------------------------------------------------------- /src/ty.md: -------------------------------------------------------------------------------- 1 | # The `ty` module: representing types 2 | 3 | The `ty` module defines how the Rust compiler represents types 4 | internally. It also defines the *typing context* (`tcx` or `TyCtxt`), 5 | which is the central data structure in the compiler. 6 | 7 | ## The tcx and how it uses lifetimes 8 | 9 | The `tcx` ("typing context") is the central data structure in the 10 | compiler. It is the context that you use to perform all manner of 11 | queries. The struct `TyCtxt` defines a reference to this shared context: 12 | 13 | ```rust,ignore 14 | tcx: TyCtxt<'tcx> 15 | // ---- 16 | // | 17 | // arena lifetime 18 | ``` 19 | 20 | As you can see, the `TyCtxt` type takes a lifetime parameter. 21 | During Rust compilation, we allocate most of our memory in 22 | **arenas**, which are basically pools of memory that get freed all at 23 | once. When you see a reference with a lifetime like `'tcx`, 24 | you know that it refers to arena-allocated data (or data that lives as 25 | long as the arenas, anyhow). 26 | 27 | ### Allocating and working with types 28 | 29 | Rust types are represented using the `Ty<'tcx>` defined in the `ty` 30 | module (not to be confused with the `Ty` struct from [the HIR]). This 31 | is in fact a simple type alias for a reference with `'tcx` lifetime: 32 | 33 | ```rust,ignore 34 | pub type Ty<'tcx> = &'tcx TyS<'tcx>; 35 | ``` 36 | 37 | [the HIR]: ./hir.html 38 | 39 | You can basically ignore the `TyS` struct – you will basically never 40 | access it explicitly. We always pass it by reference using the 41 | `Ty<'tcx>` alias – the only exception I think is to define inherent 42 | methods on types. Instances of `TyS` are only ever allocated in one of 43 | the rustc arenas (never e.g. on the stack). 44 | 45 | One common operation on types is to **match** and see what kinds of 46 | types they are. This is done by doing `match ty.sty`, sort of like this: 47 | 48 | ```rust,ignore 49 | fn test_type<'tcx>(ty: Ty<'tcx>) { 50 | match ty.sty { 51 | ty::TyArray(elem_ty, len) => { ... } 52 | ... 53 | } 54 | } 55 | ``` 56 | 57 | The `sty` field (the origin of this name is unclear to me; perhaps 58 | structural type?) is of type `TyKind<'tcx>`, which is an enum 59 | defining all of the different kinds of types in the compiler. 60 | 61 | > N.B. inspecting the `sty` field on types during type inference can be 62 | > risky, as there may be inference variables and other things to 63 | > consider, or sometimes types are not yet known that will become 64 | > known later.). 65 | 66 | To allocate a new type, you can use the various `mk_` methods defined 67 | on the `tcx`. These have names that correpond mostly to the various kinds 68 | of type variants. For example: 69 | 70 | ```rust,ignore 71 | let array_ty = tcx.mk_array(elem_ty, len * 2); 72 | ``` 73 | 74 | These methods all return a `Ty<'tcx>` – note that the lifetime you 75 | get back is the lifetime of the innermost arena that this `tcx` has 76 | access to. In fact, types are always canonicalized and interned (so we 77 | never allocate exactly the same type twice) and are always allocated 78 | in the outermost arena where they can be (so, if they do not contain 79 | any inference variables or other "temporary" types, they will be 80 | allocated in the global arena). However, the lifetime `'tcx` is always 81 | a safe approximation, so that is what you get back. 82 | 83 | > NB. Because types are interned, it is possible to compare them for 84 | > equality efficiently using `==` – however, this is almost never what 85 | > you want to do unless you happen to be hashing and looking for 86 | > duplicates. This is because often in Rust there are multiple ways to 87 | > represent the same type, particularly once inference is involved. If 88 | > you are going to be testing for type equality, you probably need to 89 | > start looking into the inference code to do it right. 90 | 91 | You can also find various common types in the `tcx` itself by accessing 92 | `tcx.types.bool`, `tcx.types.char`, etc (see `CommonTypes` for more). 93 | 94 | ### Beyond types: other kinds of arena-allocated data structures 95 | 96 | In addition to types, there are a number of other arena-allocated data 97 | structures that you can allocate, and which are found in this 98 | module. Here are a few examples: 99 | 100 | - [`Substs`][subst], allocated with `mk_substs` – this will intern a slice of 101 | types, often used to specify the values to be substituted for generics 102 | (e.g. `HashMap` would be represented as a slice 103 | `&'tcx [tcx.types.i32, tcx.types.u32]`). 104 | - `TraitRef`, typically passed by value – a **trait reference** 105 | consists of a reference to a trait along with its various type 106 | parameters (including `Self`), like `i32: Display` (here, the def-id 107 | would reference the `Display` trait, and the substs would contain 108 | `i32`). 109 | - `Predicate` defines something the trait system has to prove (see `traits` 110 | module). 111 | 112 | [subst]: ./kinds.html#subst 113 | 114 | ### Import conventions 115 | 116 | Although there is no hard and fast rule, the `ty` module tends to be used like 117 | so: 118 | 119 | ```rust,ignore 120 | use ty::{self, Ty, TyCtxt}; 121 | ``` 122 | 123 | In particular, since they are so common, the `Ty` and `TyCtxt` types 124 | are imported directly. Other types are often referenced with an 125 | explicit `ty::` prefix (e.g. `ty::TraitRef<'tcx>`). But some modules 126 | choose to import a larger or smaller set of names explicitly. 127 | -------------------------------------------------------------------------------- /src-zh/method-lookup.md: -------------------------------------------------------------------------------- 1 | # Method lookup 2 | 3 | Method lookup can be rather complex due to the interaction of a number 4 | of factors, such as self types, autoderef, trait lookup, etc. This 5 | file provides an overview of the process. More detailed notes are in 6 | the code itself, naturally. 7 | 8 | One way to think of method lookup is that we convert an expression of 9 | the form: 10 | 11 | ```rust,ignore 12 | receiver.method(...) 13 | ``` 14 | 15 | into a more explicit [UFCS] form: 16 | 17 | ```rust,ignore 18 | Trait::method(ADJ(receiver), ...) // for a trait call 19 | ReceiverType::method(ADJ(receiver), ...) // for an inherent method call 20 | ``` 21 | 22 | Here `ADJ` is some kind of adjustment, which is typically a series of 23 | autoderefs and then possibly an autoref (e.g., `&**receiver`). However 24 | we sometimes do other adjustments and coercions along the way, in 25 | particular unsizing (e.g., converting from `[T; n]` to `[T]`). 26 | 27 | Method lookup is divided into two major phases: 28 | 29 | 1. Probing ([`probe.rs`][probe]). The probe phase is when we decide what method 30 | to call and how to adjust the receiver. 31 | 2. Confirmation ([`confirm.rs`][confirm]). The confirmation phase "applies" 32 | this selection, updating the side-tables, unifying type variables, and 33 | otherwise doing side-effectful things. 34 | 35 | One reason for this division is to be more amenable to caching. The 36 | probe phase produces a "pick" (`probe::Pick`), which is designed to be 37 | cacheable across method-call sites. Therefore, it does not include 38 | inference variables or other information. 39 | 40 | [UFCS]: https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md 41 | [probe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/method/probe/ 42 | [confirm]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/method/confirm/ 43 | 44 | ## The Probe phase 45 | 46 | ### Steps 47 | 48 | The first thing that the probe phase does is to create a series of 49 | *steps*. This is done by progressively dereferencing the receiver type 50 | until it cannot be deref'd anymore, as well as applying an optional 51 | "unsize" step. So if the receiver has type `Rc>`, this 52 | might yield: 53 | 54 | ```rust,ignore 55 | Rc> 56 | Box<[T; 3]> 57 | [T; 3] 58 | [T] 59 | ``` 60 | 61 | ### Candidate assembly 62 | 63 | We then search along those steps to create a list of *candidates*. A 64 | `Candidate` is a method item that might plausibly be the method being 65 | invoked. For each candidate, we'll derive a "transformed self type" 66 | that takes into account explicit self. 67 | 68 | Candidates are grouped into two kinds, inherent and extension. 69 | 70 | **Inherent candidates** are those that are derived from the 71 | type of the receiver itself. So, if you have a receiver of some 72 | nominal type `Foo` (e.g., a struct), any methods defined within an 73 | impl like `impl Foo` are inherent methods. Nothing needs to be 74 | imported to use an inherent method, they are associated with the type 75 | itself (note that inherent impls can only be defined in the same 76 | module as the type itself). 77 | 78 | FIXME: Inherent candidates are not always derived from impls. If you 79 | have a trait object, such as a value of type `Box`, then the 80 | trait methods (`to_string()`, in this case) are inherently associated 81 | with it. Another case is type parameters, in which case the methods of 82 | their bounds are inherent. However, this part of the rules is subject 83 | to change: when DST's "impl Trait for Trait" is complete, trait object 84 | dispatch could be subsumed into trait matching, and the type parameter 85 | behavior should be reconsidered in light of where clauses. 86 | 87 | TODO: Is this FIXME still accurate? 88 | 89 | **Extension candidates** are derived from imported traits. If I have 90 | the trait `ToString` imported, and I call `to_string()` on a value of 91 | type `T`, then we will go off to find out whether there is an impl of 92 | `ToString` for `T`. These kinds of method calls are called "extension 93 | methods". They can be defined in any module, not only the one that 94 | defined `T`. Furthermore, you must import the trait to call such a 95 | method. 96 | 97 | So, let's continue our example. Imagine that we were calling a method 98 | `foo` with the receiver `Rc>` and there is a trait `Foo` 99 | that defines it with `&self` for the type `Rc` as well as a method 100 | on the type `Box` that defines `Foo` but with `&mut self`. Then we 101 | might have two candidates: 102 | ```text 103 | &Rc> from the impl of `Foo` for `Rc` where `U=Box 104 | &mut Box<[T; 3]>> from the inherent impl on `Box` where `U=[T; 3]` 105 | ``` 106 | 107 | ### Candidate search 108 | 109 | Finally, to actually pick the method, we will search down the steps, 110 | trying to match the receiver type against the candidate types. At 111 | each step, we also consider an auto-ref and auto-mut-ref to see whether 112 | that makes any of the candidates match. We pick the first step where 113 | we find a match. 114 | 115 | In the case of our example, the first step is `Rc>`, 116 | which does not itself match any candidate. But when we autoref it, we 117 | get the type `&Rc>` which does match. We would then 118 | recursively consider all where-clauses that appear on the impl: if 119 | those match (or we cannot rule out that they do), then this is the 120 | method we would pick. Otherwise, we would continue down the series of 121 | steps. 122 | -------------------------------------------------------------------------------- /src/method-lookup.md: -------------------------------------------------------------------------------- 1 | # Method lookup 2 | 3 | Method lookup can be rather complex due to the interaction of a number 4 | of factors, such as self types, autoderef, trait lookup, etc. This 5 | file provides an overview of the process. More detailed notes are in 6 | the code itself, naturally. 7 | 8 | One way to think of method lookup is that we convert an expression of 9 | the form: 10 | 11 | ```rust,ignore 12 | receiver.method(...) 13 | ``` 14 | 15 | into a more explicit [UFCS] form: 16 | 17 | ```rust,ignore 18 | Trait::method(ADJ(receiver), ...) // for a trait call 19 | ReceiverType::method(ADJ(receiver), ...) // for an inherent method call 20 | ``` 21 | 22 | Here `ADJ` is some kind of adjustment, which is typically a series of 23 | autoderefs and then possibly an autoref (e.g., `&**receiver`). However 24 | we sometimes do other adjustments and coercions along the way, in 25 | particular unsizing (e.g., converting from `[T; n]` to `[T]`). 26 | 27 | Method lookup is divided into two major phases: 28 | 29 | 1. Probing ([`probe.rs`][probe]). The probe phase is when we decide what method 30 | to call and how to adjust the receiver. 31 | 2. Confirmation ([`confirm.rs`][confirm]). The confirmation phase "applies" 32 | this selection, updating the side-tables, unifying type variables, and 33 | otherwise doing side-effectful things. 34 | 35 | One reason for this division is to be more amenable to caching. The 36 | probe phase produces a "pick" (`probe::Pick`), which is designed to be 37 | cacheable across method-call sites. Therefore, it does not include 38 | inference variables or other information. 39 | 40 | [UFCS]: https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md 41 | [probe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/method/probe/ 42 | [confirm]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/method/confirm/ 43 | 44 | ## The Probe phase 45 | 46 | ### Steps 47 | 48 | The first thing that the probe phase does is to create a series of 49 | *steps*. This is done by progressively dereferencing the receiver type 50 | until it cannot be deref'd anymore, as well as applying an optional 51 | "unsize" step. So if the receiver has type `Rc>`, this 52 | might yield: 53 | 54 | ```rust,ignore 55 | Rc> 56 | Box<[T; 3]> 57 | [T; 3] 58 | [T] 59 | ``` 60 | 61 | ### Candidate assembly 62 | 63 | We then search along those steps to create a list of *candidates*. A 64 | `Candidate` is a method item that might plausibly be the method being 65 | invoked. For each candidate, we'll derive a "transformed self type" 66 | that takes into account explicit self. 67 | 68 | Candidates are grouped into two kinds, inherent and extension. 69 | 70 | **Inherent candidates** are those that are derived from the 71 | type of the receiver itself. So, if you have a receiver of some 72 | nominal type `Foo` (e.g., a struct), any methods defined within an 73 | impl like `impl Foo` are inherent methods. Nothing needs to be 74 | imported to use an inherent method, they are associated with the type 75 | itself (note that inherent impls can only be defined in the same 76 | module as the type itself). 77 | 78 | FIXME: Inherent candidates are not always derived from impls. If you 79 | have a trait object, such as a value of type `Box`, then the 80 | trait methods (`to_string()`, in this case) are inherently associated 81 | with it. Another case is type parameters, in which case the methods of 82 | their bounds are inherent. However, this part of the rules is subject 83 | to change: when DST's "impl Trait for Trait" is complete, trait object 84 | dispatch could be subsumed into trait matching, and the type parameter 85 | behavior should be reconsidered in light of where clauses. 86 | 87 | TODO: Is this FIXME still accurate? 88 | 89 | **Extension candidates** are derived from imported traits. If I have 90 | the trait `ToString` imported, and I call `to_string()` on a value of 91 | type `T`, then we will go off to find out whether there is an impl of 92 | `ToString` for `T`. These kinds of method calls are called "extension 93 | methods". They can be defined in any module, not only the one that 94 | defined `T`. Furthermore, you must import the trait to call such a 95 | method. 96 | 97 | So, let's continue our example. Imagine that we were calling a method 98 | `foo` with the receiver `Rc>` and there is a trait `Foo` 99 | that defines it with `&self` for the type `Rc` as well as a method 100 | on the type `Box` that defines `Foo` but with `&mut self`. Then we 101 | might have two candidates: 102 | ```text 103 | &Rc> from the impl of `Foo` for `Rc` where `U=Box 104 | &mut Box<[T; 3]>> from the inherent impl on `Box` where `U=[T; 3]` 105 | ``` 106 | 107 | ### Candidate search 108 | 109 | Finally, to actually pick the method, we will search down the steps, 110 | trying to match the receiver type against the candidate types. At 111 | each step, we also consider an auto-ref and auto-mut-ref to see whether 112 | that makes any of the candidates match. We pick the first step where 113 | we find a match. 114 | 115 | In the case of our example, the first step is `Rc>`, 116 | which does not itself match any candidate. But when we autoref it, we 117 | get the type `&Rc>` which does match. We would then 118 | recursively consider all where-clauses that appear on the impl: if 119 | those match (or we cannot rule out that they do), then this is the 120 | method we would pick. Otherwise, we would continue down the series of 121 | steps. 122 | -------------------------------------------------------------------------------- /src-zh/mir/mir_overview.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | G 11 | 12 | 13 | 14 | Operand 15 | 16 | Operand 17 | 18 | 19 | 20 | Constant 21 | 22 | Constant 23 | 24 | 25 | 26 | Operand->Constant 27 | 28 | 29 | 30 | 31 | 32 | Place 33 | 34 | Place 35 | 36 | 37 | 38 | Operand->Place 39 | 40 | 41 | 42 | 43 | 44 | Projection 45 | 46 | Projection 47 | 48 | 49 | 50 | Place->Projection 51 | 52 | 53 | 54 | 55 | 56 | Local 57 | 58 | Local 59 | 60 | 61 | 62 | Place->Local 63 | 64 | 65 | 66 | 67 | 68 | Projection->Place 69 | 70 | 71 | 72 | 73 | 74 | Rvalue 75 | 76 | Rvalue 77 | 78 | 79 | 80 | Rvalue->Operand 81 | 82 | 83 | 84 | 85 | 86 | Assignment 87 | 88 | Assignment 89 | 90 | 91 | 92 | Assignment->Operand 93 | 94 | 95 | 96 | 97 | 98 | Assignment->Place 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/mir/mir_overview.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | G 11 | 12 | 13 | 14 | Operand 15 | 16 | Operand 17 | 18 | 19 | 20 | Constant 21 | 22 | Constant 23 | 24 | 25 | 26 | Operand->Constant 27 | 28 | 29 | 30 | 31 | 32 | Place 33 | 34 | Place 35 | 36 | 37 | 38 | Operand->Place 39 | 40 | 41 | 42 | 43 | 44 | Projection 45 | 46 | Projection 47 | 48 | 49 | 50 | Place->Projection 51 | 52 | 53 | 54 | 55 | 56 | Local 57 | 58 | Local 59 | 60 | 61 | 62 | Place->Local 63 | 64 | 65 | 66 | 67 | 68 | Projection->Place 69 | 70 | 71 | 72 | 73 | 74 | Rvalue 75 | 76 | Rvalue 77 | 78 | 79 | 80 | Rvalue->Operand 81 | 82 | 83 | 84 | 85 | 86 | Assignment 87 | 88 | Assignment 89 | 90 | 91 | 92 | Assignment->Operand 93 | 94 | 95 | 96 | 97 | 98 | Assignment->Place 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/name-resolution.md: -------------------------------------------------------------------------------- 1 | # Name resolution 2 | 3 | The name resolution is a two-phase process. In the first phase, which runs 4 | during macro expansion, we build a tree of modules and resolve imports. Macro 5 | expansion and name resolution communicate with each other via the `Resolver` 6 | trait, defined in `libsyntax`. 7 | 8 | The input to the second phase is the syntax tree, produced by parsing input 9 | files and expanding macros. This phase produces links from all the names in the 10 | source to relevant places where the name was introduced. It also generates 11 | helpful error messages, like typo suggestions, traits to import or lints about 12 | unused items. 13 | 14 | A successful run of the second phase (`Resolver::resolve_crate`) creates kind 15 | of an index the rest of the compilation may use to ask about the present names 16 | (through the `hir::lowering::Resolver` interface). 17 | 18 | The name resolution lives in the `librustc_resolve` crate, with the meat in 19 | `lib.rs` and some helpers or symbol-type specific logic in the other modules. 20 | 21 | ## Namespaces 22 | 23 | Different kind of symbols live in different namespaces ‒ eg. types don't 24 | clash with variables. This usually doesn't happen, because variables start with 25 | lower-case letter while types with upper case one, but this is only a 26 | convention. This is legal Rust code that'll compile (with warnings): 27 | 28 | ```rust 29 | type x = u32; 30 | let x: x = 1; 31 | let y: x = 2; // See? x is still a type here. 32 | ``` 33 | 34 | To cope with this, and with slightly different scoping rules for these 35 | namespaces, the resolver keeps them separated and builds separate structures for 36 | them. 37 | 38 | In other words, when the code talks about namespaces, it doesn't mean the module 39 | hierarchy, it's types vs. values vs. macros. 40 | 41 | ## Scopes and ribs 42 | 43 | A name is visible only in certain area in the source code. This forms a 44 | hierarchical structure, but not necessarily a simple one ‒ if one scope is 45 | part of another, it doesn't mean the name visible in the outer one is also 46 | visible in the inner one, or that it refers to the same thing. 47 | 48 | To cope with that, the compiler introduces the concept of Ribs. This is 49 | abstraction of a scope. Every time the set of visible names potentially changes, 50 | a new rib is pushed onto a stack. The places where this can happen includes for 51 | example: 52 | 53 | * The obvious places ‒ curly braces enclosing a block, function boundaries, 54 | modules. 55 | * Introducing a let binding ‒ this can shadow another binding with the same 56 | name. 57 | * Macro expansion border ‒ to cope with macro hygiene. 58 | 59 | When searching for a name, the stack of ribs is traversed from the innermost 60 | outwards. This helps to find the closest meaning of the name (the one not 61 | shadowed by anything else). The transition to outer rib may also change the 62 | rules what names are usable ‒ if there are nested functions (not closures), 63 | the inner one can't access parameters and local bindings of the outer one, 64 | even though they should be visible by ordinary scoping rules. An example: 65 | 66 | ```rust 67 | fn do_something(val: T) { // <- New rib in both types and values (1) 68 | // `val` is accessible, as is the helper function 69 | // `T` is accessible 70 | let helper = || { // New rib on `helper` (2) and another on the block (3) 71 | // `val` is accessible here 72 | }; // End of (3) 73 | // `val` is accessible, `helper` variable shadows `helper` function 74 | fn helper() { // <- New rib in both types and values (4) 75 | // `val` is not accessible here, (4) is not transparent for locals) 76 | // `T` is not accessible here 77 | } // End of (4) 78 | let val = T::default(); // New rib (5) 79 | // `val` is the variable, not the parameter here 80 | } // End of (5), (2) and (1) 81 | ``` 82 | 83 | Because the rules for different namespaces are a bit different, each namespace 84 | has its own independent rib stack that is constructed in parallel to the others. 85 | In addition, there's also a rib stack for local labels (eg. names of loops or 86 | blocks), which isn't a full namespace in its own right. 87 | 88 | ## Overall strategy 89 | 90 | To perform the name resolution of the whole crate, the syntax tree is traversed 91 | top-down and every encountered name is resolved. This works for most kinds of 92 | names, because at the point of use of a name it is already introduced in the Rib 93 | hierarchy. 94 | 95 | There are some exceptions to this. Items are bit tricky, because they can be 96 | used even before encountered ‒ therefore every block needs to be first scanned 97 | for items to fill in its Rib. 98 | 99 | Other, even more problematic ones, are imports which need recursive fixed-point 100 | resolution and macros, that need to be resolved and expanded before the rest of 101 | the code can be processed. 102 | 103 | Therefore, the resolution is performed in multiple stages. 104 | 105 | ## TODO: 106 | 107 | This is a result of the first pass of learning the code. It is definitely 108 | incomplete and not detailed enough. It also might be inaccurate in places. 109 | Still, it probably provides useful first guidepost to what happens in there. 110 | 111 | * What exactly does it link to and how is that published and consumed by 112 | following stages of compilation? 113 | * Who calls it and how it is actually used. 114 | * Is it a pass and then the result is only used, or can it be computed 115 | incrementally (eg. for RLS)? 116 | * The overall strategy description is a bit vague. 117 | * Where does the name `Rib` come from? 118 | * Does this thing have its own tests, or is it tested only as part of some e2e 119 | testing? 120 | -------------------------------------------------------------------------------- /src-zh/name-resolution.md: -------------------------------------------------------------------------------- 1 | # Name resolution 2 | 3 | The name resolution is a two-phase process. In the first phase, which runs 4 | during macro expansion, we build a tree of modules and resolve imports. Macro 5 | expansion and name resolution communicate with each other via the `Resolver` 6 | trait, defined in `libsyntax`. 7 | 8 | The input to the second phase is the syntax tree, produced by parsing input 9 | files and expanding macros. This phase produces links from all the names in the 10 | source to relevant places where the name was introduced. It also generates 11 | helpful error messages, like typo suggestions, traits to import or lints about 12 | unused items. 13 | 14 | A successful run of the second phase (`Resolver::resolve_crate`) creates kind 15 | of an index the rest of the compilation may use to ask about the present names 16 | (through the `hir::lowering::Resolver` interface). 17 | 18 | The name resolution lives in the `librustc_resolve` crate, with the meat in 19 | `lib.rs` and some helpers or symbol-type specific logic in the other modules. 20 | 21 | ## Namespaces 22 | 23 | Different kind of symbols live in different namespaces ‒ eg. types don't 24 | clash with variables. This usually doesn't happen, because variables start with 25 | lower-case letter while types with upper case one, but this is only a 26 | convention. This is legal Rust code that'll compile (with warnings): 27 | 28 | ```rust 29 | type x = u32; 30 | let x: x = 1; 31 | let y: x = 2; // See? x is still a type here. 32 | ``` 33 | 34 | To cope with this, and with slightly different scoping rules for these 35 | namespaces, the resolver keeps them separated and builds separate structures for 36 | them. 37 | 38 | In other words, when the code talks about namespaces, it doesn't mean the module 39 | hierarchy, it's types vs. values vs. macros. 40 | 41 | ## Scopes and ribs 42 | 43 | A name is visible only in certain area in the source code. This forms a 44 | hierarchical structure, but not necessarily a simple one ‒ if one scope is 45 | part of another, it doesn't mean the name visible in the outer one is also 46 | visible in the inner one, or that it refers to the same thing. 47 | 48 | To cope with that, the compiler introduces the concept of Ribs. This is 49 | abstraction of a scope. Every time the set of visible names potentially changes, 50 | a new rib is pushed onto a stack. The places where this can happen includes for 51 | example: 52 | 53 | * The obvious places ‒ curly braces enclosing a block, function boundaries, 54 | modules. 55 | * Introducing a let binding ‒ this can shadow another binding with the same 56 | name. 57 | * Macro expansion border ‒ to cope with macro hygiene. 58 | 59 | When searching for a name, the stack of ribs is traversed from the innermost 60 | outwards. This helps to find the closest meaning of the name (the one not 61 | shadowed by anything else). The transition to outer rib may also change the 62 | rules what names are usable ‒ if there are nested functions (not closures), 63 | the inner one can't access parameters and local bindings of the outer one, 64 | even though they should be visible by ordinary scoping rules. An example: 65 | 66 | ```rust 67 | fn do_something(val: T) { // <- New rib in both types and values (1) 68 | // `val` is accessible, as is the helper function 69 | // `T` is accessible 70 | let helper = || { // New rib on `helper` (2) and another on the block (3) 71 | // `val` is accessible here 72 | }; // End of (3) 73 | // `val` is accessible, `helper` variable shadows `helper` function 74 | fn helper() { // <- New rib in both types and values (4) 75 | // `val` is not accessible here, (4) is not transparent for locals) 76 | // `T` is not accessible here 77 | } // End of (4) 78 | let val = T::default(); // New rib (5) 79 | // `val` is the variable, not the parameter here 80 | } // End of (5), (2) and (1) 81 | ``` 82 | 83 | Because the rules for different namespaces are a bit different, each namespace 84 | has its own independent rib stack that is constructed in parallel to the others. 85 | In addition, there's also a rib stack for local labels (eg. names of loops or 86 | blocks), which isn't a full namespace in its own right. 87 | 88 | ## Overall strategy 89 | 90 | To perform the name resolution of the whole crate, the syntax tree is traversed 91 | top-down and every encountered name is resolved. This works for most kinds of 92 | names, because at the point of use of a name it is already introduced in the Rib 93 | hierarchy. 94 | 95 | There are some exceptions to this. Items are bit tricky, because they can be 96 | used even before encountered ‒ therefore every block needs to be first scanned 97 | for items to fill in its Rib. 98 | 99 | Other, even more problematic ones, are imports which need recursive fixed-point 100 | resolution and macros, that need to be resolved and expanded before the rest of 101 | the code can be processed. 102 | 103 | Therefore, the resolution is performed in multiple stages. 104 | 105 | ## TODO: 106 | 107 | This is a result of the first pass of learning the code. It is definitely 108 | incomplete and not detailed enough. It also might be inaccurate in places. 109 | Still, it probably provides useful first guidepost to what happens in there. 110 | 111 | * What exactly does it link to and how is that published and consumed by 112 | following stages of compilation? 113 | * Who calls it and how it is actually used. 114 | * Is it a pass and then the result is only used, or can it be computed 115 | incrementally (eg. for RLS)? 116 | * The overall strategy description is a bit vague. 117 | * Where does the name `Rib` come from? 118 | * Does this thing have its own tests, or is it tested only as part of some e2e 119 | testing? 120 | -------------------------------------------------------------------------------- /src/compiler-team.md: -------------------------------------------------------------------------------- 1 | # About the compiler team 2 | 3 | rustc is maintained by the [Rust compiler team][team]. The people who belong to 4 | this team collectively work to track regressions and implement new features. 5 | Members of the Rust compiler team are people who have made significant 6 | contributions to rustc and its design. 7 | 8 | [team]: https://www.rust-lang.org/governance/teams/language-and-compiler 9 | 10 | ## Discussion 11 | 12 | Currently the compiler team chats in 2 places: 13 | 14 | - The `t-compiler` stream on [the Zulip instance][zulip] 15 | - The `compiler` channel on the [rust-lang discord](https://discord.gg/rust-lang) 16 | 17 | ## Expert map 18 | 19 | If you're interested in figuring out who can answer questions about a 20 | particular part of the compiler, or you'd just like to know who works on what, 21 | check out our [experts directory](https://github.com/rust-lang/compiler-team/blob/master/experts/MAP.md). 22 | It contains a listing of the various parts of the compiler and a list of people 23 | who are experts on each one. 24 | 25 | ## Rust compiler meeting 26 | 27 | The compiler team has a weekly meeting where we do triage and try to 28 | generally stay on top of new bugs, regressions, and other things. This 29 | general plan for this meeting can be found in 30 | [the rust-compiler-meeting etherpad][etherpad]. It works roughly as 31 | follows: 32 | 33 | - **Review P-high bugs:** P-high bugs are those that are sufficiently 34 | important for us to actively track progress. P-high bugs should 35 | ideally always have an assignee. 36 | - **Look over new regressions:** we then look for new cases where the 37 | compiler broke previously working code in the wild. Regressions are 38 | almost always marked as P-high; the major exception would be bug 39 | fixes (though even there we often 40 | [aim to give warnings first][procedure]). 41 | - **Check I-nominated issues:** These are issues where feedback from 42 | the team is desired. 43 | - **Check for beta nominations:** These are nominations of things to 44 | backport to beta. 45 | 46 | The meeting currently takes place on Thursdays at 10am Boston time 47 | (UTC-4 typically, but daylight savings time sometimes makes things 48 | complicated). 49 | 50 | The meeting is held over a "chat medium", currently on [zulip]. 51 | 52 | [etherpad]: https://public.etherpad-mozilla.org/p/rust-compiler-meeting 53 | [procedure]: https://forge.rust-lang.org/rustc-bug-fix-procedure.html 54 | [zulip]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler 55 | 56 | ## Team membership 57 | 58 | Membership in the Rust team is typically offered when someone has been 59 | making significant contributions to the compiler for some 60 | time. Membership is both a recognition but also an obligation: 61 | compiler team members are generally expected to help with upkeep as 62 | well as doing reviews and other work. 63 | 64 | If you are interested in becoming a compiler team member, the first 65 | thing to do is to start fixing some bugs, or get involved in a working 66 | group. One good way to find bugs is to look for 67 | [open issues tagged with E-easy](https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy) 68 | or 69 | [E-mentor](https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-mentor). 70 | 71 | ### r+ rights 72 | 73 | Once you have made a number of individual PRs to rustc, we will often 74 | offer r+ privileges. This means that you have the right to instruct 75 | "bors" (the robot that manages which PRs get landed into rustc) to 76 | merge a PR 77 | ([here are some instructions for how to talk to bors][homu-guide]). 78 | 79 | [homu-guide]: https://buildbot2.rust-lang.org/homu/ 80 | 81 | The guidelines for reviewers are as follows: 82 | 83 | - You are always welcome to review any PR, regardless of who it is 84 | assigned to. However, do not r+ PRs unless: 85 | - You are confident in that part of the code. 86 | - You are confident that nobody else wants to review it first. 87 | - For example, sometimes people will express a desire to review a 88 | PR before it lands, perhaps because it touches a particularly 89 | sensitive part of the code. 90 | - Always be polite when reviewing: you are a representative of the 91 | Rust project, so it is expected that you will go above and beyond 92 | when it comes to the [Code of Conduct]. 93 | 94 | [Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct 95 | 96 | ### high-five 97 | 98 | Once you have r+ rights, you can also be added to the [high-five][hi5] 99 | rotation. high-five is the bot that assigns incoming PRs to 100 | reviewers. If you are added, you will be randomly selected to review 101 | PRs. If you find you are assigned a PR that you don't feel comfortable 102 | reviewing, you can also leave a comment like `r? @so-and-so` to assign 103 | to someone else — if you don't know who to request, just write `r? 104 | @nikomatsakis for reassignment` and @nikomatsakis will pick someone 105 | for you. 106 | 107 | [hi5]: https://github.com/rust-highfive 108 | 109 | Getting on the high-five list is much appreciated as it lowers the 110 | review burden for all of us! However, if you don't have time to give 111 | people timely feedback on their PRs, it may be better that you don't 112 | get on the list. 113 | 114 | ### Full team membership 115 | 116 | Full team membership is typically extended once someone made many 117 | contributions to the Rust compiler over time, ideally (but not 118 | necessarily) to multiple areas. Sometimes this might be implementing a 119 | new feature, but it is also important — perhaps more important! — to 120 | have time and willingness to help out with general upkeep such as 121 | bugfixes, tracking regressions, and other less glamorous work. 122 | --------------------------------------------------------------------------------