Commit Graph

420 Commits

Author SHA1 Message Date
Vadim Petrochenkov
9b797b9f7a resolve: Improve code reuse in typo candidate collection 2025-08-14 09:53:49 +03:00
Vadim Petrochenkov
d682943396 resolve: Do not show deprecated helper attributes in typo recommendations
Remove one FIXME, addressing it does not reduce the hacky-ness much, and the logic is going to be removed anyway together with the `legacy_derive_helpers` deprecation lint.
2025-08-14 09:53:49 +03:00
Vadim Petrochenkov
51eb5ed8f0 resolve: Do not call resolve_macro_path from late resolution
`maybe_resolve_path` is less precise in corner cases, but it's only used for diagnostics and error recovery, so it's good enough.
2025-08-14 09:53:46 +03:00
bors
8e7795415a Auto merge of #144793 - petrochenkov:extprel3, r=davidtwco
resolve: Split extern prelude into two scopes

One scope for `extern crate` items and another for `--extern` options, with the former shadowing the latter.

If in a single scope some things can overwrite other things, especially with ad hoc restrictions like `MacroExpandedExternCrateCannotShadowExternArguments`, then it's not really a single scope.
So this PR splits `Scope::ExternPrelude` into two cleaner scopes.

This is similar to how https://github.com/rust-lang/rust/pull/144131 splits module scope into two scopes for globs and non-globs, but simpler.
2025-08-13 22:52:17 +00:00
Vadim Petrochenkov
d98eaad509 resolve: Improve diagnostics for ambiguities in extern prelude 2025-08-13 17:45:40 +03:00
Vadim Petrochenkov
772493d51d resolve: Split extern prelude into two scopes
One for `--extern` options and another for `extern crate` items.
2025-08-13 17:45:40 +03:00
Josh Triplett
ba231db3f3 Detect and report macro kind mismatches early, and more precisely
This eliminates the case in `failed_to_match_macro` to check for a
function-like invocation of a macro with no function-like rules.

Instead, macro kind mismatches now result in an unresolved macro, and we
detect this case in `unresolved_macro_suggestions`, which now carefully
distinguishes between a kind mismatch and other errors.

This also handles cases of forward-referenced attributes and cyclic
attributes.

Expand test coverage to include all of these cases.
2025-08-12 09:24:45 -07:00
Josh Triplett
0b855bcdc9 Switch to a bitflags MacroKinds to support macros with more than one kind
Review everything that uses `MacroKind`, and switch anything that could
refer to more than one kind to use `MacroKinds`.

Add a new `SyntaxExtensionKind::MacroRules` for `macro_rules!` macros,
using the concrete `MacroRulesMacroExpander` type, and have it track
which kinds it can handle. Eliminate the separate optional `attr_ext`,
now that a `SyntaxExtension` can handle multiple macro kinds.

This also avoids the need to downcast when calling methods on
`MacroRulesMacroExpander`, such as `get_unused_rule`.

Integrate macro kind checking into name resolution's
`sub_namespace_match`, so that we only find a macro if it's the right
type, and eliminate the special-case hack for attributes.
2025-08-12 09:24:45 -07:00
Esteban Küber
29d26f27a6 review comments 2025-08-10 19:15:20 +00:00
Esteban Küber
464a6b1b4a Detect struct construction with private field in field with default
When trying to construct a struct that has a public field of a private type, suggest using `..` if that field has a default value.

```
error[E0603]: struct `Priv1` is private
  --> $DIR/non-exhaustive-ctor.rs:25:39
   |
LL |     let _ = S { field: (), field1: m::Priv1 {} };
   |                            ------     ^^^^^ private struct
   |                            |
   |                            while setting this field
   |
note: the struct `Priv1` is defined here
  --> $DIR/non-exhaustive-ctor.rs:14:4
   |
LL |    struct Priv1 {}
   |    ^^^^^^^^^^^^
help: the field `field1` you're trying to set has a default value, you can use `..` to use it
   |
LL |     let _ = S { field: (), .. };
   |                            ~~
```
2025-08-10 19:15:18 +00:00
Deadbeef
ad1113f87e remove P 2025-08-09 15:47:01 +08:00
Stuart Cook
ecce94c0a5 Rollup merge of #144912 - LorrensP-2158466:smart-resolver, r=petrochenkov
Resolver: introduce a conditionally mutable Resolver for (non-)speculative resolution.

