├── 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 |
104 |
--------------------------------------------------------------------------------
/src/mir/mir_overview.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
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 |
--------------------------------------------------------------------------------