New attribute parsing infrastructure
Another step in the plan outlined in https://github.com/rust-lang/rust/issues/131229
introduces infrastructure for structured parsers for attributes, as well as converting a couple of complex attributes to have such structured parsers.
This PR may prove too large to review. I left some of my own comments to guide it a little. Some general notes:
- The first commit is basically standalone. It just preps some mostly unrelated sources for the rest of the PR to work. It might not have enormous merit on its own, but not negative merit either. Could be merged alone, but also doesn't make the review a whole lot easier. (but it's only +274 -209)
- The second commit is the one that introduces new infrastructure. It's the important one to review.
- The 3rd commit uses the new infrastructure showing how some of the more complex attributes can be parsed using it. Theoretically can be split up, though the parsers in this commit are the ones that really test the new infrastructure and show that it all works.
- The 4th commit fixes up rustdoc and clippy. In the previous 2 they didn't compile yet while the compiler does. Separated them out to separate concerns and make the rest more palatable.
- The 5th commit blesses some test outputs. Sometimes that's just because a diagnostic happens slightly earlier than before, which I'd say is acceptable. Sometimes a diagnostic is now only emitted once where it would've been twice before (yay! fixed some bugs). One test I actually moved from crashes to fixed, because it simply doesn't crash anymore. That's why this PR Closes#132391. I think most choices I made here are generally reasonable, but let me know if you disagree anywhere.
- The 6th commit adds a derive to pretty print attributes
- The 7th removes smir apis for attributes, for the time being. The api will at some point be replaced by one based on `rustc_ast_data_structures::AttributeKind`
In general, a lot of the additions here are comments. I've found it very important to document new things in the 2nd commit well so other people can start using it.
Closes#132391Closes#136717
Allow `IndexSlice` to be indexed by ranges.
This comes with some annoyances as the index type can no longer inferred from indexing expressions. The biggest offender for this is `IndexVec::from_fn_n(|idx| ..., n)` where the index type won't be inferred from the call site or any index expressions inside the closure.
My main use case for this is mapping a `Place` to `Range<Idx>` for value tracking where the range represents all the values the place contains.
FIx `sym` -> `syn` typo in tail-expr-drop-order type opt-out
The #131326 PR attempts to reduce some false positives for the `tail_expr_drop_order` lint by hard-coding some common ecosystem crate names. Specifically, I believe it attempts to opt out the drop impls from `syn` which only exist as optimizations.
However, this was typo'd like "sym", which is a crate that has been [yanked](https://crates.io/crates/sym) (lol). This PR fixes that.
cc `@dingxiangfei2009` `@nikomatsakis` -- did I mistake this? Was this meant to be a different crate?
`@bors` rollup
coverage: Get hole spans from nested items without fully visiting them
This is a small simplification to the code that collects the spans of nested items within a function, so that those spans can be treated as “holes” to be avoided by the current function's coverage mappings.
The old code was using `nested_filter::All` to ensure that the visitor would see nested items. But we don't need the actual items themselves; we just need their spans, which we can obtain via a custom implementation of `visit_nested_item`.
This avoids the more expansive queries required by `nested_filter::All`.
Emit dropck normalization errors in borrowck
Borrowck generally assumes that any queries it runs for type checking will succeed, thinking that HIR typeck will have errored first if there was a problem. However as of #98641, dropck isn't run on HIR, so there's no direct guarantee that it doesn't error. While a type being well-formed might be expected to ensure that its fields are well-formed, this is not the case for types containing a type projection:
```rust
pub trait AuthUser {
type Id;
}
pub trait AuthnBackend {
type User: AuthUser;
}
pub struct AuthSession<Backend: AuthnBackend> {
data: Option<<<Backend as AuthnBackend>::User as AuthUser>::Id>,
}
pub trait Authz: Sized {
type AuthnBackend: AuthnBackend<User = Self>;
}
pub fn run_query<User: Authz>(auth: AuthSession<User::AuthnBackend>) {}
// ^ No User: AuthUser bound is required or inferred.
```
While improvements to trait solving might fix this in the future, for now we go for a pragmatic solution of emitting an error from borrowck (by rerunning dropck outside of a query) and making drop elaboration check if an error has been emitted previously before panicking for a failed normalization.
Closes#103899Closes#135039
r? `@compiler-errors` (feel free to re-assign)
It turns out that this visitor doesn't actually need `nested_filter::All` to
handle nested items; it just needs to override `visit_nested_item` and look up
the item's span.
Remove `rustc_middle::mir::tcx` module.
This is a really weird module. For example, what does `tcx` in `rustc_middle::mir::tcx::PlaceTy` mean? The answer is "not much".
The top-level module comment says:
> Methods for the various MIR types. These are intended for use after
> building is complete.
Awfully broad for a module that has a handful of impl blocks for some MIR types, none of which really relates to `TyCtxt`. `git blame` indicates the comment is ancient, from 2015, and made sense then.
This module is now vestigial. This commit removes it and moves all the code within into `rustc_middle::mir::statement`. Some specifics:
- `Place`, `PlaceRef`, `Rvalue`, `Operand`, `BorrowKind`: they all have `impl` blocks in both the `tcx` and `statement` modules. The commit merges the former into the latter.
- `BinOp`, `UnOp`: they only have `impl` blocks in `tcx`. The commit moves these into `statement`.
- `PlaceTy`, `RvalueInitializationState`: they are defined in `tcx`. This commit moves them into `statement` *and* makes them available in `mir::*`, like many other MIR types.
r? `@tmandry`
This is a really weird module. For example, what does `tcx` in
`rustc_middle::mir::tcx::PlaceTy` mean? The answer is "not much".
The top-level module comment says:
> Methods for the various MIR types. These are intended for use after
> building is complete.
Awfully broad for a module that has a handful of impl blocks for some
MIR types, none of which really relates to `TyCtxt`. `git blame`
indicates the comment is ancient, from 2015, and made sense then.
This module is now vestigial. This commit removes it and moves all the
code within into `rustc_middle::mir::statement`. Some specifics:
- `Place`, `PlaceRef`, `Rvalue`, `Operand`, `BorrowKind`: they all have `impl`
blocks in both the `tcx` and `statement` modules. The commit merges
the former into the latter.
- `BinOp`, `UnOp`: they only have `impl` blocks in `tcx`. The commit
moves these into `statement`.
- `PlaceTy`, `RvalueInitializationState`: they are defined in `tcx`.
This commit moves them into `statement` *and* makes them available in
`mir::*`, like many other MIR types.
It's currently lacking comments. This commit adds some, which is useful
because there are some methods with non-obvious behaviour.
The commit also renames two things:
- `patch_map` becomes `term_patch_map`, because it's only about
terminators.
- `is_patched` becomes `is_term_patched`, for the same reason.
(I would guess that originally `MirPatch` only handled terminators, and
then over time it expanded to allow other modifications, but these names
weren't updated.)
Instead of `expand_statements`. This makes the code shorter and
consistent with other MIR transform passes.
The tests require updating because there is a slight change in
MIR output:
- the old code replaced the original statement with twelve new
statements.
- the new code inserts converts the original statement to a `nop` and
then insert twelve new statements in front of it.
I.e. we now end up with an extra `nop`, which doesn't matter at all.
Continuing the work started in #136466.
Every method gains a `hir_` prefix, though for the ones that already
have a `par_` or `try_par_` prefix I added the `hir_` after that.
Drop elaboration looks at fields of a type, which may error when we try
to normalize them. Borrowck will have detected this if HIR typeck
didn't, but we don't delete the MIR body for errors in borrowck so
still have to handle this happening in drop elaboration by checking
whether an error has been emitted.
Start removing `rustc_middle::hir::map::Map`
`rustc_middle::hir::map::Map` is now just a low-value wrapper around `TyCtxt`. This PR starts removing it.
r? `@cjgillot`
First of all, note that `Map` has three different relevant meanings.
- The `intravisit::Map` trait.
- The `map::Map` struct.
- The `NestedFilter::Map` associated type.
The `intravisit::Map` trait is impl'd twice.
- For `!`, where the methods are all unreachable.
- For `map::Map`, which gets HIR stuff from the `TyCtxt`.
As part of getting rid of `map::Map`, this commit changes `impl
intravisit::Map for map::Map` to `impl intravisit::Map for TyCtxt`. It's
fairly straightforward except various things are renamed, because the
existing names would no longer have made sense.
- `trait intravisit::Map` becomes `trait intravisit::HirTyCtxt`, so named
because it gets some HIR stuff from a `TyCtxt`.
- `NestedFilter::Map` assoc type becomes `NestedFilter::MaybeTyCtxt`,
because it's always `!` or `TyCtxt`.
- `Visitor::nested_visit_map` becomes `Visitor::maybe_tcx`.
I deliberately made the new trait and associated type names different to
avoid the old `type Map: Map` situation, which I found confusing. We now
have `type MaybeTyCtxt: HirTyCtxt`.
The end goal is to eliminate `Map` altogether.
I added a `hir_` prefix to all of them, that seemed simplest. The
exceptions are `module_items` which became `hir_module_free_items` because
there was already a `hir_module_items`, and `items` which became
`hir_free_items` for consistency with `hir_module_free_items`.
Move code into `rustc_mir_transform`
I found two modules in other crates that are better placed in `rustc_mir_transform`, because that's the only crate that uses them.
r? ``@matthewjasper``
Because it's only used in `rustc_mir_transform`. (Presumably it is
currently in `rustc_middle` because lots of other MIR-related stuff is,
but that's not a hard requirement.) And because `rustc_middle` is huge
and it's always good to make it smaller.
`rustc_mir_dataflow/src/elaborate_drops.rs` contains some infrastructure
used by a few MIR passes: the `elaborate_drop` function, the
`DropElaborator` trait, etc.
`rustc_mir_transform/src/elaborate_drops.rs` (same file name, different
crate) contains the `ElaborateDrops` pass. It relies on a lot of the
infrastructure from `rustc_mir_dataflow/src/elaborate_drops.rs`.
It turns out that the drop infrastructure is only used in
`rustc_mir_transform`, so this commit moves it there. (The only
exception is the small `DropFlagState` type, which is moved to the
existing `rustc_mir_dataflow/src/drop_flag_effects.rs`.) The file is
renamed from `rustc_mir_dataflow/src/elaborate_drops.rs` to
`rustc_mir_transform/src/elaborate_drop.rs` (with no trailing `s`)
because (a) the `elaborate_drop` function is the most important export,
and (b) `rustc_mir_transform/src/elaborate_drops.rs` already exists.
All the infrastructure pieces that used to be `pub` are now
`pub(crate)`, because they are now only used within
`rustc_mir_transform`.
coverage: Eliminate more counters by giving them to unreachable nodes
When preparing a function's coverage counters and metadata during codegen, any part of the original coverage graph that was removed by MIR optimizations can be treated as having an execution count of zero.
Somewhat counter-intuitively, if we give those unreachable nodes a _higher_ priority for receiving physical counters (instead of counter expressions), that ends up reducing the total number of physical counters needed.
This works because if a node is unreachable, we don't actually create a physical counter for it. Instead that node gets a fixed zero counter, and any other node that would have relied on that physical counter in its counter expression can just ignore that term completely.
When preparing a function's coverage counters and metadata during codegen, any
part of the original coverage graph that was removed by MIR optimizations can
be treated as having an execution count of zero.
Somewhat counter-intuitively, if we give those unreachable nodes a _higher_
priority for receiving physical counters (instead of counter expressions), that
ends up reducing the total number of physical counters needed.
This works because if a node is unreachable, we don't actually create a
physical counter for it. Instead that node gets a fixed zero counter, and any
other node that would have relied on that physical counter in its counter
expression can just ignore that term completely.
Rename rustc_middle::Ty::is_unsafe_ptr to is_raw_ptr
The wording unsafe pointer is less common and not mentioned in a lot of places, instead this is usually called a "raw pointer". For the sake of uniformity, we rename this method.
This came up during the review of
https://github.com/rust-lang/rust/pull/134424.
r? `@Noratrieb`
The wording unsafe pointer is less common and not mentioned in a lot of
places, instead this is usually called a "raw pointer". For the sake of
uniformity, we rename this method.
This came up during the review of
https://github.com/rust-lang/rust/pull/134424.
coverage: Defer part of counter-creation until codegen
Follow-up to #135481 and #135873.
One of the pleasant properties of the new counter-assignment algorithm is that we can stop partway through the process, store the intermediate state in MIR, and then resume the rest of the algorithm during codegen. This lets it take into account which parts of the control-flow graph were eliminated by MIR opts, resulting in fewer physical counters and simpler counter expressions.
Those improvements end up completely obsoleting much larger chunks of code that were previously responsible for cleaning up the coverage metadata after MIR opts, while also doing a more thorough cleanup job.
(That change also unlocks some further simplifications that I've kept out of this PR to limit its scope.)
Visit all debug info in MIR Visitor
I've been experimenting with simplifying debug info in MIR inliner, and discovered that MIR Visitor doesn't reliably visit all spans. This PR adds the missing visitor calls.
Update bootstrap compiler and rustfmt
The rustfmt version we previously used formats things differently from what the latest nightly rustfmt does. This causes issues for subtrees that get formatted both in-tree and in their own repo. Updating the rustfmt used in-tree solves those issues. Also bumped the bootstrap compiler as the stage0 update command always updates both at the same
time.