This pr introduces a `CmResolver`, a wrapper around the main resolver which gives out mutable access given a condition.

`CmResolver` only allows mutation when we’re not in speculative import resolution. This ensures we can’t accidentally mutate the resolver during this process, which is important as we move towards a batched resolution algorithm.

This also changes functions that are used during speculative import resolution to take a `CmResolver` instead of a `&mut Resolver`.

Also introduces a new kind of "smart pointer" which has the behaviour described above:
```rust
/// A wrapper around a mutable reference that conditionally allows mutable access.
pub(crate) struct RefOrMut<'a, T> {
    p: &'a mut T,
    mutable: bool,
}

type CmResolver<'r, 'ra, 'tcx> = RefOrMut<'r, Resolver<'ra, 'tcx>>;
```
r? petrochenkov
2025-08-08 12:52:52 +10:00
LorrensP-2158466
487e5ce371 Introduce, implement and use CmResolver. 2025-08-07 16:05:00 +02:00
xizheyin
6e7b9d5149 Introduce ModernIdent type to unify macro 2.0 hygiene handling
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
2025-08-06 21:19:09 +08:00
Stuart Cook
2105044784 Rollup merge of #144746 - petrochenkov:extpreltidy, r=b-naber
resolve: Cleanups and micro-optimizations to extern prelude

This is what can be done without changing the structure of `ExternPreludeEntry`, like in https://github.com/rust-lang/rust/pull/144737.

See individual commits for details.
2025-08-04 11:24:39 +10:00
bors
889701db1f Auto merge of #129183 - estebank:cfg-visitor, r=davidtwco
Detect more `cfg`d out items in resolution errors

Use a visitor to collect *all* items (including those nested) that were stripped behind a `cfg` condition.

```
error[E0425]: cannot find function `f` in this scope
  --> $DIR/nested-cfg-attrs.rs:4:13
   |
LL | fn main() { f() }
   |             ^ not found in this scope
   |
note: found an item that was configured out
  --> $DIR/nested-cfg-attrs.rs:2:4
   |
LL | fn f() {}
   |    ^
note: the item is gated here
  --> $DIR/nested-cfg-attrs.rs:1:35
   |
LL | #[cfg_attr(all(), cfg_attr(all(), cfg(FALSE)))]
   |                                   ^^^^^^^^^^
```
2025-08-02 05:09:31 +00:00
Esteban Küber
4b24c4bf23 Tweak rendering of cfg'd out item
```
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 |     #[cfg(false)]
   |           ----- the item is gated here
LL |     pub mod doesnt_exist {
   |             ^^^^^^^^^^^^
```
2025-08-01 23:58:15 +00:00
Esteban Küber
77f75f91c5 tiny cleanup 2025-08-01 22:11:45 +00:00
Esteban Küber
adcda6ca9a Detect more cfgd out items in resolution errors
Use a visitor to collect *all* items (including those nested) that were stripped behind a `cfg` condition.

```
error[E0425]: cannot find function `f` in this scope
  --> $DIR/nested-cfg-attrs.rs:4:13
   |
LL | fn main() { f() }
   |             ^ not found in this scope
   |
note: found an item that was configured out
  --> $DIR/nested-cfg-attrs.rs:2:4
   |
LL | fn f() {}
   |    ^
note: the item is gated here
  --> $DIR/nested-cfg-attrs.rs:1:35
   |
LL | #[cfg_attr(all(), cfg_attr(all(), cfg(FALSE)))]
   |                                   ^^^^^^^^^^
```
2025-08-01 21:50:36 +00:00
Vadim Petrochenkov
e58e6f857f resolve: Cleanup some uses of extern prelude in diagnostics 2025-07-31 20:35:14 +03:00
Jana Dönszelmann
e1d3ad89c7 remove rustc_attr_data_structures 2025-07-31 14:19:27 +02:00
LorrensP-2158466
451a93e2b8 split up define into define_extern and define_local 2025-07-27 12:17:23 +02:00
Vadim Petrochenkov
e82011255b resolve: Do not create NameResolutions on access unless necessary 2025-07-26 00:25:26 +03:00
Vadim Petrochenkov
2c65790160 resolve: Minimize borrow scopes for resolutions 2025-07-26 00:19:12 +03:00
Vadim Petrochenkov
9ffa775232 resolve: Remove Scope::CrateRoot
Use `Scope::Module` with the crate root module inside instead, which should be identical.
2025-07-24 15:59:47 +03:00
LorrensP-2158466
466d33cb5c inline CrateLoader inside of CStore 2025-07-18 13:16:09 +02:00
Matthias Krüger
52a405b6c9 Rollup merge of #143550 - petrochenkov:lessmutres, r=lcnr
resolve: Use interior mutability for extern module map

