Plumb obligations through librustc/infer
Like #32542, but more like #31867.
TODO before merge: make an issue for the propagation of obligations through... uh, everywhere... then replace the `#????`s with the actual issue number.
cc @jroesch
r? @nikomatsakis
rBreak Critical Edges and other MIR work
This PR is built on top of #32080.
This adds the basic depth-first traversals for MIR, preorder, postorder and reverse postorder. The MIR blocks are now translated using reverse postorder. There is also a transform for breaking critical edges, which includes the edges from `invoke`d calls (`Drop` and `Call`), to account for the fact that we can't add code after an `invoke`. It also stops generating the intermediate block (since the transform essentially does it if necessary already).
The kinds of cases this deals with are difficult to produce, so the test is the one I managed to get. However, it seems to bootstrap with `-Z orbit`, which it didn't before my changes.
Also adds a new set of passes to run just before translation that
"prepare" the MIR for codegen. Removal of landing pads, region erasure
and break critical edges are run in this pass.
Also fixes some merge/rebase errors.
This is a fairly standard transform that inserts blocks along critical
edges so code can be inserted along the edge without it affecting other
edges. The main difference is that it considers a Drop or Call
terminator that would require an `invoke` instruction in LLVM a critical
edge. This is because we can't actually insert code after an invoke, so
it ends up looking similar to a critical edge anyway.
The transform is run just before translation right now.
Restrict constants in patterns
This implements [RFC 1445](https://github.com/rust-lang/rfcs/blob/master/text/1445-restrict-constants-in-patterns.md). The primary change is to limit the types of constants used in patterns to those that *derive* `Eq` (note that implementing `Eq` is not sufficient). This has two main effects:
1. Floating point constants are linted, and will eventually be disallowed. This is because floating point constants do not implement `Eq` but only `PartialEq`. This check replaces the existing special case code that aimed to detect the use of `NaN`.
2. Structs and enums must derive `Eq` to be usable within a match.
This is a [breaking-change]: if you encounter a problem, you are most likely using a constant in an expression where the type of the constant is some struct that does not currently implement
`Eq`. Something like the following:
```rust
struct SomeType { ... }
const SOME_CONST: SomeType = ...;
match foo {
SOME_CONST => ...
}
```
The easiest and most future compatible fix is to annotate the type in question with `#[derive(Eq)]` (note that merely *implementing* `Eq` is not enough, it must be *derived*):
```rust
struct SomeType { ... }
const SOME_CONST: SomeType = ...;
match foo {
SOME_CONST => ...
}
```
Another good option is to rewrite the match arm to use an `if` condition (this is also particularly good for floating point types, which implement `PartialEq` but not `Eq`):
```rust
match foo {
c if c == SOME_CONST => ...
}
```
Finally, a third alternative is to tag the type with `#[structural_match]`; but this is not recommended, as the attribute is never expected to be stabilized. Please see RFC #1445 for more details.
cc https://github.com/rust-lang/rust/issues/31434
r? @pnkfelix
This is a [breaking-change]: according to RFC #1445, constants used as
patterns must be of a type that *derives* `Eq`. If you encounter a
problem, you are most likely using a constant in an expression where the
type of the constant is some struct that does not currently implement
`Eq`. Something like the following:
```rust
struct SomeType { ... }
const SOME_CONST: SomeType = ...;
match foo {
SOME_CONST => ...
}
```
The easiest and most future compatible fix is to annotate the type in
question with `#[derive(Eq)]` (note that merely *implementing* `Eq` is
not enough, it must be *derived*):
```rust
struct SomeType { ... }
const SOME_CONST: SomeType = ...;
match foo {
SOME_CONST => ...
}
```
Another good option is to rewrite the match arm to use an `if`
condition (this is also particularly good for floating point types,
which implement `PartialEq` but not `Eq`):
```rust
match foo {
c if c == SOME_CONST => ...
}
```
Finally, a third alternative is to tag the type with
`#[structural_match]`; but this is not recommended, as the attribute is
never expected to be stabilized. Please see RFC #1445 for more details.
while I'm at it, remove the "extra caching" that I was doing for no good
reason except laziness. Basically before I was caching at each scope in
the chain, but there's not really a reason to do that, since the cached
entry point at level N is always equal to the last cached exit point
from level N-1.
It's nice to be able to index with a scope-id,
but coherence rules prevent us from implementing
`Index<ScopeId>` for `Vec<ScopeAuxiliary>`, and I'd
prefer that `ScopeAuxiliary` remain in librustc_mir,
just for compilation time reasons.
This was triggered by me wanting to address a use of DUMMY_SP, but
actually I'm not sure what would be a better span -- I guess the span
for the function as a whole.
Automated conversion using the untry tool [1] and the following command:
```
$ find -name '*.rs' -type f | xargs untry
```
at the root of the Rust repo.
[1]: https://github.com/japaric/untry
emit (via debug!) scary message from `fn borrowck_mir` until basic
prototype is in place.
Gather children of move paths and set their kill bits in
dataflow. (Each node has a link to the child that is first among its
siblings.)
Hooked in libgraphviz based rendering, including of borrowck dataflow
state.
doing this well required some refactoring of the code, so I cleaned it
up more generally (adding comments to explain what its trying to do
and how it is doing it).
Update: this newer version addresses most review comments (at least
the ones that were largely mechanical changes), but I left the more
interesting revisions to separate followup commits (in this same PR).