More long lines
This commit is contained in:
parent
42ef2ad0b8
commit
2bb61a3f59
|
|
@ -69,11 +69,11 @@ want the `TypeckTables` node for some particular fn, so you might write:
|
||||||
RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar'
|
RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar'
|
||||||
```
|
```
|
||||||
|
|
||||||
This will select only the predecessors of `TypeckTables` nodes for functions with
|
This will select only the predecessors of `TypeckTables` nodes for functions
|
||||||
`bar` in their name.
|
with `bar` in their name.
|
||||||
|
|
||||||
Perhaps you are finding that when you change `foo` you need to re-type-check `bar`,
|
Perhaps you are finding that when you change `foo` you need to re-type-check
|
||||||
but you don't think you should have to. In that case, you might do:
|
`bar`, but you don't think you should have to. In that case, you might do:
|
||||||
|
|
||||||
```
|
```
|
||||||
RUST_DEP_GRAPH_FILTER='Hir & foo -> TypeckTables & bar'
|
RUST_DEP_GRAPH_FILTER='Hir & foo -> TypeckTables & bar'
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ enforcing a number of properties:
|
||||||
- That all variables are initialized before they are used.
|
- That all variables are initialized before they are used.
|
||||||
- That you can't move the same value twice.
|
- That you can't move the same value twice.
|
||||||
- That you can't move a value while it is borrowed.
|
- That you can't move a value while it is borrowed.
|
||||||
- That you can't access a place while it is mutably borrowed (except through the reference).
|
- That you can't access a place while it is mutably borrowed (except through
|
||||||
|
the reference).
|
||||||
- That you can't mutate a place while it is shared borrowed.
|
- That you can't mutate a place while it is shared borrowed.
|
||||||
- etc
|
- etc
|
||||||
|
|
||||||
|
|
@ -44,10 +45,12 @@ The overall flow of the borrow checker is as follows:
|
||||||
Among other things, this function will replace all of the regions in
|
Among other things, this function will replace all of the regions in
|
||||||
the MIR with fresh [inference variables](./appendix-glossary.html).
|
the MIR with fresh [inference variables](./appendix-glossary.html).
|
||||||
- (More details can be found in [the regionck section](./mir-regionck.html).)
|
- (More details can be found in [the regionck section](./mir-regionck.html).)
|
||||||
- Next, we perform a number of [dataflow analyses](./appendix-background.html#dataflow)
|
- Next, we perform a number of [dataflow
|
||||||
|
analyses](./appendix-background.html#dataflow)
|
||||||
that compute what data is moved and when. The results of these analyses
|
that compute what data is moved and when. The results of these analyses
|
||||||
are needed to do both borrow checking and region inference.
|
are needed to do both borrow checking and region inference.
|
||||||
- Using the move data, we can then compute the values of all the regions in the MIR.
|
- Using the move data, we can then compute the values of all the regions in the
|
||||||
|
MIR.
|
||||||
- (More details can be found in [the NLL section](./mir-regionck.html).)
|
- (More details can be found in [the NLL section](./mir-regionck.html).)
|
||||||
- Finally, the borrow checker itself runs, taking as input (a) the
|
- Finally, the borrow checker itself runs, taking as input (a) the
|
||||||
results of move analysis and (b) the regions computed by the region
|
results of move analysis and (b) the regions computed by the region
|
||||||
|
|
|
||||||
|
|
@ -15,16 +15,19 @@ transformations. These suites represent useful intermediate points
|
||||||
where we want to access the MIR for type checking or other purposes:
|
where we want to access the MIR for type checking or other purposes:
|
||||||
|
|
||||||
- `mir_build(D)` – not a query, but this constructs the initial MIR
|
- `mir_build(D)` – not a query, but this constructs the initial MIR
|
||||||
- `mir_const(D)` – applies some simple transformations to make MIR ready for constant evaluation;
|
- `mir_const(D)` – applies some simple transformations to make MIR ready for
|
||||||
- `mir_validated(D)` – applies some more transformations, making MIR ready for borrow checking;
|
constant evaluation;
|
||||||
- `optimized_mir(D)` – the final state, after all optimizations have been performed.
|
- `mir_validated(D)` – applies some more transformations, making MIR ready for
|
||||||
|
borrow checking;
|
||||||
|
- `optimized_mir(D)` – the final state, after all optimizations have been
|
||||||
|
performed.
|
||||||
|
|
||||||
### Seeing how the MIR changes as the compiler executes
|
### Seeing how the MIR changes as the compiler executes
|
||||||
|
|
||||||
`-Zdump-mir=F` is a handy compiler options that will let you view the MIR
|
`-Zdump-mir=F` is a handy compiler options that will let you view the MIR for
|
||||||
for each function at each stage of compilation. `-Zdump-mir` takes a **filter**
|
each function at each stage of compilation. `-Zdump-mir` takes a **filter** `F`
|
||||||
`F` which allows you to control which functions and which passes you are interesting
|
which allows you to control which functions and which passes you are
|
||||||
in. For example:
|
interesting in. For example:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
> rustc -Zdump-mir=foo ...
|
> rustc -Zdump-mir=foo ...
|
||||||
|
|
@ -58,8 +61,9 @@ rustc.main.000-000.CleanEndRegions.after.mir
|
||||||
def-path to the function etc being dumped
|
def-path to the function etc being dumped
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also make more selective filters. For example, `main & CleanEndRegions` will select
|
You can also make more selective filters. For example, `main & CleanEndRegions`
|
||||||
for things that reference *both* `main` and the pass `CleanEndRegions`:
|
will select for things that reference *both* `main` and the pass
|
||||||
|
`CleanEndRegions`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
> rustc -Zdump-mir='main & CleanEndRegions' foo.rs
|
> rustc -Zdump-mir='main & CleanEndRegions' foo.rs
|
||||||
|
|
|
||||||
|
|
@ -418,16 +418,15 @@ variable `'?3`, but the variable `'?3` is not forced to outlive
|
||||||
anything else. Therefore, it simply starts and ends as the empty set
|
anything else. Therefore, it simply starts and ends as the empty set
|
||||||
of elements, and hence the type-check succeeds here.
|
of elements, and hence the type-check succeeds here.
|
||||||
|
|
||||||
(This should surprise you a little. It surprised me when I first
|
(This should surprise you a little. It surprised me when I first realized it.
|
||||||
realized it. We are saying that if we are a fn that **needs both of
|
We are saying that if we are a fn that **needs both of its arguments to have
|
||||||
its arguments to have the same region**, we can accept being called
|
the same region**, we can accept being called with **arguments with two
|
||||||
with **arguments with two distinct regions**. That seems intuitively
|
distinct regions**. That seems intuitively unsound. But in fact, it's fine, as
|
||||||
unsound. But in fact, it's fine, as I
|
I tried to explain in [this issue][ohdeargoditsallbroken] on the Rust issue
|
||||||
[tried to explain in this issue on the Rust issue tracker long ago][ohdeargoditsallbroken].
|
tracker long ago. The reason is that even if we get called with arguments of
|
||||||
The reason is that even if we get called with arguments of two
|
two distinct lifetimes, those two lifetimes have some intersection (the call
|
||||||
distinct lifetimes, those two lifetimes have some intersection (the
|
itself), and that intersection can be our value of `'a` that we use as the
|
||||||
call itself), and that intersection can be our value of `'a` that we
|
common lifetime of our arguments. -nmatsakis)
|
||||||
use as the common lifetime of our arguments. -nmatsakis)
|
|
||||||
|
|
||||||
[ohdeargoditsallbroken]: https://github.com/rust-lang/rust/issues/32330#issuecomment-202536977
|
[ohdeargoditsallbroken]: https://github.com/rust-lang/rust/issues/32330#issuecomment-202536977
|
||||||
|
|
||||||
|
|
@ -440,10 +439,10 @@ a return type:
|
||||||
<:
|
<:
|
||||||
for<'b, 'c> fn(&'b u32, &'c u32) -> &'b u32
|
for<'b, 'c> fn(&'b u32, &'c u32) -> &'b u32
|
||||||
|
|
||||||
Despite seeming very similar to the previous example, this case is
|
Despite seeming very similar to the previous example, this case is going to get
|
||||||
going to get an error. That's good: the problem is that we've gone
|
an error. That's good: the problem is that we've gone from a fn that promises
|
||||||
from a fn that promises to return one of its two arguments, to a fn
|
to return one of its two arguments, to a fn that is promising to return the
|
||||||
that is promising to return the first one. That is unsound. Let's see how it plays out.
|
first one. That is unsound. Let's see how it plays out.
|
||||||
|
|
||||||
First, we skolemize the supertype:
|
First, we skolemize the supertype:
|
||||||
|
|
||||||
|
|
@ -463,8 +462,8 @@ And now we create the subtyping relationships:
|
||||||
&'!2 u32 <: &'?3 u32 // arg 2
|
&'!2 u32 <: &'?3 u32 // arg 2
|
||||||
&'?3 u32 <: &'!1 u32 // return type
|
&'?3 u32 <: &'!1 u32 // return type
|
||||||
|
|
||||||
And finally the outlives relationships. Here, let V1, V2, and V3 be the variables
|
And finally the outlives relationships. Here, let V1, V2, and V3 be the
|
||||||
we assign to `!1`, `!2`, and `?3` respectively:
|
variables we assign to `!1`, `!2`, and `?3` respectively:
|
||||||
|
|
||||||
V1: V3
|
V1: V3
|
||||||
V2: V3
|
V2: V3
|
||||||
|
|
@ -476,8 +475,8 @@ Those variables will have these initial values:
|
||||||
V2 in U2 = {skol(2)}
|
V2 in U2 = {skol(2)}
|
||||||
V3 in U2 = {}
|
V3 in U2 = {}
|
||||||
|
|
||||||
Now because of the `V3: V1` constraint, we have to add `skol(1)` into `V3` (and indeed
|
Now because of the `V3: V1` constraint, we have to add `skol(1)` into `V3` (and
|
||||||
it is visible from `V3`), so we get:
|
indeed it is visible from `V3`), so we get:
|
||||||
|
|
||||||
V3 in U2 = {skol(1)}
|
V3 in U2 = {skol(1)}
|
||||||
|
|
||||||
|
|
|
||||||
25
src/mir.md
25
src/mir.md
|
|
@ -34,14 +34,17 @@ This section introduces the key concepts of MIR, summarized here:
|
||||||
|
|
||||||
- **Basic blocks**: units of the control-flow graph, consisting of:
|
- **Basic blocks**: units of the control-flow graph, consisting of:
|
||||||
- **statements:** actions with one successor
|
- **statements:** actions with one successor
|
||||||
- **terminators:** actions with potentially multiple successors; always at the end of a block
|
- **terminators:** actions with potentially multiple successors; always at
|
||||||
- (if you're not familiar with the term *basic block*, see the [background chapter][cfg])
|
the end of a block
|
||||||
|
- (if you're not familiar with the term *basic block*, see the [background
|
||||||
|
chapter][cfg])
|
||||||
- **Locals:** Memory locations alloated on the stack (conceptually, at
|
- **Locals:** Memory locations alloated on the stack (conceptually, at
|
||||||
least), such as function arguments, local variables, and
|
least), such as function arguments, local variables, and
|
||||||
temporaries. These are identified by an index, written with a
|
temporaries. These are identified by an index, written with a
|
||||||
leading underscore, like `_1`. There is also a special "local"
|
leading underscore, like `_1`. There is also a special "local"
|
||||||
(`_0`) allocated to store the return value.
|
(`_0`) allocated to store the return value.
|
||||||
- **Places:** expressions that identify a location in memory, like `_1` or `_1.f`.
|
- **Places:** expressions that identify a location in memory, like `_1` or
|
||||||
|
`_1.f`.
|
||||||
- **Rvalues:** expressions that produce a value. The "R" stands for
|
- **Rvalues:** expressions that produce a value. The "R" stands for
|
||||||
the fact that these are the "right-hand side" of an assignment.
|
the fact that these are the "right-hand side" of an assignment.
|
||||||
- **Operands:** the arguments to an rvalue, which can either be a
|
- **Operands:** the arguments to an rvalue, which can either be a
|
||||||
|
|
@ -100,8 +103,9 @@ you their original name (`// "vec" in scope 1...`). The "scope" blocks
|
||||||
(e.g., `scope 1 { .. }`) describe the lexical structure of the source
|
(e.g., `scope 1 { .. }`) describe the lexical structure of the source
|
||||||
program (which names were in scope when).
|
program (which names were in scope when).
|
||||||
|
|
||||||
**Basic blocks.** Reading further, we see our first **basic block** (naturally it may look
|
**Basic blocks.** Reading further, we see our first **basic block** (naturally
|
||||||
slightly different when you view it, and I am ignoring some of the comments):
|
it may look slightly different when you view it, and I am ignoring some of the
|
||||||
|
comments):
|
||||||
|
|
||||||
```
|
```
|
||||||
bb0: {
|
bb0: {
|
||||||
|
|
@ -110,8 +114,8 @@ bb0: {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
A basic block is defined by a series of **statements** and a final **terminator**.
|
A basic block is defined by a series of **statements** and a final
|
||||||
In this case, there is one statement:
|
**terminator**. In this case, there is one statement:
|
||||||
|
|
||||||
```
|
```
|
||||||
StorageLive(_1);
|
StorageLive(_1);
|
||||||
|
|
@ -146,8 +150,8 @@ bb2: {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Here there are two statements: another `StorageLive`, introducing the `_3` temporary,
|
Here there are two statements: another `StorageLive`, introducing the `_3`
|
||||||
and then an assignment:
|
temporary, and then an assignment:
|
||||||
|
|
||||||
```
|
```
|
||||||
_3 = &mut _1;
|
_3 = &mut _1;
|
||||||
|
|
@ -189,7 +193,8 @@ TMP1 = a + b
|
||||||
x = TMP1 + c
|
x = TMP1 + c
|
||||||
```
|
```
|
||||||
|
|
||||||
([Try it and see, though you may want to do release mode to skip over the overflow checks.][play-abc])
|
([Try it and see][play-abc], though you may want to do release mode to skip
|
||||||
|
over the overflow checks.)
|
||||||
|
|
||||||
[play-abc]: https://play.rust-lang.org/?gist=1751196d63b2a71f8208119e59d8a5b6&version=stable
|
[play-abc]: https://play.rust-lang.org/?gist=1751196d63b2a71f8208119e59d8a5b6&version=stable
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue