Add mdbook-toc, markers, and documentation (#1028)
* Add mdbook-toc to travis, book.toml and documentation * Add toc markers * Whitespace cleanup and some punctuation * Addressed comments
This commit is contained in:
parent
d8d5bbcfe3
commit
7a80b01e01
|
|
@ -13,6 +13,7 @@ install:
|
|||
- source ~/.cargo/env || true
|
||||
- cargo install mdbook --version '^0.4.5'
|
||||
- cargo install mdbook-linkcheck --version '^0.7.2'
|
||||
- cargo install mdbook-toc --version '^0.6.1'
|
||||
script:
|
||||
- git checkout -b ci
|
||||
- git rebase origin/master
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ rustdocs][rustdocs].
|
|||
To build a local static HTML site, install [`mdbook`](https://github.com/rust-lang/mdBook) with:
|
||||
|
||||
```
|
||||
> cargo install mdbook mdbook-linkcheck
|
||||
> cargo install mdbook mdbook-linkcheck mdbook-toc
|
||||
```
|
||||
|
||||
and execute the following command in the root of the repository:
|
||||
|
|
@ -56,6 +56,11 @@ The build files are found in the `book` directory.
|
|||
We use `mdbook-linkcheck` to validate URLs included in our documentation.
|
||||
`linkcheck` will be run automatically when you build with the instructions in the section above.
|
||||
|
||||
### Table of Contents
|
||||
|
||||
We use `mdbook-toc` to auto-generate TOCs for long sections. You can invoke the preprocessor by
|
||||
including the `<!-- toc -->` marker at the place where you want the TOC.
|
||||
|
||||
### Pre-commit script
|
||||
|
||||
We also test that line lengths are less than 100 columns. To test this locally,
|
||||
|
|
@ -95,7 +100,7 @@ but we leave these instructions for when we do it again in the future.
|
|||
|
||||
7. Click on the log and Ctrl-f to get a search box in the log
|
||||
|
||||
8. Search for rustc-dev-guide. This gets you to the place where the links are checked. It is usually ~11K lines into the log
|
||||
8. Search for rustc-dev-guide. This gets you to the place where the links are checked. It is usually ~11K lines into the log.
|
||||
|
||||
9. Look at the links in the log near that point in the log
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ description = "A guide to developing rustc"
|
|||
[build]
|
||||
create-missing = false
|
||||
|
||||
[preprocessor.toc]
|
||||
command = "mdbook-toc"
|
||||
renderer = ["html"]
|
||||
|
||||
[output.html]
|
||||
git-repository-url = "https://github.com/rust-lang/rustc-dev-guide"
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ a correction!
|
|||
If you do contribute to the guide, please see the corresponding
|
||||
[subsection on writing documentation in this guide].
|
||||
|
||||
[subsection on writing documentation in this guide]: contributing.md#contributing-to-rustc-dev-guide.
|
||||
[subsection on writing documentation in this guide]: contributing.md#contributing-to-rustc-dev-guide
|
||||
|
||||
> “‘All conditioned things are impermanent’ — when one sees this with wisdom, one turns away from
|
||||
> suffering.” _The Dhammapada, verse 277_
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Backend Agnostic Codegen
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
As of January 2021, `rustc_codegen_ssa` provides an abstract interface for all backends to
|
||||
implement, to allow other codegen backends (e.g. [Cranelift]).
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
# Implicit Caller Location
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
Approved in [RFC 2091], this feature enables the accurate reporting of caller location during panics
|
||||
initiated from functions like `Option::unwrap`, `Result::expect`, and `Index::index`. This feature
|
||||
adds the [`#[track_caller]`][attr-reference] attribute for functions, the
|
||||
[`caller_location`][intrinsic] intrinsic, and the stabilization-friendly
|
||||
initiated from functions like `Option::unwrap`, `Result::expect`, and `Index::index`. This feature
|
||||
adds the [`#[track_caller]`][attr-reference] attribute for functions, the
|
||||
[`caller_location`][intrinsic] intrinsic, and the stabilization-friendly
|
||||
[`core::panic::Location::caller`][wrapper] wrapper.
|
||||
|
||||
## Motivating Example
|
||||
|
|
@ -28,25 +30,25 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
|
|||
As of 1.42, we get a much more helpful message:
|
||||
|
||||
```
|
||||
$ rustc +1.42.0 example.rs; example.exe
|
||||
$ rustc +1.42.0 example.rs; example.exe
|
||||
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', example.rs:3:5
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
```
|
||||
|
||||
These error messages are achieved through a combination of changes to `panic!` internals to make use
|
||||
of `core::panic::Location::caller` and a number of `#[track_caller]` annotations in the standard
|
||||
of `core::panic::Location::caller` and a number of `#[track_caller]` annotations in the standard
|
||||
library which propagate caller information.
|
||||
|
||||
## Reading Caller Location
|
||||
|
||||
Previously, `panic!` made use of the `file!()`, `line!()`, and `column!()` macros to construct a
|
||||
[`Location`] pointing to where the panic occurred. These macros couldn't be given an overridden
|
||||
location, so functions which intentionally invoked `panic!` couldn't provide their own location,
|
||||
location, so functions which intentionally invoked `panic!` couldn't provide their own location,
|
||||
hiding the actual source of error.
|
||||
|
||||
Internally, `panic!()` now calls [`core::panic::Location::caller()`][wrapper] to find out where it
|
||||
was expanded. This function is itself annotated with `#[track_caller]` and wraps the
|
||||
[`caller_location`][intrinsic] compiler intrinsic implemented by rustc. This intrinsic is easiest
|
||||
Internally, `panic!()` now calls [`core::panic::Location::caller()`][wrapper] to find out where it
|
||||
was expanded. This function is itself annotated with `#[track_caller]` and wraps the
|
||||
[`caller_location`][intrinsic] compiler intrinsic implemented by rustc. This intrinsic is easiest
|
||||
explained in terms of how it works in a `const` context.
|
||||
|
||||
## Caller Location in `const`
|
||||
|
|
@ -56,20 +58,20 @@ to find the right location and allocating a const value to return.
|
|||
|
||||
### Finding the right `Location`
|
||||
|
||||
In a const context we "walk up the stack" from where the intrinsic is invoked, stopping when we
|
||||
In a const context we "walk up the stack" from where the intrinsic is invoked, stopping when we
|
||||
reach the first function call in the stack which does *not* have the attribute. This walk is in
|
||||
[`InterpCx::find_closest_untracked_caller_location()`][const-find-closest].
|
||||
|
||||
Starting at the bottom, we iterate up over stack [`Frame`][const-frame]s in the
|
||||
Starting at the bottom, we iterate up over stack [`Frame`][const-frame]s in the
|
||||
[`InterpCx::stack`][const-stack], calling
|
||||
[`InstanceDef::requires_caller_location`][requires-location] on the
|
||||
[`InstanceDef::requires_caller_location`][requires-location] on the
|
||||
[`Instance`s from each `Frame`][frame-instance]. We stop once we find one that returns `false` and
|
||||
return the span of the *previous* frame which was the "topmost" tracked function.
|
||||
|
||||
### Allocating a static `Location`
|
||||
|
||||
Once we have a `Span`, we need to allocate static memory for the `Location`, which is performed by
|
||||
the [`TyCtxt::const_caller_location()`][const-location-query] query. Internally this calls
|
||||
Once we have a `Span`, we need to allocate static memory for the `Location`, which is performed by
|
||||
the [`TyCtxt::const_caller_location()`][const-location-query] query. Internally this calls
|
||||
[`InterpCx::alloc_caller_location()`][alloc-location] and results in a unique
|
||||
[memory kind][location-memory-kind] (`MemoryKind::CallerLocation`). The SSA codegen backend is able
|
||||
to emit code for these same values, and we use this code there as well.
|
||||
|
|
@ -78,14 +80,14 @@ Once our `Location` has been allocated in static memory, our intrinsic returns a
|
|||
|
||||
## Generating code for `#[track_caller]` callees
|
||||
|
||||
To generate efficient code for a tracked function and its callers, we need to provide the same
|
||||
To generate efficient code for a tracked function and its callers, we need to provide the same
|
||||
behavior from the intrinsic's point of view without having a stack to walk up at runtime. We invert
|
||||
the approach: as we grow the stack down we pass an additional argument to calls of tracked functions
|
||||
rather than walking up the stack when the intrinsic is called. That additional argument can be
|
||||
returned wherever the caller location is queried.
|
||||
|
||||
The argument we append is of type `&'static core::panic::Location<'static>`. A reference was chosen
|
||||
to avoid unnecessary copying because a pointer is a third the size of
|
||||
to avoid unnecessary copying because a pointer is a third the size of
|
||||
`std::mem::size_of::<core::panic::Location>() == 24` at time of writing.
|
||||
|
||||
When generating a call to a function which is tracked, we pass the location argument the value of
|
||||
|
|
@ -151,12 +153,12 @@ probably the best we can do without modifying fully-stabilized type signatures.
|
|||
|
||||
> *Note:* We always emit a [`ReifyShim`] when taking a pointer to a tracked function. While the
|
||||
> constraint here is imposed by codegen contexts, we don't know during MIR construction of the shim
|
||||
> whether we'll be called in a const context (safe to ignore shim) or in a codegen context (unsafe
|
||||
> whether we'll be called in a const context (safe to ignore shim) or in a codegen context (unsafe
|
||||
> to ignore shim). Even if we did know, the results from const and codegen contexts must agree.
|
||||
|
||||
## The Attribute
|
||||
|
||||
The `#[track_caller]` attribute is checked alongside other codegen attributes to ensure the
|
||||
The `#[track_caller]` attribute is checked alongside other codegen attributes to ensure the
|
||||
function:
|
||||
|
||||
* has the `"Rust"` ABI (as opposed to e.g., `"C"`)
|
||||
|
|
@ -171,7 +173,7 @@ used in both const and codegen contexts to ensure correct propagation.
|
|||
|
||||
When applied to trait method implementations, the attribute works as it does for regular functions.
|
||||
|
||||
When applied to a trait method prototype, the attribute applies to all implementations of the
|
||||
When applied to a trait method prototype, the attribute applies to all implementations of the
|
||||
method. When applied to a default trait method implementation, the attribute takes effect on
|
||||
that implementation *and* any overrides.
|
||||
|
||||
|
|
@ -203,14 +205,14 @@ trait TrackedFourWays {
|
|||
assert_tracked!();
|
||||
}
|
||||
|
||||
/// Overrides of this implementation are tracked (it is too).
|
||||
/// Overrides of this implementation are tracked (it is too).
|
||||
#[track_caller]
|
||||
fn default_tracked_to_override() {
|
||||
assert_tracked!();
|
||||
}
|
||||
}
|
||||
|
||||
/// This impl uses the default impl for `default_tracked` and provides its own for
|
||||
/// This impl uses the default impl for `default_tracked` and provides its own for
|
||||
/// `default_tracked_to_override`.
|
||||
impl TrackedFourWays for () {
|
||||
fn blanket_tracked() {
|
||||
|
|
@ -253,7 +255,7 @@ up on the tracking issue. During the course of implementing that, it was also di
|
|||
implementation was possible without modifying the number of arguments in a function's MIR, which
|
||||
would simplify later stages and unlock use in traits.
|
||||
|
||||
Because the RFC's implementation strategy could not readily support traits, the semantics were not
|
||||
Because the RFC's implementation strategy could not readily support traits, the semantics were not
|
||||
originally specified. They have since been implemented following the path which seemed most correct
|
||||
to the author and reviewers.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Monomorphization
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
As you probably know, rust has a very expressive type system that has extensive
|
||||
support for generic types. But of course, assembly is not generic, so we need
|
||||
to figure out the concrete types of all the generics before the code can
|
||||
|
|
@ -57,12 +59,12 @@ units](../appendix/glossary.md#codegen-unit).
|
|||
|
||||
## Codegen Unit (CGU) partitioning
|
||||
|
||||
For better incremental build times, the CGU partitioner creates two CGU for each source level
|
||||
modules. One is for "stable" i.e. non-generic code and the other is more volatile code i.e.
|
||||
For better incremental build times, the CGU partitioner creates two CGU for each source level
|
||||
modules. One is for "stable" i.e. non-generic code and the other is more volatile code i.e.
|
||||
monoporphized/specialized instances.
|
||||
|
||||
For depenencies, consider Crate A and Crate B, such that Crate B depends on Crate A.
|
||||
The following table lists different scenarios for a function in Crate A that might be used by one
|
||||
The following table lists different scenarios for a function in Crate A that might be used by one
|
||||
or more modules in Crate B.
|
||||
|
||||
| Crate A function | Behavior |
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Updating LLVM
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
The Rust compiler uses LLVM as its primary codegen backend today, and naturally
|
||||
we want to at least occasionally update this dependency! Currently we do not
|
||||
have a strict policy about when to update LLVM or what it can be updated to, but
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Move paths
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
In reality, it's not enough to track initialization at the granularity
|
||||
of local variables. Rust also allows us to do moves and initialization
|
||||
at the field granularity:
|
||||
|
|
@ -7,11 +9,11 @@ at the field granularity:
|
|||
```rust,ignore
|
||||
fn foo() {
|
||||
let a: (Vec<u32>, Vec<u32>) = (vec![22], vec![44]);
|
||||
|
||||
|
||||
// a.0 and a.1 are both initialized
|
||||
|
||||
|
||||
let b = a.0; // moves a.0
|
||||
|
||||
|
||||
// a.0 is not initialized, but a.1 still is
|
||||
|
||||
let c = a.0; // ERROR
|
||||
|
|
@ -73,7 +75,7 @@ there is no need for a [`MovePathIndex`]. Some examples:
|
|||
there would be no move-path for `foo[1]`.
|
||||
- You cannot move from inside of a borrowed reference, so if we have e.g. `foo: &String`,
|
||||
there would be no move-path for `*foo`.
|
||||
|
||||
|
||||
These rules are enforced by the [`move_path_for`] function, which
|
||||
converts a [`Place`] into a [`MovePathIndex`] -- in error cases like
|
||||
those just discussed, the function returns an `Err`. This in turn
|
||||
|
|
@ -102,7 +104,7 @@ of [`MoveData`]. There are two different methods:
|
|||
[`LookupResult`] indicating the closest path it was able to find
|
||||
that exists (e.g., for `foo[1]`, it might return just the path for
|
||||
`foo`).
|
||||
|
||||
|
||||
[`find`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MovePathLookup.html#method.find
|
||||
[`find_local`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/dataflow/move_paths/struct.MovePathLookup.html#method.find_local
|
||||
[`mir::Local`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Local.html
|
||||
|
|
@ -120,7 +122,7 @@ just over the paths that are **actually referenced** in the source,
|
|||
not all **possible** paths that could have been referenced). These
|
||||
references are used for example in the
|
||||
[`find_in_move_path_or_its_descendants`] function, which determines
|
||||
whether a move-path (e.g., `a.b`) or any child of that move-path
|
||||
whether a move-path (e.g., `a.b`) or any child of that move-path
|
||||
(e.g.,`a.b.c`) matches a given predicate.
|
||||
|
||||
[`Place`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Place.html
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Region inference (NLL)
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
The MIR-based region checking code is located in [the `rustc_mir::borrow_check`
|
||||
module][nll].
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Constraint propagation
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
The main work of the region inference is **constraint propagation**,
|
||||
which is done in the [`propagate_constraints`] function. There are
|
||||
three sorts of constraints that are used in NLL, and we'll explain how
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Universal regions
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
"Universal regions" is the name that the code uses to refer to "named
|
||||
lifetimes" -- e.g., lifetime parameters and `'static`. The name
|
||||
derives from the fact that such lifetimes are "universally quantified"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Member constraints
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
A member constraint `'m member of ['c_1..'c_N]` expresses that the
|
||||
region `'m` must be *equal* to some **choice regions** `'c_i` (for
|
||||
some `i`). These constraints cannot be expressed by users, but they
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Placeholders and universes
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
From time to time we have to reason about regions that we can't
|
||||
concretely know. For example, consider this program:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
# Rustc Bug Fix Procedure
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
This page defines the best practices procedure for making bug fixes or soundness
|
||||
corrections in the compiler that can cause existing code to stop compiling. This
|
||||
text is based on
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Bootstrapping the Compiler
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
This subchapter is about the bootstrapping process.
|
||||
|
||||
## What is bootstrapping? How does it work?
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
# Debugging the compiler
|
||||
[debugging]: #debugging
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
This chapter contains a few tips to debug the compiler. These tips aim to be
|
||||
useful no matter what you are working on. Some of the other chapters have
|
||||
advice about specific parts of the compiler (e.g. the [Queries Debugging and
|
||||
|
|
@ -9,14 +11,14 @@ chapter](./backend/debugging.md)).
|
|||
|
||||
## Configuring the compiler
|
||||
|
||||
By default, rustc is built without most debug information. To enable debug info,
|
||||
set `debug = true` in your config.toml.
|
||||
By default, rustc is built without most debug information. To enable debug info,
|
||||
set `debug = true` in your config.toml.
|
||||
|
||||
Setting `debug = true` turns on many different debug options (e.g., `debug-assertions`,
|
||||
`debug-logging`, etc.) which can be individually tweaked if you want to, but many people
|
||||
Setting `debug = true` turns on many different debug options (e.g., `debug-assertions`,
|
||||
`debug-logging`, etc.) which can be individually tweaked if you want to, but many people
|
||||
simply set `debug = true`. Check out the comments in config.toml.example for more info.
|
||||
|
||||
You will need to rebuild the compiler once you've changed any configuration options.
|
||||
You will need to rebuild the compiler once you've changed any configuration options.
|
||||
|
||||
## `-Z` flags
|
||||
|
||||
|
|
@ -36,7 +38,7 @@ normal Rust programs. IIRC backtraces **don't work** on MinGW,
|
|||
sorry. If you have trouble or the backtraces are full of `unknown`,
|
||||
you might want to find some way to use Linux, Mac, or MSVC on Windows.
|
||||
|
||||
In the default configuration (without `debug` set to `true`), you don't have line numbers
|
||||
In the default configuration (without `debug` set to `true`), you don't have line numbers
|
||||
enabled, so the backtrace looks like this:
|
||||
|
||||
```text
|
||||
|
|
@ -56,7 +58,7 @@ stack backtrace:
|
|||
37: rustc_driver::run_compiler
|
||||
```
|
||||
|
||||
If you set `debug = true`, you will get line numbers for the stack trace.
|
||||
If you set `debug = true`, you will get line numbers for the stack trace.
|
||||
Then the backtrace will look like this:
|
||||
|
||||
```text
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
# High-level overview of the compiler source
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
> **NOTE**: The structure of the repository is going through a lot of
|
||||
> transitions. In particular, we want to get to a point eventually where the
|
||||
> top-level directory has separate directories for the compiler, build-system,
|
||||
> std libs, etc, rather than one huge `src/` directory.
|
||||
>
|
||||
> As of this writing, the std libs have been moved to `library/` and the crates
|
||||
> As of January 2021, the std libs have been moved to `library/` and the crates
|
||||
> that make up the `rustc` compiler itself have been moved to `compiler/`
|
||||
|
||||
Now that we have [seen what the compiler does](./overview.md), let's take a
|
||||
|
|
|
|||
|
|
@ -3,14 +3,7 @@
|
|||
Thank you for your interest in contributing to Rust! There are many ways to
|
||||
contribute, and we appreciate all of them.
|
||||
|
||||
* [Feature Requests](#feature-requests)
|
||||
* [Bug Reports](#bug-reports)
|
||||
* [The Build System](./building/how-to-build-and-run.md)
|
||||
* [Pull Requests](#pull-requests)
|
||||
* [Writing Documentation](#writing-documentation)
|
||||
* [Issue Triage](#issue-triage)
|
||||
* [Out-of-tree Contributions](#out-of-tree-contributions)
|
||||
* [Helpful Links and Information](#helpful-links-and-information)
|
||||
<!-- toc -->
|
||||
|
||||
If you have questions, please make a post on [internals.rust-lang.org][internals] or
|
||||
hop on the [Rust Discord server][rust-discord] or [Rust Zulip server][rust-zulip].
|
||||
|
|
@ -423,6 +416,9 @@ Just a few things to keep in mind:
|
|||
- A link to a relevant WG, tracking issue, `rustc` rustdoc page, or similar, that may provide
|
||||
further explanation for the change process or a way to verify that the information is not
|
||||
outdated.
|
||||
- If a text grows rather long (more than a few page scrolls) or complicated (more than four
|
||||
subsections) it might benefit from having a Table of Contents at the beginning, which you can
|
||||
auto-generate by including the `<!-- toc -->` marker.
|
||||
|
||||
[rdg]: https://rustc-dev-guide.rust-lang.org/
|
||||
[rdgrepo]: https://github.com/rust-lang/rustc-dev-guide
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Debugging support in the Rust compiler
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
This document explains the state of debugging tools support in the Rust compiler (rustc).
|
||||
The document gives an overview of debugging tools like GDB, LLDB etc. and infrastructure
|
||||
around Rust compiler to debug Rust code. If you want to learn how to debug the Rust compiler
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Errors and Lints
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
A lot of effort has been put into making `rustc` have great error messages.
|
||||
This chapter is about how to emit compile errors and lints from the compiler.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Getting Started
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
This documentation is _not_ intended to be comprehensive; it is meant to be a
|
||||
quick guide for the most useful things. For more information, [see this
|
||||
chapter on how to build and run the compiler](./building/how-to-build-and-run.md).
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Using Git
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
The Rust project uses [Git] to manage its source code. In order to
|
||||
contribute, you'll need some familiarity with its features so that your changes
|
||||
can be incorporated into the compiler.
|
||||
|
|
|
|||
10
src/hir.md
10
src/hir.md
|
|
@ -1,5 +1,7 @@
|
|||
# The HIR
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
The HIR – "High-Level Intermediate Representation" – is the primary IR used
|
||||
in most of rustc. It is a compiler-friendly representation of the abstract
|
||||
syntax tree (AST) that is generated after parsing, macro expansion, and name
|
||||
|
|
@ -18,7 +20,7 @@ You can view the HIR representation of your code by passing the
|
|||
cargo rustc -- -Z unpretty=hir-tree
|
||||
```
|
||||
|
||||
### Out-of-band storage and the `Crate` type
|
||||
## Out-of-band storage and the `Crate` type
|
||||
|
||||
The top-level data-structure in the HIR is the [`Crate`], which stores
|
||||
the contents of the crate currently being compiled (we only ever
|
||||
|
|
@ -66,7 +68,7 @@ the compiler a chance to observe that you accessed the data for
|
|||
|
||||
<a name="hir-id"></a>
|
||||
|
||||
### Identifiers in the HIR
|
||||
## Identifiers in the HIR
|
||||
|
||||
There are a bunch of different identifiers to refer to other nodes or definitions
|
||||
in the HIR. In short:
|
||||
|
|
@ -81,7 +83,7 @@ For more detailed information, check out the [chapter on identifiers][ids].
|
|||
[`HirId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir_id/struct.HirId.html
|
||||
[ids]: ./identifiers.md#in-the-hir
|
||||
|
||||
### The HIR Map
|
||||
## The HIR Map
|
||||
|
||||
Most of the time when you are working with the HIR, you will do so via
|
||||
the **HIR Map**, accessible in the tcx via [`tcx.hir()`] (and defined in
|
||||
|
|
@ -124,7 +126,7 @@ calls like [`tcx.hir().get_parent_node(n)`][get_parent_node].
|
|||
|
||||
[get_parent_node]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.get_parent_node
|
||||
|
||||
### HIR Bodies
|
||||
## HIR Bodies
|
||||
|
||||
A [`rustc_hir::Body`] represents some kind of executable code, such as the body
|
||||
of a function/closure or the definition of a constant. Bodies are
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# LLVM Source-Based Code Coverage
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
`rustc` supports detailed source-based code and test coverage analysis
|
||||
with a command line option (`-Z instrument-coverage`) that instruments Rust
|
||||
libraries and binaries with additional instructions and data, at compile time.
|
||||
|
|
@ -32,7 +34,7 @@ Detailed instructions and examples are documented in the
|
|||
[Coverage Map]: https://llvm.org/docs/CoverageMappingFormat.html
|
||||
[unstable-book-sbcc]: https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/source-based-code-coverage.html
|
||||
|
||||
### Rust symbol mangling
|
||||
## Rust symbol mangling
|
||||
|
||||
`-Z instrument-coverage` automatically enables Rust symbol mangling `v0` (as
|
||||
if the user specified `-Z symbol-mangling-version=v0` option when invoking
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Macro expansion
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
> `rustc_ast`, `rustc_expand`, and `rustc_builtin_macros` are all undergoing
|
||||
> refactoring, so some of the links in this chapter may be broken.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# THIR and MIR construction
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
The lowering of [HIR] to [MIR] occurs for the following (probably incomplete)
|
||||
list of items:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Dataflow Analysis
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
If you work on the MIR, you will frequently come across various flavors of
|
||||
[dataflow analysis][wiki]. `rustc` uses dataflow to find uninitialized
|
||||
variables, determine what variables are live across a generator `yield`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# The MIR (Mid-level IR)
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
MIR is Rust's _Mid-level Intermediate Representation_. It is
|
||||
constructed from [HIR](../hir.html). MIR was introduced in
|
||||
[RFC 1211]. It is a radically simplified form of Rust that is used for
|
||||
|
|
@ -228,7 +230,7 @@ but [you can read about those below](#promoted)).
|
|||
- **Statements** are represented by the type [`Statement`].
|
||||
- **Terminators** are represented by the [`Terminator`].
|
||||
- **Locals** are represented by a [newtype'd] index type [`Local`].
|
||||
The data for a local variable is found in the
|
||||
The data for a local variable is found in the
|
||||
[`Body::local_decls`][localdecls] vector). There is also a special constant
|
||||
[`RETURN_PLACE`] identifying the special "local" representing the return value.
|
||||
- **Places** are identified by the enum [`Place`]. There are a few
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Miri
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
Miri (**MIR** **I**nterpreter) is a virtual machine for executing MIR without
|
||||
compiling to machine code. It is usually invoked via `tcx.const_eval_*` functions.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Name resolution
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
In the previous chapters, we saw how the AST is built with all macros expanded.
|
||||
We saw how doing that requires doing some name resolution to resolve imports
|
||||
and macro names. In this chapter, we show how this is actually done and more.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Overview of the Compiler
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
This chapter is about the overall process of compiling a program -- how
|
||||
everything fits together.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
### Panicking in rust ###
|
||||
# Panicking in rust
|
||||
|
||||
#### Step 1: Invocation of the `panic!` macro.
|
||||
<!-- toc -->
|
||||
|
||||
## Step 1: Invocation of the `panic!` macro.
|
||||
|
||||
There are actually two panic macros - one defined in `core`, and one defined in `std`.
|
||||
This is due to the fact that code in `core` can panic. `core` is built before `std`,
|
||||
but we want panics to use the same machinery at runtime, whether they originate in `core`
|
||||
or `std`.
|
||||
|
||||
##### core definition of panic!
|
||||
### core definition of panic!
|
||||
|
||||
The `core` `panic!` macro eventually makes the following call (in `library/core/src/panicking.rs`):
|
||||
|
||||
|
|
@ -57,7 +59,7 @@ Rust source).
|
|||
Thus, control flow will pass from core to std at runtime. This allows panics from `core`
|
||||
to go through the same infrastructure that other panics use (panic hooks, unwinding, etc)
|
||||
|
||||
##### std implementation of panic!
|
||||
### std implementation of panic!
|
||||
|
||||
This is where the actual panic-related logic begins. In `library/std/src/panicking.rs`,
|
||||
control passes to `rust_panic_with_hook`. This method is responsible
|
||||
|
|
@ -83,7 +85,7 @@ is suitable for passing across an FFI boundary.
|
|||
|
||||
Finally, we call `__rust_start_panic` with this `usize`. We have now entered the panic runtime.
|
||||
|
||||
#### Step 2: The panic runtime
|
||||
## Step 2: The panic runtime
|
||||
|
||||
Rust provides two panic runtimes: `panic_abort` and `panic_unwind`. The user chooses
|
||||
between them at build time via their `Cargo.toml`
|
||||
|
|
@ -91,7 +93,7 @@ between them at build time via their `Cargo.toml`
|
|||
`panic_abort` is extremely simple: its implementation of `__rust_start_panic` just aborts,
|
||||
as you would expect.
|
||||
|
||||
`panic_unwind` is the more interesting case.
|
||||
`panic_unwind` is the more interesting case.
|
||||
|
||||
In its implementation of `__rust_start_panic`, we take the `usize`, convert
|
||||
it back to a `*mut &mut dyn BoxMeUp`, dereference it, and call `box_me_up`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Profile Guided Optimization
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
`rustc` supports doing profile-guided optimization (PGO).
|
||||
This chapter describes what PGO is and how the support for it is
|
||||
implemented in `rustc`.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Incremental Compilation In Detail
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
The incremental compilation scheme is, in essence, a surprisingly
|
||||
simple extension to the overall query system. It relies on the fact that:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Incremental compilation
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
The incremental compilation scheme is, in essence, a surprisingly
|
||||
simple extension to the overall query system. We'll start by describing
|
||||
a slightly simplified variant of the real thing – the "basic algorithm" –
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
# Profiling Queries
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
In an effort to support _incremental compilation_, the latest design of the Rust
|
||||
compiler consists of a _query-based_ model.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
|
||||
# The Query Evaluation Model in Detail
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
This chapter provides a deeper dive into the abstract model queries are built on.
|
||||
It does not go into implementation details but tries to explain
|
||||
the underlying logic. The examples here, therefore, have been stripped down and
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Rustdoc internals
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
This page describes rustdoc's passes and modes. For an overview of rustdoc,
|
||||
see [`rustdoc`](./rustdoc.md).
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# How Salsa works
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
This chapter is based on the explanation given by Niko Matsakis in this
|
||||
[video](https://www.youtube.com/watch?v=_muY4HjSqVw) about
|
||||
[Salsa](https://github.com/salsa-rs/salsa). To find out more you may
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Stability attributes
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
This section is about the stability attributes and schemes that allow stable
|
||||
APIs to use unstable APIs internally in the rustc standard library.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,9 @@
|
|||
|
||||
Once an unstable feature has been well-tested with no outstanding
|
||||
concern, anyone may push for its stabilization. It involves the
|
||||
following steps.
|
||||
following steps:
|
||||
|
||||
- Documentation PRs
|
||||
- Write a stabilization report
|
||||
- FCP
|
||||
- Stabilization PR
|
||||
<!-- toc -->
|
||||
|
||||
## Documentation PRs
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
### The `#[test]` attribute
|
||||
# The `#[test]` attribute
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
Today, rust programmers rely on a built in attribute called `#[test]`. All
|
||||
you have to do is mark a function as a test and include some asserts like so:
|
||||
|
||||
|
|
@ -35,7 +38,7 @@ What exactly is `rustc --test` doing?
|
|||
[`rustc_ast` crate][rustc_ast]. Essentially, it's a fancy macro, that
|
||||
rewrites the crate in 3 steps:
|
||||
|
||||
#### Step 1: Re-Exporting
|
||||
## Step 1: Re-Exporting
|
||||
|
||||
As mentioned earlier, tests can exist inside private modules, so we need a
|
||||
way of exposing them to the main function, without breaking any existing
|
||||
|
|
@ -77,7 +80,8 @@ hand-written one, it will not share a Symbol. This technique prevents name
|
|||
collision during code generation and is the foundation of Rust's macro
|
||||
hygiene.
|
||||
|
||||
#### Step 2: Harness Generation
|
||||
## Step 2: Harness Generation
|
||||
|
||||
Now that our tests are accessible from the root of our crate, we need to do
|
||||
something with them. `rustc_ast` generates a module like so:
|
||||
|
||||
|
|
@ -99,7 +103,8 @@ called [`test`][test] that is part of Rust core, that implements all of the
|
|||
runtime for testing. `test`'s interface is unstable, so the only stable way
|
||||
to interact with it is through the `#[test]` macro.
|
||||
|
||||
#### Step 3: Test Object Generation
|
||||
## Step 3: Test Object Generation
|
||||
|
||||
If you've written tests in Rust before, you may be familiar with some of the
|
||||
optional attributes available on test functions. For example, a test can be
|
||||
annotated with `#[should_panic]` if we expect the test to cause a panic. It
|
||||
|
|
@ -137,7 +142,8 @@ self::test::TestDescAndFn{
|
|||
Once we've constructed an array of these test objects, they're passed to the
|
||||
test runner via the harness generated in step 2.
|
||||
|
||||
### Inspecting the generated code
|
||||
## Inspecting the generated code
|
||||
|
||||
On nightly rust, there's an unstable flag called `unpretty` that you can use
|
||||
to print out the module source after macro expansion:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Adding new tests
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
**In general, we expect every PR that fixes a bug in rustc to come
|
||||
accompanied by a regression test of some kind.** This test should fail
|
||||
in master but pass after the PR. These tests are really useful for
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# The compiler testing framework
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
The Rust project runs a wide variety of different tests, orchestrated by
|
||||
the build system (`x.py test`). The main test harness for testing the
|
||||
compiler itself is a tool called compiletest (located in the
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Running tests
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
You can run the tests using `x.py`. The most basic command – which
|
||||
you will almost never want to use! – is as follows:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Goals and clauses
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
In logic programming terms, a **goal** is something that you must
|
||||
prove and a **clause** is something that you know is true. As
|
||||
described in the [lowering to logic](./lowering-to-logic.html)
|
||||
|
|
@ -196,7 +198,7 @@ it is okay to assume `FromEnv(T: Clone)` in the `loud_clone` example is that we
|
|||
_also_ verify `WellFormed(T: Clone)` for each call site of `loud_clone`.
|
||||
Similarly, it is okay to assume `FromEnv(HashSet<K>)` in the `loud_insert`
|
||||
example because we will verify `WellFormed(HashSet<K>)` for each call site of
|
||||
`loud_insert`.
|
||||
`loud_insert`.
|
||||
|
||||
#### Outlives(Type: Region), Outlives(Region: Region)
|
||||
e.g. `Outlives(&'a str: 'b)`, `Outlives('a: 'static)`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Lowering to logic
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
The key observation here is that the Rust trait system is basically a
|
||||
kind of logic, and it can be mapped onto standard logical inference
|
||||
rules. We can then look for solutions to those inference rules in a
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Trait resolution (old-style)
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
This chapter describes the general process of _trait resolution_ and points out
|
||||
some non-obvious things.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# The `ty` module: representing types
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
The `ty` module defines how the Rust compiler represents types internally. It also defines the
|
||||
*typing context* (`tcx` or `TyCtxt`), which is the central data structure in the compiler.
|
||||
|
||||
|
|
@ -189,7 +191,7 @@ There are many variants on the `TyKind` enum, which you can see by looking at it
|
|||
- [**Array**][kindarray] Corresponds to `[T; n]`.
|
||||
- [**RawPtr**][kindrawptr] Corresponds to `*mut T` or `*const T`.
|
||||
- [**Ref**][kindref] `Ref` stands for safe references, `&'a mut T` or `&'a T`. `Ref` has some
|
||||
associated parts, like `Ty<'tcx>` which is the type that the reference references.
|
||||
associated parts, like `Ty<'tcx>` which is the type that the reference references.
|
||||
`Region<'tcx>` is the lifetime or region of the reference and `Mutability` if the reference
|
||||
is mutable or not.
|
||||
- [**Param**][kindparam] Represents a type parameter (e.g. the `T` in `Vec<T>`).
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Type inference
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
Type inference is the process of automatic detection of the type of an
|
||||
expression.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Variance of type and lifetime parameters
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
For a more general background on variance, see the [background] appendix.
|
||||
|
||||
[background]: ./appendix/background.html
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# Walkthrough: a typical contribution
|
||||
|
||||
<!-- toc -->
|
||||
|
||||
There are _a lot_ of ways to contribute to the rust compiler, including fixing
|
||||
bugs, improving performance, helping design features, providing feedback on
|
||||
existing features, etc. This chapter does not claim to scratch the surface.
|
||||
|
|
|
|||
Loading…
Reference in New Issue