about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2025-08-13 22:01:02 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2025-08-14 09:53:49 +0300
commit9b797b9f7ac12a8ad6a2a5097b69e0216958709e (patch)
treece7c08346fca1956587f7d2b4925d19e0522e3d9
parentd682943396fdc0a8fcf907c570435d01a3035fe2 (diff)
downloadrust-9b797b9f7ac12a8ad6a2a5097b69e0216958709e.tar.gz
rust-9b797b9f7ac12a8ad6a2a5097b69e0216958709e.zip
resolve: Improve code reuse in typo candidate collection
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs25
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs51
-rw-r--r--tests/ui/hygiene/arguments.stderr3
-rw-r--r--tests/ui/hygiene/cross-crate-name-hiding-2.stderr5
-rw-r--r--tests/ui/hygiene/globs.stderr14
5 files changed, 52 insertions, 46 deletions
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 5f54411b463..c5fcbdfb42f 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1016,16 +1016,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         .emit()
     }
 
-    /// Lookup typo candidate in scope for a macro or import.
-    fn early_lookup_typo_candidate(
+    pub(crate) fn add_scope_set_candidates(
         &mut self,
+        suggestions: &mut Vec<TypoSuggestion>,
         scope_set: ScopeSet<'ra>,
         parent_scope: &ParentScope<'ra>,
-        ident: Ident,
+        ctxt: SyntaxContext,
         filter_fn: &impl Fn(Res) -> bool,
-    ) -> Option<TypoSuggestion> {
-        let mut suggestions = Vec::new();
-        let ctxt = ident.span.ctxt();
+    ) {
         self.cm().visit_scopes(scope_set, parent_scope, ctxt, |this, scope, use_prelude, _| {
             match scope {
                 Scope::DeriveHelpers(expn_id) => {
@@ -1055,7 +1053,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     }
                 }
                 Scope::Module(module, _) => {
-                    this.add_module_candidates(module, &mut suggestions, filter_fn, None);
+                    this.add_module_candidates(module, suggestions, filter_fn, None);
                 }
                 Scope::MacroUsePrelude => {
                     suggestions.extend(this.macro_use_prelude.iter().filter_map(
@@ -1113,6 +1111,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
             None::<()>
         });
+    }
+
+    /// Lookup typo candidate in scope for a macro or import.
+    fn early_lookup_typo_candidate(
+        &mut self,
+        scope_set: ScopeSet<'ra>,
+        parent_scope: &ParentScope<'ra>,
+        ident: Ident,
+        filter_fn: &impl Fn(Res) -> bool,
+    ) -> Option<TypoSuggestion> {
+        let mut suggestions = Vec::new();
+        let ctxt = ident.span.ctxt();
+        self.add_scope_set_candidates(&mut suggestions, scope_set, parent_scope, ctxt, filter_fn);
 
         // Make sure error reporting is deterministic.
         suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index c8cab5a0fe9..6a753b38035 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -38,8 +38,8 @@ use crate::late::{
 };
 use crate::ty::fast_reject::SimplifiedType;
 use crate::{
-    Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Resolver, Segment, errors,
-    path_names_to_string,
+    Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Resolver, ScopeSet, Segment,
+    errors, path_names_to_string,
 };
 
 type Res = def::Res<ast::NodeId>;
@@ -2458,45 +2458,30 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     }
                 }
 
+                if let RibKind::Module(module) = rib.kind
+                    && let ModuleKind::Block = module.kind
+                {
+                    self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
+                } else if let RibKind::Module(module) = rib.kind {
+                    // Encountered a module item, abandon ribs and look into that module and preludes.
+                    self.r.add_scope_set_candidates(
+                        &mut names,
+                        ScopeSet::Late(ns, module, None),
+                        &self.parent_scope,
+                        ctxt,
+                        filter_fn,
+                    );
+                    break;
+                }
+
                 if let RibKind::MacroDefinition(def) = rib.kind
                     && def == self.r.macro_def(ctxt)
                 {
                     // If an invocation of this macro created `ident`, give up on `ident`
                     // and switch to `ident`'s source from the macro definition.
                     ctxt.remove_mark();
-                    continue;
-                }
-
-                // Items in scope
-                if let RibKind::Module(module) = rib.kind {
-                    // Items from this module
-                    self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
-
-                    if let ModuleKind::Block = module.kind {
-                        // We can see through blocks
-                    } else {
-                        // Items from the prelude
-                        if !module.no_implicit_prelude {
-                            names.extend(self.r.extern_prelude.keys().flat_map(|ident| {
-                                let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
-                                filter_fn(res)
-                                    .then_some(TypoSuggestion::typo_from_ident(ident.0, res))
-                            }));
-
-                            if let Some(prelude) = self.r.prelude {
-                                self.r.add_module_candidates(prelude, &mut names, &filter_fn, None);
-                            }
-                        }
-                        break;
-                    }
                 }
             }
-            // Add primitive types to the mix
-            if filter_fn(Res::PrimTy(PrimTy::Bool)) {
-                names.extend(PrimTy::ALL.iter().map(|prim_ty| {
-                    TypoSuggestion::typo_from_name(prim_ty.name(), Res::PrimTy(*prim_ty))
-                }))
-            }
         } else {
             // Search in module.
             let mod_path = &path[..path.len() - 1];
diff --git a/tests/ui/hygiene/arguments.stderr b/tests/ui/hygiene/arguments.stderr
index 0d8d652b6f3..fe92daf6437 100644
--- a/tests/ui/hygiene/arguments.stderr
+++ b/tests/ui/hygiene/arguments.stderr
@@ -1,6 +1,9 @@
 error[E0412]: cannot find type `S` in this scope
   --> $DIR/arguments.rs:14:8
    |
+LL |         struct S;
+   |                - you might have meant to refer to this struct
+...
 LL |     m!(S, S);
    |        ^ not found in this scope
 
diff --git a/tests/ui/hygiene/cross-crate-name-hiding-2.stderr b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr
index a5d509fab99..fe3a12e93a7 100644
--- a/tests/ui/hygiene/cross-crate-name-hiding-2.stderr
+++ b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr
@@ -3,6 +3,11 @@ error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope
    |
 LL |     let x = MyStruct {};
    |             ^^^^^^^^ not found in this scope
+   |
+  ::: $DIR/auxiliary/use_by_macro.rs:15:1
+   |
+LL | x!(my_struct);
+   | ------------- you might have meant to refer to this struct
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/hygiene/globs.stderr b/tests/ui/hygiene/globs.stderr
index 31f25b182f1..85946bf34bc 100644
--- a/tests/ui/hygiene/globs.stderr
+++ b/tests/ui/hygiene/globs.stderr
@@ -48,7 +48,10 @@ error[E0425]: cannot find function `f` in this scope
   --> $DIR/globs.rs:61:12
    |
 LL | n!(f);
-   | ----- in this macro invocation
+   | -----
+   | |  |
+   | |  you might have meant to refer to this function
+   | in this macro invocation
 ...
 LL |                     $j();
    |                     -- due to this macro variable
@@ -56,15 +59,16 @@ LL |                     $j();
 LL |         n!(f);
    |            ^ not found in this scope
    |
-   = help: consider importing this function:
-           foo::f
    = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find function `f` in this scope
   --> $DIR/globs.rs:65:17
    |
 LL | n!(f);
-   | ----- in this macro invocation
+   | -----
+   | |  |
+   | |  you might have meant to refer to this function
+   | in this macro invocation
 ...
 LL |                     $j();
    |                     -- due to this macro variable
@@ -72,8 +76,6 @@ LL |                     $j();
 LL |                 f
    |                 ^ not found in this scope
    |
-   = help: consider importing this function:
-           foo::f
    = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors