Implement a Method to Seal `DiagInner`'s Suggestions
This PR adds a method on `DiagInner` called `.seal_suggestions()` to prevent new suggestions from being added while preserving existing suggestions.
This is useful because currently there is no way to prevent new suggestions from being added to a diagnostic. `.disable_suggestions()` is the closest but it gets rid of all suggestions before and after the call.
Therefore, `.seal_suggestions()` can be used when, for example, misspelled keyword is detected and reported. In such cases, we may want to prevent other suggestions from being added to the diagnostic, as they would likely be meaningless once the misspelled keyword is identified. For context: https://github.com/rust-lang/rust/pull/129899#discussion_r1741307132
To store an additional state, the type of the `suggestions` field in `DiagInner` was changed into a three variant enum. While this change affects files across different crates, care was taken to preserve the existing code's semantics. This is validated by the fact that all UI tests pass without any modifications.
r? chenyukang
Fix anon const def-creation when macros are involved
Fixes#128016.
Ever since #125915, some `ast::AnonConst`s turn into `hir::ConstArgKind::Path`s,
which don't have associated `DefId`s. To deal with the fact that we don't have
resolution information in `DefCollector`, we decided to implement a process
where if the anon const *appeared* to be trivial (i.e., `N` or `{ N }`), we
would avoid creating a def for it in `DefCollector`. If later, in AST lowering,
we realized it turned out to be a unit struct literal, or we were lowering it
to something that didn't use `hir::ConstArg`, we'd create its def there.
However, let's say we have a macro `m!()` that expands to a reference to a free
constant `FOO`. If we use `m!()` in the body of an anon const (e.g., `Foo<{ m!() }>`),
then in def collection, it appears to be a nontrivial anon const and we create
a def. But the macro expands to something that looks like a trivial const arg,
but is not, so in AST lowering we "fix" the mistake we assumed def collection
made and create a def for it. This causes a duplicate definition ICE.
The long-term fix for this is to delay the creation of defs for all expression-like
nodes until AST lowering (see #128844 for an incomplete attempt at this). This
would avoid issues like this one that are caused by hacky workarounds. However,
doing this uncovers a pre-existing bug with opaque types that is quite involved
to fix (see #129023).
In the meantime, this PR fixes the bug by delaying def creation for anon consts
whose bodies are macro invocations until after we expand the macro and know
what is inside it. This is accomplished by adding information to create the
anon const's def to the data in `Resolver.invocation_parents`.
r? `@BoxyUwU`
...and remove the `const_arg_path` feature gate as a result. It was only
a stopgap measure to fix the regression that the new lowering introduced
(which should now be fixed by this PR).
Ever since #125915, some `ast::AnonConst`s turn into `hir::ConstArgKind::Path`s,
which don't have associated `DefId`s. To deal with the fact that we don't have
resolution information in `DefCollector`, we decided to implement a process
where if the anon const *appeared* to be trivial (i.e., `N` or `{ N }`), we
would avoid creating a def for it in `DefCollector`. If later, in AST lowering,
we realized it turned out to be a unit struct literal, or we were lowering it
to something that didn't use `hir::ConstArg`, we'd create its def there.
However, let's say we have a macro `m!()` that expands to a reference to a free
constant `FOO`. If we use `m!()` in the body of an anon const (e.g., `Foo<{ m!() }>`),
then in def collection, it appears to be a nontrivial anon const and we create
a def. But the macro expands to something that looks like a trivial const arg,
but is not, so in AST lowering we "fix" the mistake we assumed def collection
made and create a def for it. This causes a duplicate definition ICE.
The ideal long-term fix for this is a bit unclear. One option is to delay def
creation for all expression-like nodes until AST lowering (see #128844 for an
incomplete attempt at this). This would avoid issues like this one that are
caused by hacky workarounds. However, this approach has some downsides as well,
and the best approach is yet to be determined.
In the meantime, this PR fixes the bug by delaying def creation for anon consts
whose bodies are macro invocations until after we expand the macro and know
what is inside it. This is accomplished by adding information to create the
anon const's def to the data in `Resolver.invocation_parents`.
Introduce `'ra` lifetime name.
`rustc_resolve` allocates many things in `ResolverArenas`. The lifetime used for references into the arena is mostly `'a`, and sometimes `'b`.
This commit changes it to `'rslv`, which is much more descriptive. The commit also changes the order of lifetimes on a couple of structs so that '`rslv` is second last, before `'tcx`, and does other minor renamings such as `'r` to `'a`.
r? ``@petrochenkov``
cc ``@oli-obk``
Simplify some nested `if` statements
Applies some but not all instances of `clippy::collapsible_if`. Some ended up looking worse afterwards, though, so I left those out. Also applies instances of `clippy::collapsible_else_if`
Review with whitespace disabled please.
`rustc_resolve` allocates many things in `ResolverArenas`. The lifetime
used for references into the arena is mostly `'a`, and sometimes `'b`.
This commit changes it to `'ra`, which is much more descriptive. The
commit also changes the order of lifetimes on a couple of structs so
that '`ra` is second last, before `'tcx`, and does other minor
renamings such as `'r` to `'a`.
Retroactively feature gate `ConstArgKind::Path`
This puts the lowering introduced by #125915 under a feature gate until we fix the regressions introduced by it. Alternative to whole sale reverting the PR since it didn't seem like a very clean revert and I think this is generally a step in the right direction and don't want to get stuck landing and reverting the PR over and over :)
cc #129137 ``@camelid,`` tests taken from there. beta is branching soon so I think it makes sense to not try and rush that fix through since it wont have much time to bake and if it has issues we can't simply revert it on beta.
Fixes#128016
Use shorthand field initialization syntax more aggressively in the compiler
Caught these when cleaning up #129344 and decided to run clippy to find the rest
Use `bool` in favor of `Option<()>` for diagnostics
We originally only supported `Option<()>` for optional notes/labels, but we now support `bool`. Let's use that, since it usually leads to more readable code.
I'm not removing the support from the derive macro, though I guess we could error on it... 🤔
Don't consider locals to shadow inner items' generics
We don't want to consider the bindings from a `RibKind::Module` itself, because for an inner item that module will contain the local bindings from the function body or wherever else the inner item is being defined.
Fixes#129265
r? petrochenkov
rm `import.used`
By the way, `import_used_map` will only be used during `build_reduced_graph` and `finalize`, so it can be split from `Resolver` in the future.
r? ``@petrochenkov``
Use more slice patterns inside the compiler
Nothing super noteworthy. Just replacing the common 'fragile' pattern of "length check followed by indexing or unwrap" with slice patterns for legibility and 'robustness'.
r? ghost
Only walk ribs to collect possibly shadowed params if we are adding params in our new rib
No need to collect params from parent ribs if we literally have no params to declare in this new rib.
Attempt to win back some of the perf in https://github.com/rust-lang/rust/pull/128357#issuecomment-2262677031.
Please review with whitespace *off*, the diff should be like 2 lines.
r? petrochenkov
Add `REDUNDANT_IMPORTS` lint for new redundant import detection
Defaults to Allow for now. Stacked on #123744 to avoid merge conflict, but much easier to review all as one.
r? petrochenkov
Structured suggestion for `extern crate foo` when `foo` isn't resolved in import
When encountering a name in an import that could have come from a crate that wasn't imported, use a structured suggestion to suggest `extern crate foo;` pointing at the right place in the crate.
When encountering `_` in an import, do not suggest `extern crate _;`.
```
error[E0432]: unresolved import `spam`
--> $DIR/import-from-missing-star-3.rs:2:9
|
LL | use spam::*;
| ^^^^ maybe a missing crate `spam`?
|
help: consider importing the `spam` crate
|
LL + extern crate spam;
|
```
When encountering a name in an import that could have come from a crate that wasn't imported, use a structured suggestion to suggest `extern crate foo;` pointing at the right place in the crate.
When encountering `_` in an import, do not suggest `extern crate _;`.
```
error[E0432]: unresolved import `spam`
--> $DIR/import-from-missing-star-3.rs:2:9
|
LL | use spam::*;
| ^^^^ maybe a missing crate `spam`?
|
help: consider importing the `spam` crate
|
LL + extern crate spam;
|
```
We don't want to have questions in the diagnostic output. Instead, we use wording that communicates uncertainty, like "might":
```
error[E0432]: unresolved import `spam`
--> $DIR/import-from-missing-star-3.rs:2:9
|
LL | use spam::*;
| ^^^^ you might be missing crate `spam`
|
= help: consider adding `extern crate spam` to use the `spam` crate
```
Clean up a few minor refs in `format!` macro, as it has a performance cost. Apparently the compiler is unable to inline `format!("{}", &variable)`, and does a run-time double-reference instead (format macro already does one level referencing). Inlining format args prevents accidental `&` misuse.
When finding item gated behind a `cfg` flag, point at it
Previously we would only mention that the item was gated out, and opportunisitically mention the feature flag name when possible. We now point to the place where the item was gated, which can be behind layers of macro indirection, or in different modules.
```
error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner`
--> $DIR/diagnostics-cross-crate.rs:18:23
|
LL | cfged_out::inner::doesnt_exist::hello();
| ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner`
|
note: found an item that was configured out
--> $DIR/auxiliary/cfged_out.rs:6:13
|
LL | pub mod doesnt_exist {
| ^^^^^^^^^^^^
note: the item is gated here
--> $DIR/auxiliary/cfged_out.rs:5:5
|
LL | #[cfg(FALSE)]
| ^^^^^^^^^^^^^
```
Represent type-level consts with new-and-improved `hir::ConstArg`
### Summary
This is a step toward `min_generic_const_exprs`. We now represent all const
generic arguments using an enum that differentiates between const *paths*
(temporarily just bare const params) and arbitrary anon consts that may perform
computations. This will enable us to cleanly implement the `min_generic_const_args`
plan of allowing the use of generics in paths used as const args, while
disallowing their use in arbitrary anon consts. Here is a summary of the salient
aspects of this change:
- Add `current_def_id_parent` to `LoweringContext`
This is needed to track anon const parents properly once we implement
`ConstArgKind::Path` (which requires moving anon const def-creation
outside of `DefCollector`).
- Create `hir::ConstArgKind` enum with `Path` and `Anon` variants. Use it in the
existing `hir::ConstArg` struct, replacing the previous `hir::AnonConst` field.
- Use `ConstArg` for all instances of const args. Specifically, use it instead
of `AnonConst` for assoc item constraints, array lengths, and const param
defaults.
- Some `ast::AnonConst`s now have their `DefId`s created in
rustc_ast_lowering rather than `DefCollector`. This is because in some
cases they will end up becoming a `ConstArgKind::Path` instead, which
has no `DefId`. We have to solve this in a hacky way where we guess
whether the `AnonConst` could end up as a path const since we can't
know for sure until after name resolution (`N` could refer to a free
const or a nullary struct). If it has no chance as being a const
param, then we create a `DefId` in `DefCollector` -- otherwise we
decide during ast_lowering. This will have to be updated once all path
consts use `ConstArgKind::Path`.
- We explicitly use `ConstArgHasType` for array lengths, rather than
implicitly relying on anon const type feeding -- this is due to the
addition of `ConstArgKind::Path`.
- Some tests have their outputs changed, but the changes are for the
most part minor (including removing duplicate or almost-duplicate
errors). One test now ICEs, but it is for an incomplete, unstable
feature and is now tracked at https://github.com/rust-lang/rust/issues/127009.
### Followup items post-merge
- Use `ConstArgKind::Path` for all const paths, not just const params.
- Fix (no github dont close this issue) #127009
- If a path in generic args doesn't resolve as a type, try to resolve as a const
instead (do this in rustc_resolve). Then remove the special-casing from
`rustc_ast_lowering`, so that all params will automatically be lowered as
`ConstArgKind::Path`.
- (?) Consider making `const_evaluatable_unchecked` a hard error, or at least
trying it in crater
r? `@BoxyUwU`
Fix ambiguous cases of multiple & in elided self lifetimes
This change proposes simpler rules to identify the lifetime on `self` parameters which may be used to elide a return type lifetime.
## The old rules
(copied from [this comment](https://github.com/rust-lang/rust/pull/117967#discussion_r1420554242))
Most of the code can be found in [late.rs](https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_resolve/late.rs.html) and acts on AST types. The function [resolve_fn_params](https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_resolve/late.rs.html#2006), in the success case, returns a single lifetime which can be used to elide the lifetime of return types.
Here's how:
* If the first parameter is called self then we search that parameter using "`self` search rules", below
* If no unique applicable lifetime was found, search all other parameters using "regular parameter search rules", below
(In practice the code does extra work to assemble good diagnostic information, so it's not quite laid out like the above.)
### `self` search rules
This is primarily handled in [find_lifetime_for_self](https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_resolve/late.rs.html#2118) , and is described slightly [here](https://github.com/rust-lang/rust/issues/117715#issuecomment-1813115477) already. The code:
1. Recursively walks the type of the `self` parameter (there's some complexity about resolving various special cases, but it's essentially just walking the type as far as I can see)
2. Each time we find a reference anywhere in the type, if the **direct** referent is `Self` (either spelled `Self` or by some alias resolution which I don't fully understand), then we'll add that to a set of candidate lifetimes
3. If there's exactly one such unique lifetime candidate found, we return this lifetime.
### Regular parameter search rules
1. Find all the lifetimes in each parameter, including implicit, explicit etc.
2. If there's exactly one parameter containing lifetimes, and if that parameter contains exactly one (unique) lifetime, *and if we didn't find a `self` lifetime parameter already*, we'll return this lifetime.
## The new rules
There are no changes to the "regular parameter search rules" or to the overall flow, only to the `self` search rules which are now:
1. Recursively walks the type of the `self` parameter, searching for lifetimes of reference types whose referent **contains** `Self`.[^1]
2. Keep a record of:
* Whether 0, 1 or n unique lifetimes are found on references encountered during the walk
4. If no lifetime was found, we don't return a lifetime. (This means other parameters' lifetimes may be used for return type lifetime elision).
5. If there's one lifetime found, we return the lifetime.
6. If multiple lifetimes were found, we abort elision entirely (other parameters' lifetimes won't be used).
[^1]: this prevents us from considering lifetimes from inside of the self-type
## Examples that were accepted before and will now be rejected
```rust
fn a(self: &Box<&Self>) -> &u32
fn b(self: &Pin<&mut Self>) -> &String
fn c(self: &mut &Self) -> Option<&Self>
fn d(self: &mut &Box<Self>, arg: &usize) -> &usize // previously used the lt from arg
```
### Examples that change the elided lifetime
```rust
fn e(self: &mut Box<Self>, arg: &usize) -> &usize
// ^ new ^ previous
```
## Examples that were rejected before and will now be accepted
```rust
fn f(self: &Box<Self>) -> &u32
```
---
*edit: old PR description:*
```rust
struct Concrete(u32);
impl Concrete {
fn m(self: &Box<Self>) -> &u32 {
&self.0
}
}
```
resulted in a confusing error.
```rust
impl Concrete {
fn n(self: &Box<&Self>) -> &u32 {
&self.0
}
}
```
resulted in no error or warning, despite apparent ambiguity over the elided lifetime.
Fixes https://github.com/rust-lang/rust/issues/117715
Accurate `use` rename suggestion span
When suggesting to rename an import with `as`, use a smaller span to render the suggestion with a better format:
```
error[E0252]: the name `baz` is defined multiple times
--> $DIR/issue-25396.rs:4:5
|
LL | use foo::baz;
| -------- previous import of the module `baz` here
LL | use bar::baz;
| ^^^^^^^^ `baz` reimported here
|
= note: `baz` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use bar::baz as other_baz;
| ++++++++++++
```
When suggesting to rename an import with `as`, use a smaller span to
render the suggestion with a better format:
```
error[E0252]: the name `baz` is defined multiple times
--> $DIR/issue-25396.rs:4:5
|
LL | use foo::baz;
| -------- previous import of the module `baz` here
LL | use bar::baz;
| ^^^^^^^^ `baz` reimported here
|
= note: `baz` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
LL | use bar::baz as other_baz;
| ++++++++++++
```
This is a very large commit since a lot needs to be changed in order to
make the tests pass. The salient changes are:
- `ConstArgKind` gets a new `Path` variant, and all const params are now
represented using it. Non-param paths still use `ConstArgKind::Anon`
to prevent this change from getting too large, but they will soon use
the `Path` variant too.
- `ConstArg` gets a distinct `hir_id` field and its own variant in
`hir::Node`. This affected many parts of the compiler that expected
the parent of an `AnonConst` to be the containing context (e.g., an
array repeat expression). They have been changed to check the
"grandparent" where necessary.
- Some `ast::AnonConst`s now have their `DefId`s created in
rustc_ast_lowering rather than `DefCollector`. This is because in some
cases they will end up becoming a `ConstArgKind::Path` instead, which
has no `DefId`. We have to solve this in a hacky way where we guess
whether the `AnonConst` could end up as a path const since we can't
know for sure until after name resolution (`N` could refer to a free
const or a nullary struct). If it has no chance as being a const
param, then we create a `DefId` in `DefCollector` -- otherwise we
decide during ast_lowering. This will have to be updated once all path
consts use `ConstArgKind::Path`.
- We explicitly use `ConstArgHasType` for array lengths, rather than
implicitly relying on anon const type feeding -- this is due to the
addition of `ConstArgKind::Path`.
- Some tests have their outputs changed, but the changes are for the
most part minor (including removing duplicate or almost-duplicate
errors). One test now ICEs, but it is for an incomplete, unstable
feature and is now tracked at #127009.
Fix import suggestion ice
Fixes#127302#127302 only crash in edition 2015
#120074 can only reproduced in edition 2021
so I added revisions in test file.
Previously we would only mention that the item was gated out, and opportunisitically mention the feature flag name when possible. We now point to the place where the item was gated, which can be behind layers of macro indirection, or in different modules.
```
error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner`
--> $DIR/diagnostics-cross-crate.rs:18:23
|
LL | cfged_out::inner::doesnt_exist::hello();
| ^^^^^^^^^^^^ could not find `doesnt_exist` in `inner`
|
note: found an item that was configured out
--> $DIR/auxiliary/cfged_out.rs:6:13
|
LL | pub mod doesnt_exist {
| ^^^^^^^^^^^^
note: the item is gated here
--> $DIR/auxiliary/cfged_out.rs:5:5
|
LL | #[cfg(FALSE)]
| ^^^^^^^^^^^^^
```
Use field ident spans directly instead of the full field span in diagnostics on local fields
This improves diagnostics and avoids having to store the `DefId`s of fields
The only place it is meaningfully used is in a panic message in
`TokenStream::from_ast`. But `node.span()` doesn't need to be printed
because `node` is also printed and it must contain the span.
rustdoc: update to pulldown-cmark 0.11
r? rustdoc
This pull request updates rustdoc to the latest version of pulldown-cmark. Along with adding new markdown extensions (which this PR doesn't enable), the new pulldown-cmark version also fixes a large number of bugs. Because all text files successfully parse as markdown, these bugfixes change the output, which can break people's existing docs.
A crater run, https://github.com/rust-lang/rust/pull/121659, has already been run for this change.
The first commit upgrades and fixes rustdoc. The second commit adds a lint for the footnote and block quote parser changes, which break the largest numbers of docs in the Crater run. The strikethrough change was mitigated in pulldown-cmark itself.
Unblocks https://github.com/rust-lang/rust-clippy/pull/12876
ast: Standardize visiting order for attributes and node IDs
This should only affect `macro_rules` scopes and order of diagnostics.
Also add a deprecation lint for `macro_rules` called outside of their scope, like in https://github.com/rust-lang/rust/issues/124535.
`StaticForeignItem` and `StaticItem` are the same
The struct `StaticItem` and `StaticForeignItem` are the same, so remove `StaticForeignItem`. Having them be separate is unique to `static` items -- unlike `ForeignItemKind::{Fn,TyAlias}`, which use the normal AST item.
r? ``@spastorino`` or ``@oli-obk``
delegation: Implement glob delegation
Support delegating to all trait methods in one go.
Overriding globs with explicit definitions is also supported.
The implementation is generally based on the design from https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2020869823, but unlike with list delegation in https://github.com/rust-lang/rust/pull/123413 we cannot expand glob delegation eagerly.
We have to enqueue it into the queue of unexpanded macros (most other macros are processed this way too), and then a glob delegation waits in that queue until its trait path is resolved, and enough code expands to generate the identifier list produced from the glob.
Glob delegation is only allowed in impls, and can only point to traits.
Supporting it in other places gives very little practical benefit, but significantly raises the implementation complexity.
Part of https://github.com/rust-lang/rust/issues/118212.
Resolve elided lifetimes in assoc const to static if no other lifetimes are in scope
Implements the change to elided lifetime resolution in *associated consts* subject to FCP here: https://github.com/rust-lang/rust/issues/125190#issue-2301532282
Specifically, walk the enclosing lifetime ribs in an associated const, and if we find no other lifetimes, then resolve to `'static`.
Also make it work for traits, but don't lint -- just give a hard error in that case.