Make some parser structured suggestions verbose and tweak their wording
Replace most of the `.span_suggestion(` in `rustc_parse` with `.span_suggestion_verbose(`, as they are more readabale, if more verbose. Verbose suggestions also tend to highlight off-by-one `Span` errors better.
Tweak some of the touched diagnostics to bring them more in-line with our house style.
CC https://github.com/rust-lang/rust/issues/141973
Replace most of the `.span_suggestion(` in `rustc_parse` with `.span_suggestion_verbose(`, as they are more readabale, if more verbose. Verbose suggestions also tend to highlight off-by-one `Span` errors better.
Remove some dead code
Leftover from a previous revision of `#[unsafe(no_mangle)]`. All call sites disallowed it anyway, and the real handling is in the parser.
Make `TokenTreeCursor` private
And also the fields of `TokenCursor`.
It's good hygiene in general, and will allow larger changes to `TokenCursor` down the road (e.g. hopefully avoiding the flattening of token trees to a linear token stream).
r? @Kobzol
And also the fields of `TokenCursor`.
It's good hygiene in general, and will allow larger changes to
`TokenCursor` down the road (e.g. hopefully avoiding the flattening of
token trees to a linear token stream).
proc_macro: preserve file module spans for inner attrs
fixesrust-lang/rust#157881
out-of-line mods with custom inner attrs were sending proc macros a pretty-printed module wrapper. the awkward bit: tokens inside the module picked up the span from the parent mod foo;, so later diags pointed at the decl instead of the file where the code actually came from.
this keeps the wrapper synthetic, but puts the loaded file body back into the token stream with its own spans. it also skips the attr currently being expanded, so we don't replay it by accident. added a small ui repro too, plus the older span-debug output changed because those spans are now real.
imo this is the least annoying fix for now. fwiw, it keeps the old fake-wrapper path instead of trying to make full token capture for file mods happen in this PR.
Currently the method computes the span from the path's span and the
args' span. That used to be fine but then `unsafe(..)`/`safe(..)` were
added without it being changed. So it doesn't account for those optional
keywords and parentheses. The only way to handle those reliably is with
a dedicated span for the entire `AttrItem`.
Consequences:
- `NormalAttr` grows from 72 bytes to 80. (It's the only AST node that
contains an `AttrItem`.) Not ideal, but non-doc-comment attributes
aren't that common (not compared to expressions, for example). Also,
`NormalAttr` is always boxed and jemalloc will round up 72 byte
allocations to 80 bytes anyway.
- In `lint-unsafe-code.rs` various spans now point to `unsafe(foo)`
rather than just `foo`. (It makes sense to include the `unsafe` keyword
in the complaint about unsafety.)
AST attributes use "early parsed"/"parsed" terminology to refer to the
`CfgTrace` and `CfgAttrTrace` attributes. I think this terminology is
meant to echo the terminology used for HIR attributes, i.e.
`hir::Attribute::{Parsed,Unparsed}`, probably because
`hir::Attribute::Parsed` is used for attributes that aren't stored in a
token-based form.
But this naming is misleading. "Early parsed" attributes aren't parsed
at all because they are inserted by the compiler and cannot be written
in source code. There are also two comments that claim that these
attributes are kept in parsed form "so they don't have to be reparsed
every time they're used, for performance", which is simply incorrect.
This commit renames these as "synthetic" attributes, which better
reflects their nature. The commit also fixes the incorrect comments.
Note that `is_parsed_attribute` is unchanged, because it refers to the
HIR attribute meaning. (And the removal of the synthetic attributes from
it in the previous commit is now more obviously correct.)
This commit pushes further than the previous one, relying more heavily
on looking directly at `AttrKind::Parsed` to handle various cases.
Note that the removed clippy code was actually dead.
`AttrItem` currently contains an `AttrItemKind` which is either `Parsed`
or `Unparsed`. In the `Parsed` case the surrounding `AttrItem` is
basically fake, with a meaningless `unsafety` field, a synthetic
(non-ident) symbol, and an empty `tokens`.
This commit moves `Parsed` up one level to become a new variant of
`AttrKind`. It no longer needs to pretend to be an `AttrKind::Normal`,
and makes a number of things simpler:
- No `unparsed_ref` calls needed.
- Replaces the `attr_into_trace` and `Attribute::replace_args` mess with
the much simpler `convert_normal_to_parsed`.
The commit converts a numberof non-exhaustive `AttrKind` matches (those
that don't involve matching a single attribute) to exhaustive, for
future-proofing. It uses `unreachable!` on all the `AttrKind::Parsed`
cases that aren't hit by the full test suite.
Emit more targeted diagnostics when an input file cannot be opened,
including dedicated messages for common error kinds and typo
suggestions for missing files. Add run-make tests covering NotFound,
PermissionDenied, IsADirectory, and non-existent directory cases.
Signed-off-by: Usman Akinyemi <usmanakinyemi202@gmail.com>
Shrink `ast::Expr64`
From 72 bytes to 64 bytes, by boxing `ForLoop`, which is the biggest
variant.
There are now 11 `ExprKind` variants that are 31 bytes, so future
improvements here will be very difficult.
Make `HasTokens` a sub-trait of `HasAttrs`.
Because that's what it is: any type with tokens must also have attrs. This simplifies some trait bounds.
r? @petrochenkov
The line `&& segment.ident.name == sym::cfg` duplicates a line from just
a few lines above in the same if-let chain. It's clear from context that
the `segment` is a copy/paste error and should be `next_segment`. This
fixes the erroneous suggestion given for
`multiple-tail-expr-behind-cfg.rs`.
Preparatory changes for macro parsing BFS->DFS
This PR contains some miscellaneous commits I accumulated while working on the BFS->DFS change. Their goal is to simplify the code and clarifying existing behavior. It is a conceptual follow-up to rust-lang/rust#158577. High-level overview:
- Adds context about the current match arm to `Tracker` through the new `Tracker::prepare()`, so that the `WhichMatcher` parameter is available implicitly. In a later PR, this will be used to reference `MatcherLoc`s by index.
- Reformulates matching failures to work more like ambiguity errors wrt. `Tracker`; `Tracker::build_failure()` (which would build a failure consumed by `Tracker::after_arm()`) becomes `Tracker::failure()` which eagerly processes the error. This removes the need for `ParseResult::Failure` to store any data at all. This relies on the match arm context provided by `Tracker::prepare()`.
- There is a subtle edge case involving `token::Eof` and non-terminal parsing; `Parser::nonterminal_may_begin_with()` would sometimes return `true` for `token::Eof`, even though the non-terminal parse would never be attempted. `TtParser` did not check `bb_mps` when handling `token::Eof`, so non-terminal parses at EOF were being silently dropped. I changed `Parser::nonterminal_may_begin_with()` to always return `false` for `token::Eof`, making this behavior much more visible. I added a test case to make sure meta-variables return the same error uniformly when parsed against EOF.
Contains rust-lang/rust#158894, which should be merged soon (after which I'll rebase onto `main`).
Best reviewed commit-by-commit.
r? @nnethercote
From 72 bytes to 64 bytes, by boxing `ForLoop`, which is the biggest
variant.
There are now 11 `ExprKind` variants that are 31 bytes, so future
improvements here will be very difficult.
The same basic idea from the previous commit applies: the tokens are
only sometimes needed and we can store them next to the `AttrItem`
(using `WithTokens`) instead of inside the `AttrItem`. The change is a
bit more complex because more than just `parse_nonterminal` is involved
(e.g. `parse_attr_item`, `parse_cfg_attr`, `expand_cfg_attr_item`).
Specifically, from `Block`, `Pat`, `Path`, `Ty`, `Visibility`.
This field is usually `None`. It only gets filled in for paths that
might later be re-tokenized via `TokenStream::from_ast`, e.g. because of
macro or cfg use. All such cases go through a single place:
`parse_nonterminal`.
This commit changes `parse_nonterminal` to store the non-`None` lazy
attr token stream *next* to the node in `ParseNtResult` (using the new
`WithTokens` type) instead of *inside* the parsed node.
Along with some minor changes to the relevant `HasTokens` and `HasAttrs`
impls, this is enough for things to work. These AST nodes all shrink by
8 bytes, as do various other nodes that contain nodes of these types.
A guide to the changes:
- `compiler/rustc_ast/src/tokenstream.rs` has the new `WithTokens` type.
- `compiler/rustc_parse/src/parser/nonterminal.rs`,
`compiler/rustc_expand/src/mbe/transcribe.rs` and
`compiler/rustc_parse/src/parser/mod.rs` have minor changes due to the
changes to `ParseNtResult`.
- `compiler/rustc_ast/src/ast_traits.rs` has the `HasTokens`/`HasAttrs`
changes.
- Everything else is just mechanical changes for the removal of the
`tokens` field.
Until now, `:tt`, `:item`, and `:stmt` metavars could be
attempted against `token::Eof`. *HOWEVER*, when a `token::Eof` is
processed, `parse_tt_inner()` ignores `bb_mps`, not even checking
for ambiguity. It's as if those `bb_mps` never existed; as if
`nonterminal_may_begin_with()` returned `false` for `Eof`. This commit
makes that behavior more explicit.
This does not change user visible behavior.
`tests/ui/macros` pass.
allow mGCA const arguments to fall back to anon consts
makes good progress on https://github.com/rust-lang/project-const-generics/issues/108
`min_generic_const_args` (mGCA) is all about "is this const lowered to a const item with a body, or, is it "directly" represented and visible in the type system?"
Here's various answers to the question of "can we represent this const arg directly?" - if we answer "no", then we fall back to an anon const (or error, sometimes, depending on context)
on **stable**, the full list of things can be directly represented is (... it's just the one thing)
- paths to generic const parameters
on `main`, under mGCA, **before** this PR:
- absolutely everything, if something cannot be represented directly, compiler error
- `const { }` gives you an escape hatch to go back to being an anon const
on macro**ful** gca, the directly represented things will be:
- paths to const parameters
- `direct_const_arg!` macro
on macro**less** gca, the directly represented things will be:
- paths to const parameters
- `direct_const_arg!` macro (not *particularly* useful under macro**less** gca)
- struct expressions, arrays, blah blah
- currently, paths to *anything*, even if that produces a compiler error later down the line (potential followup work here...)
this PR implements macro**less** gca, with the intent of a quick follow-up introducing a "macroless gca" feature and transitioning `#[feature(min_generic_const_args)]` to be macro**ful** gca
Also of note is that this PR removes the logic to skip generating "fake" DefIds for directly represented AnonConsts under mGCA, we now always generate a DefId when encountering an AnonConst. This lines up with stable, which has a fake AnonConst DefId for a directly represented plain path generic parameter (i.e. the bullet point under the "stable" entry above).
r? @BoxyUwU
Fix the span for parameter suggestion
Fixesrust-lang/rust#131084
Previously, the recovered parameter span could point only at the inner identifier, so the suggestion was inserted after the leading `&`, produced a werid `&&self`.
The fix keeps the recovered parameter's full span on `Param.span`
r? @nnethercote
the second commit shows the diff of stderr.