Implement the `!` type
This implements the never type (`!`) and hides it behind the feature gate `#[feature(never_type)]`. With the feature gate off, things should build as normal (although some error messages may be different). With the gate on, `!` is usable as a type and diverging type variables (ie. types that are unconstrained by anything in the code) will default to `!` instead of `()`.
refactor lvalue_ty to be method of lvalue
Currently `Mir` (and `MirContext`) implement a method `lvalue_ty` (and actually many more `foo_ty`). But this should be a method of `Lvalue`.
If you have an `lvalue` and you want to get its type, the natural thing to write is:
```
lvalue.ty()
```
Of course it needs context, but still:
```
lvalue.ty(mir, tcx)
```
Makes more sense than
```
mir.lvalue_ty(lvalue, tcx)
```
I actually think we should go a step farther and have traits so we could get the type of some value generically, but that's up for debate. The thing I'm running into a lot in the compiler is I have a value of type `Foo` and I know that there is some related type `Bar` which I can get through some combination of method calls, but it's often not as direct as I would imagine. Unless you already know the code, its not clear why you would look in `Mir` for a method to get the type of an `Lvalue`.
Per the discussion on #34765, we make one `DepNode::Mir` variant and use
it to represent both the MIR tracking map as well as passes that operate
on MIR. We also track loads of cached MIR (which naturally comes from
metadata).
Note that the "HAIR" pass adds a read of TypeckItemBody because it uses
a myriad of tables that are not individually tracked.
Batch up libsyntax breaking changes
Batch of the following syntax-[breaking-change] changes:
- #34213: Add a variant `Macro` to `TraitItemKind`
- #34368: Merge the variant `QPath` of `PatKind` into the variant `PatKind::Path`
- #34385: Move `syntax::ast::TokenTree` into a new module `syntax::tokenstream`
- #33943:
- Remove the type parameter from `visit::Visitor`
- Remove `attr::WithAttrs` -- use `attr::HasAttrs` instead.
- Change `fold_tt`/`fold_tts` to take token trees by value and avoid wrapping token trees in `Rc`.
- Remove the field `ctxt` of `ast::Mac_`
- Remove inherent method `attrs()` of types -- use the method `attrs` of `HasAttrs` instead.
- #34316:
- Remove `ast::Decl`/`ast::DeclKind` and add variants `Local` and `Item` to `StmtKind`.
- Move the node id for statements from the `StmtKind` variants to a field of `Stmt` (making `Stmt` a struct instead of an alias for `Spanned<StmtKind>`)
- Rename `ast::ExprKind::Again` to `Continue`.
- #34339: Generalize and abstract `ThinAttributes` to `ThinVec<Attribute>`
- Use `.into()` in convert between `Vec<Attribute>` and `ThinVec<Attribute>`
- Use autoderef instead of `.as_attr_slice()`
- #34436: Remove the optional expression from `ast::Block` and instead use a `StmtKind::Expr` at the end of the statement list.
- #34403: Move errors into a separate crate (unlikely to cause breakage)
Use it instead of a `panic` for inexhaustive matches and correct the
comment. I think we trust our match-generation algorithm enough to
generate these blocks, and not generating an `unreachable` means that
LLVM won't optimize `match void() {}` to an `unreachable`.
this introduces a DropAndReplace terminator as a fix to #30380. That terminator
is suppsoed to be translated by desugaring during drop elaboration, which is
not implemented in this commit, so this breaks `-Z orbit` temporarily.
Incorporates many fixes contributed by arielb1.
----
revise borrowck::mir::dataflow code to allow varying domain for bitvectors.
This particular code implements the `BitDenotation` trait for three
analyses:
* `MovingOutStatements`, which, like `borrowck::move_data`, maps each
bit-index to a move instruction, and a 1 means "the effect of this
move reaches this point" (and the assigned l-value, if a scoped
declaration, is still in scope).
* `MaybeInitializedLvals`, which maps each bit-index to an l-value.
A 1 means "there exists a control flow path to this point that
initializes the associated l-value."
* `MaybeUninitializedLvals`, which maps each bit-index to an l-value
A 1 means "there exists a control flow path to this point that
de-initializes the associated l-value."
----
Revised `graphviz` dataflow-rendering support in `borrowck::mir`.
One big difference is that this code is now parameterized over the
`BitDenotation`, so that it can be used to render dataflow results
independent of how the dataflow bitvectors are interpreted; see where
reference to `MoveOut` is replaced by the type parameter `D`.
----
Factor out routine to query subattributes in `#[rustc_mir(..)]`.
(Later commits build upon this for some unit testing and instrumentation.)
----
thread through a tcx so that I can query types of lvalues as part of analysis.
----
Revised `BitDenotation::Ctxt`, allowing variation beyond `MoveData`.
The main motivation is to ease threading through a `TyCtxt`.
(In hindsight it might have been better to instead attach the `TyCtxt`
to each of the different dataflow implementations, but that would
require e.g. switching away from having a `Default` impl, so I am
leaving that experiment for another time.)
MIR: Do not require END_BLOCK to always exist
Basically, all this does, is removing restriction for END_BLOCK to exist past the first invocation of RemoveDeadBlocks pass. This way for functions whose CFG does not reach the `END_BLOCK` end up not containing the block.
As far as the implementation goes, I’m not entirely satisfied with the `BasicBlock::end_block`. I had hoped to make `new` a `const fn` and then just have a `const END_BLOCK` private to mir::build, but it turns out that constant functions don’t yet support conditionals nor a way to assert.
Once upon a time, along with START_BLOCK and END_BLOCK in the castle of important blocks also lived
a RESUME_BLOCK (or was it UNWIND_BLOCK? Either works, I don’t remember anymore). This trinity of
important blocks were required to always exist from the birth to death of the MIR-land they
belonged to.
Some time later, it was discovered that RESUME_BLOCK was just a lazy goon enjoying comfortable life
in the light of fame of the other two. Needless to say, once found out, the RESUME_BLOCK was
quickly slain and disposed of.
Now, the all-seeing eye of ours discovers that END_BLOCK is actually the more evil and better
disguised twin of the slain RESUME_BLOCK. Thus END_BLOCK gets slain and quickly disposed
of. Glory to the START_BLOCK, one and only lord of the important blocks’ castle!
---
Basically, all this does, is removing restriction for END_BLOCK to exist past the first invocation
of RemoveDeadBlocks pass. This way for functions whose CFG does not reach the `END_BLOCK` end up
not containing the block.
As far as the implementation goes, I’m not entirely satisfied with the `BasicBlock::end_block`, I
had hoped to make `new` a `const fn` and then just have a `const END_BLOCK` private to mir::build,
but it turns out that constant functions don’t yet support conditionals nor a way to assert.
Handle operand temps for function calls
Previously, all non-void function returns required an on-stack location for the value to be stored to. This code improves translation of function calls so this is no longer necessary.