Module map for extern modules is a lazily populated cache, it's not *significantly* mutable.
If some logic in name resolver is parallelized, then this cache can be populated from any thread, and without affecting results of any speculative resolution.

Unblocks https://github.com/rust-lang/rust/pull/143884.
This is a part of [#gsoc > Project: Parallel Macro Expansion](https://rust-lang.zulipchat.com/#narrow/channel/421156-gsoc/topic/Project.3A.20Parallel.20Macro.20Expansion/with/527348747).
cc `@LorrensP-2158466`
2025-07-17 10:41:44 +02:00
Vadim Petrochenkov
6849f816b1 resolve: Change &mut Resolver to &Resolver when possible 2025-07-17 02:09:01 +03:00
Vadim Petrochenkov
8b8889df25 resolve: Split module_map into two maps for local and extern modules 2025-07-17 02:09:01 +03:00
Vadim Petrochenkov
8d7193973f resolve: Use module_map and get_module less 2025-07-17 02:09:00 +03:00
Nicholas Nethercote
fb7aa9e4fd Improve path segment joining.
There are many places that join path segments with `::` to produce a
string. A lot of these use `join("::")`. Many in rustdoc use
`join_with_double_colon`, and a few use `.joined("..")`. One in Clippy
uses `itertools::join`. A couple of them look for `kw::PathRoot` in the
first segment, which can be important.

This commit introduces `rustc_ast::join_path_{syms,ident}` to do the
joining for everyone. `rustc_ast` is as good a location for these as
any, being the earliest-running of the several crates with a `Path`
type. Two functions are needed because `Ident` printing is more complex
than simple `Symbol` printing.

The commit also removes `join_with_double_colon`, and
`estimate_item_path_byte_length` with it.

There are still a handful of places that join strings with "::" that are
unchanged. They are not that important: some of them are in tests, and
some of them first split a path around "::" and then rejoin with "::".

This fixes one test case where `{{root}}` shows up in an error message.
2025-07-17 08:37:19 +10:00
Vadim Petrochenkov
babe2c0d0f resolve: Merge NameBindingKind::Module into NameBindingKind::Res 2025-07-16 08:28:17 +03:00
Jonathan Brouwer
6133c676d7 Define attribute parser & config evaluator 2025-07-15 09:21:26 +02:00
b-naber
9ed5378cfd replace binding and shadowed_glob on NameResolution with non_glob_binding and glob_binding 2025-07-12 15:06:32 +02:00
LorrensP-2158466
e9e31b1a93 MacroData in ResolverArenas + split macro_map into extern_macro_map and local_macro_map. 2025-07-09 23:24:36 +02:00
Jonathan Brouwer
027126ce0b Port #[non_exhaustive] to the new attribute parsing infrastructure 2025-07-04 20:30:42 +02:00
Matthias Krüger
190a1a7f74 Rollup merge of #142730 - bend-n:suggest_declaring_modules_when_file_found_but_module_not_defined, r=petrochenkov
suggest declaring modules when file found but module not defined

suggests declaring modules when a module is found but not defined, i.e
```
├── main.rs: `use thing::thang;`
└── thing.rs: `struct thang`
```
or
```
├── main.rs: `use thing::thang;`
└── thing
    └── mod.rs: `struct thang`
```
which currently is just
```rust
error[E0432]: unresolved import `yeah`
 --> src/main.rs:1:1
  |
1 | use thing::thang;
  |     ^^^^^ use of unresolved module or unlinked crate `thing`
  |
```
but now would have this nice help:
```text
= help: you may have forgotten to declare the module `thing`. use `mod thing` in this file to declare this module.
```
2025-06-27 22:13:02 +02:00
xizheyin
d2d17c60bd Add runtime check to avoid overwrite arg easily in diag and store and restore snapshot when set subdiag arg
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
2025-06-25 21:07:16 +08:00
bendn
3583423536 suggest declaring modules when file found but module not defined 2025-06-25 01:12:15 +07:00
Esteban Küber
92a798dac0 Detect when attribute is provided by missing derive macro
```
error: cannot find attribute `empty_helper` in this scope
  --> $DIR/derive-helper-legacy-limits.rs:17:3
   |
LL | #[empty_helper]
   |   ^^^^^^^^^^^^
   |
help: `empty_helper` is an attribute that can be used by the derive macro `Empty`, you might be missing a `derive` attribute
   |
LL + #[derive(Empty)]
LL | struct S2;
   |
```

Look at proc-macro attributes when encountering unknown attribute

```
error: cannot find attribute `sede` in this scope
  --> src/main.rs:18:7
   |
18 |     #[sede(untagged)]
   |       ^^^^
   |
help: the derive macros `Serialize` and `Deserialize` accept the similarly named `serde` attribute
   |
18 |     #[serde(untagged)]
   |       ~~~~~

error: cannot find attribute `serde` in this scope
  --> src/main.rs:12:7
   |
12 |     #[serde(untagged)]
   |       ^^^^^
   |
   = note: `serde` is in scope, but it is a crate, not an attribute
help: `serde` is an attribute that can be used by the derive macros `Serialize` and `Deserialize`, you might be missing a `derive` attribute
   |
10 | #[derive(Serialize, Deserialize)]
   |
```
2025-06-12 21:28:49 +00:00
bohan
e9080948c6 consider glob imports in cfg suggestion 2025-05-28 00:59:47 +08:00
bohan
1adfdb42b9 Use crate:: prefix for root macro suggestions 2025-05-17 22:01:57 +08:00
mu001999
7c253ac504 Suggest stable candidates rather than unstable ones 2025-05-09 22:05:59 +08:00
Vadim Petrochenkov
3eee3dad5c resolve: Support imports of associated types and glob imports from traits 2025-05-02 15:59:38 +03:00
Oli Scherer
24efefafcb Avoid a reverse map that is only used in diagnostics paths 2025-04-11 09:33:38 +00:00
Nicholas Nethercote
1b3fc585cb Rename some name variables as ident.
It bugs me when variables of type `Ident` are called `name`. It leads to
silly things like `name.name`. `Ident` variables should be called
`ident`, and `name` should be used for variables of type `Symbol`.

This commit improves things by by doing `s/name/ident/` on a bunch of
`Ident` variables. Not all of them, but a decent chunk.
2025-04-10 09:30:55 +10:00
Matthias Krüger
068594e365 Rollup merge of #138790 - xizheyin:issue-138626, r=compiler-errors
Note potential but private items in show_candidates

Closes #138626 .
We should add potential private items to give ample hints.
And for the other seemingly false positive ` pub use crate:1️⃣:Foo;` should be kept because we don't know if the user wants to import other module's items or not, and therefore should be given the full option to do so.
r? compiler
2025-04-01 20:25:21 +02:00
bors
ed201574c5 Auto merge of #138740 - nnethercote:ast-ItemKind-idents, r=fmease
Move `ast::Item::ident` into `ast::ItemKind`

The follow-up to #138384, which did the same thing for `hir::ItemKind`.

r? `@fmease`
2025-04-01 07:21:28 +00:00
Nicholas Nethercote
df247968f2 Move ast::Item::ident into ast::ItemKind.
`ast::Item` has an `ident` field.

- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
  `Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
  `Trait`, `TraitAlias`, `MacroDef`, `Delegation`.

- It's always empty for these item kinds: `Use`, `ForeignMod`,
  `GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.

There is a similar story for `AssocItemKind` and `ForeignItemKind`.

Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.

The commit is large but it's mostly obvious plumbing work. Some notable
things.

- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
  fields within some of the `ast::ItemKind` variants (specifically:
  `Struct`, `Union`, `Enum`). I might do that in a follow-up; this
  commit is big enough already.

- For the visitors: `FnKind` no longer needs an `ident` field because
  the `Fn` within how has one.

- In the parser, the `ItemInfo` typedef is no longer needed. It was used
  in various places to return an `Ident` alongside an `ItemKind`, but
  now the `Ident` (if present) is within the `ItemKind`.

- In a few places I renamed identifier variables called `name` (or
  `foo_name`) as `ident` (or `foo_ident`), to better match the type, and
  because `name` is normally used for `Symbol`s. It's confusing to see
  something like `foo_name.name`.
2025-04-01 14:08:57 +11:00
Nicholas Nethercote
a6a6d01bbc Use sym::dummy in one more place.
It makes it clearer that the symbol is unused and doesn't matter.
2025-04-01 07:34:23 +11:00