From 4d3f051b3fc220d8f7a1c9927b666d9858458f68 Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 18 Jul 2025 10:31:59 +0000 Subject: [PATCH 1/6] introduce Scope::NonGlobModule and Scope::GlobModule --- compiler/rustc_resolve/src/diagnostics.rs | 8 +- compiler/rustc_resolve/src/ident.rs | 421 +++++++++++++++++----- compiler/rustc_resolve/src/lib.rs | 20 +- 3 files changed, 340 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index a437f86e37789..77505389ed74b 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1052,7 +1052,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } } - Scope::Module(module, _) => { + Scope::NonGlobModule(module, _) | Scope::GlobModule(module, _) => { this.add_module_candidates(module, suggestions, filter_fn, None); } Scope::MacroUsePrelude => { @@ -1476,9 +1476,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &parent_scope, ident.span.ctxt(), |this, scope, _use_prelude, _ctxt| { - let Scope::Module(m, _) = scope else { - return None; + let m = match scope { + Scope::NonGlobModule(module, _) | Scope::GlobModule(module, _) => module, + _ => return None, }; + for (_, resolution) in this.resolutions(m).borrow().iter() { let Some(binding) = resolution.borrow().best_binding() else { continue; diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index c1b3aff4e69f6..f0777f7dea70f 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -40,6 +40,18 @@ enum Shadowing { Unrestricted, } +bitflags::bitflags! { + #[derive(Clone, Copy, Debug)] + struct Flags: u8 { + const MACRO_RULES = 1 << 0; + const NON_GLOB_MODULE = 1 << 1; + const GLOB_MODULE = 1 << 2; + const MISC_SUGGEST_CRATE = 1 << 3; + const MISC_SUGGEST_SELF = 1 << 4; + const MISC_FROM_PRELUDE = 1 << 5; + } +} + impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// A generic scope visitor. /// Visits scopes in order to resolve some identifier in them or perform other actions. @@ -114,9 +126,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let module_and_extern_prelude = matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)); let extern_prelude = matches!(scope_set, ScopeSet::ExternPrelude); let mut scope = match ns { - _ if module_and_extern_prelude => Scope::Module(module, None), + _ if module_and_extern_prelude => Scope::NonGlobModule(module, None), _ if extern_prelude => Scope::ExternPreludeItems, - TypeNS | ValueNS => Scope::Module(module, None), + TypeNS | ValueNS => Scope::NonGlobModule(module, None), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; let mut ctxt = ctxt.normalize_to_macros_2_0(); @@ -143,7 +155,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } true } - Scope::Module(..) => true, + Scope::NonGlobModule(..) | Scope::GlobModule(..) => true, Scope::MacroUsePrelude => use_prelude || rust_2015, Scope::BuiltinAttrs => true, Scope::ExternPreludeItems | Scope::ExternPreludeFlags => { @@ -182,16 +194,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { MacroRulesScope::Invocation(invoc_id) => { Scope::MacroRules(self.invocation_parent_scopes[&invoc_id].macro_rules) } - MacroRulesScope::Empty => Scope::Module(module, None), + MacroRulesScope::Empty => Scope::NonGlobModule(module, None), }, - Scope::Module(..) if module_and_extern_prelude => match ns { - TypeNS => { - ctxt.adjust(ExpnId::root()); - Scope::ExternPreludeItems + Scope::NonGlobModule(..) | Scope::GlobModule(..) if module_and_extern_prelude => { + match ns { + TypeNS => { + ctxt.adjust(ExpnId::root()); + Scope::ExternPreludeItems + } + ValueNS | MacroNS => break, } - ValueNS | MacroNS => break, - }, - Scope::Module(module, prev_lint_id) => { + } + Scope::NonGlobModule(module, prev_lint_id) => { + use_prelude = !module.no_implicit_prelude; + Scope::GlobModule(module, prev_lint_id) + } + Scope::GlobModule(module, prev_lint_id) => { use_prelude = !module.no_implicit_prelude; let derive_fallback_lint_id = match scope_set { ScopeSet::Late(.., lint_id) => lint_id, @@ -199,7 +217,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; match self.hygienic_lexical_parent(module, &mut ctxt, derive_fallback_lint_id) { Some((parent_module, lint_id)) => { - Scope::Module(parent_module, lint_id.or(prev_lint_id)) + Scope::NonGlobModule(parent_module, lint_id.or(prev_lint_id)) } None => { ctxt.adjust(ExpnId::root()); @@ -392,17 +410,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ignore_binding: Option>, ignore_import: Option>, ) -> Result, Determinacy> { - bitflags::bitflags! { - #[derive(Clone, Copy)] - struct Flags: u8 { - const MACRO_RULES = 1 << 0; - const MODULE = 1 << 1; - const MISC_SUGGEST_CRATE = 1 << 2; - const MISC_SUGGEST_SELF = 1 << 3; - const MISC_FROM_PRELUDE = 1 << 4; - } - } - assert!(force || finalize.is_none()); // `finalize` implies `force` // Make sure `self`, `super` etc produce an error when passed to here. @@ -494,7 +501,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { MacroRulesScope::Invocation(_) => Err(Determinacy::Undetermined), _ => Err(Determinacy::Determined), }, - Scope::Module(module, derive_fallback_lint_id) => { + Scope::NonGlobModule(module, derive_fallback_lint_id) => { // FIXME: use `finalize_scope` here. let (adjusted_parent_scope, adjusted_finalize) = if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) { @@ -505,8 +512,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize.map(|f| Finalize { used: Used::Scope, ..f }), ) }; - let binding = this.reborrow().resolve_ident_in_module_unadjusted( - ModuleOrUniformRoot::Module(module), + + let binding = this.reborrow().resolve_ident_in_non_glob_module_unadjusted( + module, ident, ns, adjusted_parent_scope, @@ -519,6 +527,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ignore_binding, ignore_import, ); + match binding { Ok(binding) => { if let Some(lint_id) = derive_fallback_lint_id { @@ -533,14 +542,62 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }, ); } - let misc_flags = if module == this.graph_root { - Flags::MISC_SUGGEST_CRATE - } else if module.is_normal() { - Flags::MISC_SUGGEST_SELF - } else { - Flags::empty() - }; - Ok((binding, Flags::MODULE | misc_flags)) + + let misc_flags = this.create_module_misc_flags(module); + Ok((binding, Flags::NON_GLOB_MODULE | misc_flags)) + } + Err((Determinacy::Undetermined, Weak::No)) => { + return Some(Err(Determinacy::determined(force))); + } + Err((Determinacy::Undetermined, Weak::Yes)) => { + Err(Determinacy::Undetermined) + } + Err((Determinacy::Determined, _)) => Err(Determinacy::Determined), + } + } + Scope::GlobModule(module, derive_fallback_lint_id) => { + let (adjusted_parent_scope, finalize) = + if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) { + (parent_scope, finalize) + } else { + ( + &ParentScope { module, ..*parent_scope }, + finalize.map(|f| Finalize { used: Used::Scope, ..f }), + ) + }; + + let binding = this.reborrow().resolve_ident_in_glob_module_unadjusted( + module, + ident, + ns, + adjusted_parent_scope, + if matches!(scope_set, ScopeSet::Late(..)) { + Shadowing::Unrestricted + } else { + Shadowing::Restricted + }, + finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), + ignore_binding, + ignore_import, + ); + + match binding { + Ok(binding) => { + if let Some(lint_id) = derive_fallback_lint_id { + this.get_mut().lint_buffer.buffer_lint( + PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, + lint_id, + orig_ident.span, + BuiltinLintDiag::ProcMacroDeriveResolutionFallback { + span: orig_ident.span, + ns, + ident, + }, + ); + } + + let misc_flags = this.create_module_misc_flags(module); + Ok((binding, Flags::GLOB_MODULE | misc_flags)) } Err((Determinacy::Undetermined, Weak::No)) => { return Some(Err(Determinacy::determined(force))); @@ -650,7 +707,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let Some((innermost_binding, innermost_flags)) = innermost_result { // Found another solution, if the first one was "weak", report an error. let (res, innermost_res) = (binding.res(), innermost_binding.res()); - if res != innermost_res { + + // don't report ambiguity errors when we have a glob resolution with a + // non-glob innermost resolution. + let ignore_innermost_result = flags.contains(Flags::GLOB_MODULE) + && innermost_flags.contains(Flags::NON_GLOB_MODULE); + + if res != innermost_res && !ignore_innermost_result { let is_builtin = |res| { matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Builtin(..))) }; @@ -668,13 +731,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { { Some(AmbiguityKind::DeriveHelper) } else if innermost_flags.contains(Flags::MACRO_RULES) - && flags.contains(Flags::MODULE) + && (flags.contains(Flags::NON_GLOB_MODULE) + || flags.contains(Flags::GLOB_MODULE)) && !this.disambiguate_macro_rules_vs_modularized( innermost_binding, binding, ) || flags.contains(Flags::MACRO_RULES) - && innermost_flags.contains(Flags::MODULE) + && (innermost_flags.contains(Flags::NON_GLOB_MODULE) + || flags.contains(Flags::GLOB_MODULE)) && !this.disambiguate_macro_rules_vs_modularized( binding, innermost_binding, @@ -720,7 +785,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } Err(Determinacy::Determined) => {} - Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined, + Err(Determinacy::Undetermined) => { + if let Scope::NonGlobModule(..) = scope { + // we wait for Scope::GlobModule to determine `determinacy` + } else { + determinacy = Determinacy::Undetermined; + } + } } None @@ -739,6 +810,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Err(Determinacy::determined(determinacy == Determinacy::Determined || force)) } + fn create_module_misc_flags(&self, module: Module<'ra>) -> Flags { + if module == self.graph_root { + Flags::MISC_SUGGEST_CRATE + } else if module.is_normal() { + Flags::MISC_SUGGEST_SELF + } else { + Flags::empty() + } + } + #[instrument(level = "debug", skip(self))] pub(crate) fn maybe_resolve_ident_in_module<'r>( self: CmResolver<'r, 'ra, 'tcx>, @@ -865,6 +946,49 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } }; + match self.reborrow().resolve_ident_in_non_glob_module_unadjusted( + module, + ident, + ns, + parent_scope, + shadowing, + finalize, + ignore_binding, + ignore_import, + ) { + Ok(binding) => return Ok(binding), + Err((_, Weak::No)) => { + return Err((Determined, Weak::No)); + } + // no non-glob binding was found, check for glob binding + Err((_, Weak::Yes)) => {} + } + + self.reborrow().resolve_ident_in_glob_module_unadjusted( + module, + ident, + ns, + parent_scope, + shadowing, + finalize, + ignore_binding, + ignore_import, + ) + } + + fn resolve_ident_in_non_glob_module_unadjusted<'r>( + mut self: CmResolver<'r, 'ra, 'tcx>, + module: Module<'ra>, + ident: Ident, + ns: Namespace, + parent_scope: &ParentScope<'ra>, + shadowing: Shadowing, + finalize: Option, + // This binding should be ignored during in-module resolution, so that we don't get + // "self-confirming" import resolutions during import validation and checking. + ignore_binding: Option>, + _ignore_import: Option>, // not used, but kept for signature consistency + ) -> Result, (Determinacy, Weak)> { let key = BindingKey::new(ident, ns); // `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding // doesn't need to be mutable. It will fail when there is a cycle of imports, and without @@ -874,74 +998,134 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .try_borrow_mut() .map_err(|_| (Determined, Weak::No))?; - // If the primary binding is unusable, search further and return the shadowed glob - // binding if it exists. What we really want here is having two separate scopes in - // a module - one for non-globs and one for globs, but until that's done use this - // hack to avoid inconsistent resolution ICEs during import validation. - let binding = [resolution.non_glob_binding, resolution.glob_binding] - .into_iter() - .find_map(|binding| if binding == ignore_binding { None } else { binding }); + let check_usable = |this: CmResolver<'r, 'ra, 'tcx>, binding: NameBinding<'ra>| { + let usable = this.is_accessible_from(binding.vis, parent_scope.module); + if usable { Ok(binding) } else { Err((Determined, Weak::No)) } + }; - if let Some(finalize) = finalize { - return self.get_mut().finalize_module_binding( - ident, - binding, - if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None }, - parent_scope, - finalize, - shadowing, - ); + if let Some(binding) = resolution.non_glob_binding + && ignore_binding.map_or(true, |b| binding != b) + { + if let Some(finalize) = finalize { + return self.get_mut().finalize_non_glob_module_binding( + ident, + binding, + resolution.glob_binding, + parent_scope, + finalize, + shadowing, + ); + } else { + return check_usable(self, binding); + } } + Err((Determinacy::determined(finalize.is_some()), Weak::Yes)) + } + + fn resolve_ident_in_glob_module_unadjusted<'r>( + mut self: CmResolver<'r, 'ra, 'tcx>, + module: Module<'ra>, + ident: Ident, + ns: Namespace, + parent_scope: &ParentScope<'ra>, + shadowing: Shadowing, + finalize: Option, + // This binding should be ignored during in-module resolution, so that we don't get + // "self-confirming" import resolutions during import validation and checking. + ignore_binding: Option>, + ignore_import: Option>, + ) -> Result, (Determinacy, Weak)> { + let key = BindingKey::new(ident, ns); + let resolution = self + .resolution_or_default(module, key) + .try_borrow_mut() + .map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports. + let check_usable = |this: CmResolver<'r, 'ra, 'tcx>, binding: NameBinding<'ra>| { let usable = this.is_accessible_from(binding.vis, parent_scope.module); if usable { Ok(binding) } else { Err((Determined, Weak::No)) } }; - // Items and single imports are not shadowable, if we have one, then it's determined. - if let Some(binding) = binding - && !binding.is_glob_import() + if let Some(binding) = resolution.glob_binding + && ignore_binding.map_or(true, |b| binding != b) { - return check_usable(self, binding); - } - - // --- From now on we either have a glob resolution or no resolution. --- + if let Some(finalize) = finalize { + return self.get_mut().finalize_glob_module_binding( + ident, + binding, + parent_scope, + finalize, + shadowing, + ); + } - // Check if one of single imports can still define the name, - // if it can then our result is not determined and can be invalidated. - if self.reborrow().single_import_can_define_name( - &resolution, - binding, - ns, - ignore_import, - ignore_binding, - parent_scope, - ) { - return Err((Undetermined, Weak::No)); - } + // Check if a single import can still define the name, + // if it can then our result is not determined and can be invalidated. + if self.reborrow().single_import_can_define_name( + &resolution, + Some(binding), + ns, + ignore_import, + ignore_binding, + parent_scope, + ) { + return Err((Undetermined, Weak::No)); + } - // So we have a resolution that's from a glob import. This resolution is determined - // if it cannot be shadowed by some new item/import expanded from a macro. - // This happens either if there are no unexpanded macros, or expanded names cannot - // shadow globs (that happens in macro namespace or with restricted shadowing). - // - // Additionally, any macro in any module can plant names in the root module if it creates - // `macro_export` macros, so the root module effectively has unresolved invocations if any - // module has unresolved invocations. - // However, it causes resolution/expansion to stuck too often (#53144), so, to make - // progress, we have to ignore those potential unresolved invocations from other modules - // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted - // shadowing is enabled, see `macro_expanded_macro_export_errors`). - if let Some(binding) = binding { + // So we have a resolution that's from a glob import. This resolution is determined + // if it cannot be shadowed by some new item/import expanded from a macro. + // This happens either if there are no unexpanded macros, or expanded names cannot + // shadow globs (that happens in macro namespace or with restricted shadowing). + // + // Additionally, any macro in any module can plant names in the root module if it creates + // `macro_export` macros, so the root module effectively has unresolved invocations if any + // module has unresolved invocations. + // However, it causes resolution/expansion to stuck too often (#53144), so, to make + // progress, we have to ignore those potential unresolved invocations from other modules + // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted + // shadowing is enabled, see `macro_expanded_macro_export_errors`). if binding.determined() || ns == MacroNS || shadowing == Shadowing::Restricted { return check_usable(self, binding); } else { return Err((Undetermined, Weak::No)); } - } + } else if finalize.is_some() { + return Err((Determined, Weak::No)); + } else { + // Check if a single import can still define the name, + // if it can then our result is not determined and can be invalidated. + if self.reborrow().single_import_can_define_name( + &resolution, + None, + ns, + ignore_import, + ignore_binding, + parent_scope, + ) { + return Err((Undetermined, Weak::No)); + } - // --- From now on we have no resolution. --- + return Err(self.create_resolution_in_module_error( + module, + ident, + ns, + parent_scope, + ignore_binding, + ignore_import, + )); + } + } + fn create_resolution_in_module_error<'r>( + mut self: CmResolver<'r, 'ra, 'tcx>, + module: Module<'ra>, + ident: Ident, + ns: Namespace, + parent_scope: &ParentScope<'ra>, + ignore_binding: Option>, + ignore_import: Option>, + ) -> (Determinacy, Weak) { // Now we are in situation when new item/import can appear only from a glob or a macro // expansion. With restricted shadowing names from globs and macro expansions cannot // shadow names from outer scopes, so we can freely fallback from module search to search @@ -951,7 +1135,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Check if one of unexpanded macros can still define the name, // if it can then our "no resolution" result is not determined and can be invalidated. if !module.unexpanded_invocations.borrow().is_empty() { - return Err((Undetermined, Weak::Yes)); + return (Undetermined, Weak::Yes); } // Check if one of glob imports can still define the name, @@ -966,8 +1150,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let module = match glob_import.imported_module.get() { Some(ModuleOrUniformRoot::Module(module)) => module, Some(_) => continue, - None => return Err((Undetermined, Weak::Yes)), + None => return (Undetermined, Weak::Yes), }; + let tmp_parent_scope; let (mut adjusted_parent_scope, mut ident) = (parent_scope, ident.normalize_to_macros_2_0()); @@ -998,29 +1183,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { { continue; } - Ok(_) | Err((Undetermined, _)) => return Err((Undetermined, Weak::Yes)), + Ok(_) | Err((Undetermined, _)) => return (Undetermined, Weak::Yes), } } // No resolution and no one else can define the name - determinate error. - Err((Determined, Weak::No)) + (Determined, Weak::No) } - fn finalize_module_binding( + fn finalize_non_glob_module_binding( &mut self, ident: Ident, - binding: Option>, - shadowed_glob: Option>, + binding: NameBinding<'ra>, + glob_binding: Option>, parent_scope: &ParentScope<'ra>, finalize: Finalize, shadowing: Shadowing, ) -> Result, (Determinacy, Weak)> { let Finalize { path_span, report_private, used, root_span, .. } = finalize; - let Some(binding) = binding else { - return Err((Determined, Weak::No)); - }; - if !self.is_accessible_from(binding.vis, parent_scope.module) { if report_private { self.privacy_errors.push(PrivacyError { @@ -1038,7 +1219,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Forbid expanded shadowing to avoid time travel. - if let Some(shadowed_glob) = shadowed_glob + // FIXME it should be possible to output a MoreExpandedVsOuter ambiguity error + // instead of GlobVsExpanded, but that presumably has to be done in a different location. + if let Some(shadowed_glob) = glob_binding && shadowing == Shadowing::Restricted && binding.expansion != LocalExpnId::ROOT && binding.res() != shadowed_glob.res() @@ -1066,6 +1249,44 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return Ok(binding); } + fn finalize_glob_module_binding( + &mut self, + ident: Ident, + binding: NameBinding<'ra>, + parent_scope: &ParentScope<'ra>, + finalize: Finalize, + shadowing: Shadowing, + ) -> Result, (Determinacy, Weak)> { + let Finalize { path_span, report_private, used, root_span, .. } = finalize; + + if !self.is_accessible_from(binding.vis, parent_scope.module) { + if report_private { + self.privacy_errors.push(PrivacyError { + ident, + binding, + dedup_span: path_span, + outermost_res: None, + source: None, + parent_scope: *parent_scope, + single_nested: path_span != root_span, + }); + } else { + return Err((Determined, Weak::No)); + } + } + + if shadowing == Shadowing::Unrestricted + && binding.expansion != LocalExpnId::ROOT + && let NameBindingKind::Import { import, .. } = binding.kind + && matches!(import.kind, ImportKind::MacroExport) + { + self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); + } + + self.record_use(ident, binding, used); + return Ok(binding); + } + // Checks if a single import can define the `Ident` corresponding to `binding`. // This is used to check whether we can definitively accept a glob as a resolution. fn single_import_can_define_name<'r>( diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ca9c124fca63c..72d99d4f86857 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -126,11 +126,12 @@ enum Scope<'ra> { DeriveHelpersCompat, /// Textual `let`-like scopes introduced by `macro_rules!` items. MacroRules(MacroRulesScopeRef<'ra>), - /// Names declared in the given module. - /// The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK` - /// lint if it should be reported. - Module(Module<'ra>, Option), - /// Names introduced by `#[macro_use]` attributes on `extern crate` items. + // The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK` + // lint if it should be reported. + NonGlobModule(Module<'ra>, Option), + // The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK` + // lint if it should be reported. + GlobModule(Module<'ra>, Option), MacroUsePrelude, /// Built-in attributes. BuiltinAttrs, @@ -1881,10 +1882,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } + let mut non_glob_module_inserted = false; self.cm().visit_scopes(ScopeSet::All(TypeNS), parent_scope, ctxt, |this, scope, _, _| { match scope { - Scope::Module(module, _) => { + Scope::NonGlobModule(module, _) => { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); + non_glob_module_inserted = true; + } + Scope::GlobModule(module, _) => { + if !non_glob_module_inserted { + this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); + } } Scope::StdLibPrelude => { if let Some(module) = this.prelude { From 5caedeb1e4cc4f1a1130adfcec5ad4fcb79d6afe Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 6 Aug 2025 20:41:57 +0000 Subject: [PATCH 2/6] address review --- compiler/rustc_resolve/src/diagnostics.rs | 8 +++++--- compiler/rustc_resolve/src/ident.rs | 16 +++++++--------- compiler/rustc_resolve/src/lib.rs | 8 ++------ 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 77505389ed74b..ce2172aca6882 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1055,6 +1055,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Scope::NonGlobModule(module, _) | Scope::GlobModule(module, _) => { this.add_module_candidates(module, suggestions, filter_fn, None); } + Scope::GlobModule(..) => { + // already inserted in `Scope::NonGlobModule` arm + } Scope::MacroUsePrelude => { suggestions.extend(this.macro_use_prelude.iter().filter_map( |(name, binding)| { @@ -1476,9 +1479,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &parent_scope, ident.span.ctxt(), |this, scope, _use_prelude, _ctxt| { - let m = match scope { - Scope::NonGlobModule(module, _) | Scope::GlobModule(module, _) => module, - _ => return None, + let (Scope::NonGlobModule(m, _) | Scope::GlobModule(m, _)) = scope else { + return None; }; for (_, resolution) in this.resolutions(m).borrow().iter() { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index f0777f7dea70f..3e123e043438e 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -196,15 +196,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } MacroRulesScope::Empty => Scope::NonGlobModule(module, None), }, - Scope::NonGlobModule(..) | Scope::GlobModule(..) if module_and_extern_prelude => { - match ns { - TypeNS => { - ctxt.adjust(ExpnId::root()); - Scope::ExternPreludeItems - } - ValueNS | MacroNS => break, + Scope::GlobModule(..) if module_and_extern_prelude => match ns { + TypeNS => { + ctxt.adjust(ExpnId::root()); + Scope::ExternPreludeItems } - } + ValueNS | MacroNS => break, + }, Scope::NonGlobModule(module, prev_lint_id) => { use_prelude = !module.no_implicit_prelude; Scope::GlobModule(module, prev_lint_id) @@ -739,7 +737,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) || flags.contains(Flags::MACRO_RULES) && (innermost_flags.contains(Flags::NON_GLOB_MODULE) - || flags.contains(Flags::GLOB_MODULE)) + || innermost_flags.contains(Flags::GLOB_MODULE)) && !this.disambiguate_macro_rules_vs_modularized( binding, innermost_binding, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 72d99d4f86857..61ad54b36b939 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1882,17 +1882,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - let mut non_glob_module_inserted = false; self.cm().visit_scopes(ScopeSet::All(TypeNS), parent_scope, ctxt, |this, scope, _, _| { match scope { Scope::NonGlobModule(module, _) => { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); - non_glob_module_inserted = true; } - Scope::GlobModule(module, _) => { - if !non_glob_module_inserted { - this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); - } + Scope::GlobModule(..) => { + // already inserted in `Scope::NonGlobModule` arm } Scope::StdLibPrelude => { if let Some(module) = this.prelude { From 4d7fa7c5ed0735a13f8065a57dda9f0faa9562bd Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 8 Aug 2025 09:18:22 +0000 Subject: [PATCH 3/6] add ScopeSet::Module --- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/ident.rs | 153 +++++++++++----------- compiler/rustc_resolve/src/lib.rs | 8 ++ 3 files changed, 82 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index ce2172aca6882..3f6f27ce6a30c 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1052,7 +1052,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } } - Scope::NonGlobModule(module, _) | Scope::GlobModule(module, _) => { + Scope::NonGlobModule(module, _) => { this.add_module_candidates(module, suggestions, filter_fn, None); } Scope::GlobModule(..) => { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 3e123e043438e..0f83bfec22e4d 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -19,7 +19,7 @@ use crate::{ AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, CmResolver, Determinacy, Finalize, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError, - Resolver, Scope, ScopeSet, Segment, Used, Weak, errors, + Resolver, Scope, ScopeSet, Segment, Shadowing, Used, Weak, errors, }; #[derive(Copy, Clone)] @@ -34,12 +34,6 @@ impl From for bool { } } -#[derive(Debug, PartialEq, Clone, Copy)] -enum Shadowing { - Restricted, - Unrestricted, -} - bitflags::bitflags! { #[derive(Clone, Copy, Debug)] struct Flags: u8 { @@ -113,20 +107,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let (ns, macro_kind) = match scope_set { ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) + | ScopeSet::Module(_, ns, _) | ScopeSet::Late(ns, ..) => (ns, None), ScopeSet::ExternPrelude => (TypeNS, None), ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)), }; let module = match scope_set { // Start with the specified module. - ScopeSet::Late(_, module, _) | ScopeSet::ModuleAndExternPrelude(_, module) => module, + ScopeSet::Late(_, module, _) + | ScopeSet::ModuleAndExternPrelude(_, module) + | ScopeSet::Module(module, ..) => module, // Jump out of trait or enum modules, they do not act as scopes. _ => parent_scope.module.nearest_item_scope(), }; + + let module_scope = matches!(scope_set, ScopeSet::Module(..)); let module_and_extern_prelude = matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)); let extern_prelude = matches!(scope_set, ScopeSet::ExternPrelude); let mut scope = match ns { - _ if module_and_extern_prelude => Scope::NonGlobModule(module, None), + _ if (module_and_extern_prelude || module_scope) => Scope::NonGlobModule(module, None), _ if extern_prelude => Scope::ExternPreludeItems, TypeNS | ValueNS => Scope::NonGlobModule(module, None), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), @@ -203,6 +202,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } ValueNS | MacroNS => break, }, + Scope::GlobModule(..) if module_scope => break, Scope::NonGlobModule(module, prev_lint_id) => { use_prelude = !module.no_implicit_prelude; Scope::GlobModule(module, prev_lint_id) @@ -418,6 +418,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let (ns, macro_kind) = match scope_set { ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) + | ScopeSet::Module(_, ns, _) | ScopeSet::Late(ns, ..) => (ns, None), ScopeSet::ExternPrelude => (TypeNS, None), ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)), @@ -502,7 +503,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Scope::NonGlobModule(module, derive_fallback_lint_id) => { // FIXME: use `finalize_scope` here. let (adjusted_parent_scope, adjusted_finalize) = - if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) { + if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) + || matches!(scope_set, ScopeSet::Module(..)) + { (parent_scope, finalize) } else { ( @@ -516,10 +519,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, ns, adjusted_parent_scope, - if matches!(scope_set, ScopeSet::Late(..)) { - Shadowing::Unrestricted - } else { - Shadowing::Restricted + match scope_set { + ScopeSet::Late(..) => Shadowing::Unrestricted, + ScopeSet::Module(_, _, shadowing) => shadowing, + _ => Shadowing::Restricted, }, adjusted_finalize, ignore_binding, @@ -541,6 +544,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); } + // Don't visit Scope::GlobModule after successful resolution in + // Scope::NonGlobModule with ScopeSet::Module. + if matches!(scope_set, ScopeSet::Module(..)) { + return Some(Ok(binding)); + } + let misc_flags = this.create_module_misc_flags(module); Ok((binding, Flags::NON_GLOB_MODULE | misc_flags)) } @@ -550,12 +559,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Err((Determinacy::Undetermined, Weak::Yes)) => { Err(Determinacy::Undetermined) } - Err((Determinacy::Determined, _)) => Err(Determinacy::Determined), + Err((Determinacy::Determined, weak)) => { + // Only go through Glob Scope with `Weak::Yes` errors in ScopeSet::Module + if matches!(scope_set, ScopeSet::Module(..)) + && matches!(weak, Weak::No) + { + return Some(Err(Determinacy::Determined)); + } + + Err(Determinacy::Determined) + } } } Scope::GlobModule(module, derive_fallback_lint_id) => { let (adjusted_parent_scope, finalize) = - if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) { + if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) + || matches!(scope_set, ScopeSet::Module(..)) + { (parent_scope, finalize) } else { ( @@ -569,10 +589,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, ns, adjusted_parent_scope, - if matches!(scope_set, ScopeSet::Late(..)) { - Shadowing::Unrestricted - } else { - Shadowing::Restricted + match scope_set { + ScopeSet::Late(..) => Shadowing::Unrestricted, + ScopeSet::Module(_, _, shadowing) => shadowing, + _ => Shadowing::Restricted, }, finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), ignore_binding, @@ -828,7 +848,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ignore_import: Option>, ) -> Result, Determinacy> { self.resolve_ident_in_module(module, ident, ns, parent_scope, None, None, ignore_import) - .map_err(|(determinacy, _)| determinacy) } #[instrument(level = "debug", skip(self))] @@ -841,7 +860,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize: Option, ignore_binding: Option>, ignore_import: Option>, - ) -> Result, (Determinacy, Weak)> { + ) -> Result, Determinacy> { let tmp_parent_scope; let mut adjusted_parent_scope = parent_scope; match module { @@ -874,7 +893,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Invariant: if `finalize` is `Some`, expansion and import resolution must be complete. #[instrument(level = "debug", skip(self))] fn resolve_ident_in_module_unadjusted<'r>( - mut self: CmResolver<'r, 'ra, 'tcx>, + self: CmResolver<'r, 'ra, 'tcx>, module: ModuleOrUniformRoot<'ra>, ident: Ident, ns: Namespace, @@ -885,12 +904,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // "self-confirming" import resolutions during import validation and checking. ignore_binding: Option>, ignore_import: Option>, - ) -> Result, (Determinacy, Weak)> { - let module = match module { - ModuleOrUniformRoot::Module(module) => module, + ) -> Result, Determinacy> { + match module { + ModuleOrUniformRoot::Module(module) => self.early_resolve_ident_in_lexical_scope( + ident, + ScopeSet::Module(module, ns, shadowing), + parent_scope, + finalize, + finalize.is_some(), + ignore_binding, + ignore_import, + ), ModuleOrUniformRoot::ModuleAndExternPrelude(module) => { assert_eq!(shadowing, Shadowing::Unrestricted); - let binding = self.early_resolve_ident_in_lexical_scope( + self.early_resolve_ident_in_lexical_scope( ident, ScopeSet::ModuleAndExternPrelude(ns, module), parent_scope, @@ -898,15 +925,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize.is_some(), ignore_binding, ignore_import, - ); - return binding.map_err(|determinacy| (determinacy, Weak::No)); + ) } ModuleOrUniformRoot::ExternPrelude => { assert_eq!(shadowing, Shadowing::Unrestricted); return if ns != TypeNS { - Err((Determined, Weak::No)) + Err(Determined) } else { - let binding = self.early_resolve_ident_in_lexical_scope( + self.early_resolve_ident_in_lexical_scope( ident, ScopeSet::ExternPrelude, parent_scope, @@ -914,8 +940,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize.is_some(), ignore_binding, ignore_import, - ); - return binding.map_err(|determinacy| (determinacy, Weak::No)); + ) }; } ModuleOrUniformRoot::CurrentScope => { @@ -931,7 +956,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - let binding = self.early_resolve_ident_in_lexical_scope( + self.early_resolve_ident_in_lexical_scope( ident, ScopeSet::All(ns), parent_scope, @@ -939,39 +964,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize.is_some(), ignore_binding, ignore_import, - ); - return binding.map_err(|determinacy| (determinacy, Weak::No)); - } - }; - - match self.reborrow().resolve_ident_in_non_glob_module_unadjusted( - module, - ident, - ns, - parent_scope, - shadowing, - finalize, - ignore_binding, - ignore_import, - ) { - Ok(binding) => return Ok(binding), - Err((_, Weak::No)) => { - return Err((Determined, Weak::No)); + ) } - // no non-glob binding was found, check for glob binding - Err((_, Weak::Yes)) => {} } - - self.reborrow().resolve_ident_in_glob_module_unadjusted( - module, - ident, - ns, - parent_scope, - shadowing, - finalize, - ignore_binding, - ignore_import, - ) } fn resolve_ident_in_non_glob_module_unadjusted<'r>( @@ -1175,13 +1170,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); match result { - Err((Determined, _)) => continue, + Err(Determined) => continue, Ok(binding) if !self.is_accessible_from(binding.vis, glob_import.parent_scope.module) => { continue; } - Ok(_) | Err((Undetermined, _)) => return (Undetermined, Weak::Yes), + Ok(_) | Err(Undetermined) => return (Undetermined, Weak::Yes), } } @@ -1333,13 +1328,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ignore_binding, ignore_import, ) { - Err((Determined, _)) => continue, + Err(Determined) => continue, Ok(binding) if !self.is_accessible_from(binding.vis, single_import.parent_scope.module) => { continue; } - Ok(_) | Err((Undetermined, _)) => { + Ok(_) | Err(Undetermined) => { return true; } } @@ -1818,17 +1813,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } let binding = if let Some(module) = module { - self.reborrow() - .resolve_ident_in_module( - module, - ident, - ns, - parent_scope, - finalize, - ignore_binding, - ignore_import, - ) - .map_err(|(determinacy, _)| determinacy) + self.reborrow().resolve_ident_in_module( + module, + ident, + ns, + parent_scope, + finalize, + ignore_binding, + ignore_import, + ) } else if let Some(ribs) = ribs && let Some(TypeNS | ValueNS) = opt_ns { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 61ad54b36b939..f02a189f9ee70 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -147,6 +147,12 @@ enum Scope<'ra> { BuiltinTypes, } +#[derive(Debug, PartialEq, Clone, Copy)] +enum Shadowing { + Restricted, + Unrestricted, +} + /// Names from different contexts may want to visit different subsets of all specific scopes /// with different restrictions when looking up the resolution. #[derive(Clone, Copy, Debug)] @@ -162,6 +168,8 @@ enum ScopeSet<'ra> { /// All scopes with the given namespace, used for partially performing late resolution. /// The node id enables lints and is used for reporting them. Late(Namespace, Module<'ra>, Option), + /// Scope::NonGlobModule and Scope::GlobModule. + Module(Module<'ra>, Namespace, Shadowing), } /// Everything you need to know about a name's location to resolve it. From 2818f1db8bfe67aff8ddc927d255698c73bbeebb Mon Sep 17 00:00:00 2001 From: b-naber Date: Sat, 16 Aug 2025 18:24:44 +0000 Subject: [PATCH 4/6] address review --- compiler/rustc_resolve/src/ident.rs | 114 +++++++++------------------- compiler/rustc_resolve/src/lib.rs | 8 +- 2 files changed, 38 insertions(+), 84 deletions(-) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 0f83bfec22e4d..78b2bf3449631 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -19,7 +19,7 @@ use crate::{ AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, CmResolver, Determinacy, Finalize, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError, - Resolver, Scope, ScopeSet, Segment, Shadowing, Used, Weak, errors, + Resolver, Scope, ScopeSet, Segment, Used, Weak, errors, }; #[derive(Copy, Clone)] @@ -34,6 +34,12 @@ impl From for bool { } } +#[derive(Debug, PartialEq, Clone, Copy)] +enum Shadowing { + Restricted, + Unrestricted, +} + bitflags::bitflags! { #[derive(Clone, Copy, Debug)] struct Flags: u8 { @@ -107,7 +113,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let (ns, macro_kind) = match scope_set { ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) - | ScopeSet::Module(_, ns, _) + | ScopeSet::Module(ns, ..) | ScopeSet::Late(ns, ..) => (ns, None), ScopeSet::ExternPrelude => (TypeNS, None), ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)), @@ -116,7 +122,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Start with the specified module. ScopeSet::Late(_, module, _) | ScopeSet::ModuleAndExternPrelude(_, module) - | ScopeSet::Module(module, ..) => module, + | ScopeSet::Module(_, module) => module, // Jump out of trait or enum modules, they do not act as scopes. _ => parent_scope.module.nearest_item_scope(), }; @@ -125,7 +131,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let module_and_extern_prelude = matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)); let extern_prelude = matches!(scope_set, ScopeSet::ExternPrelude); let mut scope = match ns { - _ if (module_and_extern_prelude || module_scope) => Scope::NonGlobModule(module, None), + _ if module_and_extern_prelude || module_scope => Scope::NonGlobModule(module, None), _ if extern_prelude => Scope::ExternPreludeItems, TypeNS | ValueNS => Scope::NonGlobModule(module, None), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), @@ -355,7 +361,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, ns, parent_scope, - Shadowing::Unrestricted, finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), ignore_binding, None, @@ -418,7 +423,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let (ns, macro_kind) = match scope_set { ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) - | ScopeSet::Module(_, ns, _) + | ScopeSet::Module(ns, ..) | ScopeSet::Late(ns, ..) => (ns, None), ScopeSet::ExternPrelude => (TypeNS, None), ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)), @@ -520,13 +525,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ns, adjusted_parent_scope, match scope_set { - ScopeSet::Late(..) => Shadowing::Unrestricted, - ScopeSet::Module(_, _, shadowing) => shadowing, + ScopeSet::Late(..) | ScopeSet::Module(..) => { + Shadowing::Unrestricted + } _ => Shadowing::Restricted, }, adjusted_finalize, ignore_binding, - ignore_import, ); match binding { @@ -590,8 +595,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ns, adjusted_parent_scope, match scope_set { - ScopeSet::Late(..) => Shadowing::Unrestricted, - ScopeSet::Module(_, _, shadowing) => shadowing, + ScopeSet::Late(..) | ScopeSet::Module(..) => { + Shadowing::Unrestricted + } _ => Shadowing::Restricted, }, finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), @@ -665,7 +671,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, ns, parent_scope, - Shadowing::Unrestricted, None, ignore_binding, ignore_import, @@ -883,7 +888,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, ns, adjusted_parent_scope, - Shadowing::Unrestricted, finalize, ignore_binding, ignore_import, @@ -898,7 +902,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident: Ident, ns: Namespace, parent_scope: &ParentScope<'ra>, - shadowing: Shadowing, finalize: Option, // This binding should be ignored during in-module resolution, so that we don't get // "self-confirming" import resolutions during import validation and checking. @@ -908,16 +911,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match module { ModuleOrUniformRoot::Module(module) => self.early_resolve_ident_in_lexical_scope( ident, - ScopeSet::Module(module, ns, shadowing), + ScopeSet::Module(ns, module), parent_scope, finalize, finalize.is_some(), ignore_binding, ignore_import, ), - ModuleOrUniformRoot::ModuleAndExternPrelude(module) => { - assert_eq!(shadowing, Shadowing::Unrestricted); - self.early_resolve_ident_in_lexical_scope( + ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self + .early_resolve_ident_in_lexical_scope( ident, ScopeSet::ModuleAndExternPrelude(ns, module), parent_scope, @@ -925,10 +927,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize.is_some(), ignore_binding, ignore_import, - ) - } + ), ModuleOrUniformRoot::ExternPrelude => { - assert_eq!(shadowing, Shadowing::Unrestricted); return if ns != TypeNS { Err(Determined) } else { @@ -944,7 +944,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; } ModuleOrUniformRoot::CurrentScope => { - assert_eq!(shadowing, Shadowing::Unrestricted); if ns == TypeNS { if ident.name == kw::Crate || ident.name == kw::DollarCrate { let module = self.resolve_crate_root(ident); @@ -980,7 +979,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // This binding should be ignored during in-module resolution, so that we don't get // "self-confirming" import resolutions during import validation and checking. ignore_binding: Option>, - _ignore_import: Option>, // not used, but kept for signature consistency ) -> Result, (Determinacy, Weak)> { let key = BindingKey::new(ident, ns); // `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding @@ -991,16 +989,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .try_borrow_mut() .map_err(|_| (Determined, Weak::No))?; - let check_usable = |this: CmResolver<'r, 'ra, 'tcx>, binding: NameBinding<'ra>| { - let usable = this.is_accessible_from(binding.vis, parent_scope.module); - if usable { Ok(binding) } else { Err((Determined, Weak::No)) } - }; - if let Some(binding) = resolution.non_glob_binding && ignore_binding.map_or(true, |b| binding != b) { if let Some(finalize) = finalize { - return self.get_mut().finalize_non_glob_module_binding( + return self.get_mut().finalize_module_binding( ident, binding, resolution.glob_binding, @@ -1009,7 +1002,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { shadowing, ); } else { - return check_usable(self, binding); + let usable = self.is_accessible_from(binding.vis, parent_scope.module); + if usable { + return Ok(binding); + } else { + return Err((Determined, Weak::No)); + }; } } @@ -1035,18 +1033,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .try_borrow_mut() .map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports. - let check_usable = |this: CmResolver<'r, 'ra, 'tcx>, binding: NameBinding<'ra>| { - let usable = this.is_accessible_from(binding.vis, parent_scope.module); - if usable { Ok(binding) } else { Err((Determined, Weak::No)) } - }; - if let Some(binding) = resolution.glob_binding && ignore_binding.map_or(true, |b| binding != b) { if let Some(finalize) = finalize { - return self.get_mut().finalize_glob_module_binding( + return self.get_mut().finalize_module_binding( ident, binding, + None, parent_scope, finalize, shadowing, @@ -1079,7 +1073,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted // shadowing is enabled, see `macro_expanded_macro_export_errors`). if binding.determined() || ns == MacroNS || shadowing == Shadowing::Restricted { - return check_usable(self, binding); + let usable = self.is_accessible_from(binding.vis, parent_scope.module); + if usable { + return Ok(binding); + } else { + return Err((Determined, Weak::No)); + }; } else { return Err((Undetermined, Weak::No)); } @@ -1163,7 +1162,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ident, ns, adjusted_parent_scope, - Shadowing::Unrestricted, None, ignore_binding, ignore_import, @@ -1184,7 +1182,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (Determined, Weak::No) } - fn finalize_non_glob_module_binding( + fn finalize_module_binding( &mut self, ident: Ident, binding: NameBinding<'ra>, @@ -1242,44 +1240,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return Ok(binding); } - fn finalize_glob_module_binding( - &mut self, - ident: Ident, - binding: NameBinding<'ra>, - parent_scope: &ParentScope<'ra>, - finalize: Finalize, - shadowing: Shadowing, - ) -> Result, (Determinacy, Weak)> { - let Finalize { path_span, report_private, used, root_span, .. } = finalize; - - if !self.is_accessible_from(binding.vis, parent_scope.module) { - if report_private { - self.privacy_errors.push(PrivacyError { - ident, - binding, - dedup_span: path_span, - outermost_res: None, - source: None, - parent_scope: *parent_scope, - single_nested: path_span != root_span, - }); - } else { - return Err((Determined, Weak::No)); - } - } - - if shadowing == Shadowing::Unrestricted - && binding.expansion != LocalExpnId::ROOT - && let NameBindingKind::Import { import, .. } = binding.kind - && matches!(import.kind, ImportKind::MacroExport) - { - self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); - } - - self.record_use(ident, binding, used); - return Ok(binding); - } - // Checks if a single import can define the `Ident` corresponding to `binding`. // This is used to check whether we can definitively accept a glob as a resolution. fn single_import_can_define_name<'r>( diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f02a189f9ee70..f212e838118bc 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -147,12 +147,6 @@ enum Scope<'ra> { BuiltinTypes, } -#[derive(Debug, PartialEq, Clone, Copy)] -enum Shadowing { - Restricted, - Unrestricted, -} - /// Names from different contexts may want to visit different subsets of all specific scopes /// with different restrictions when looking up the resolution. #[derive(Clone, Copy, Debug)] @@ -169,7 +163,7 @@ enum ScopeSet<'ra> { /// The node id enables lints and is used for reporting them. Late(Namespace, Module<'ra>, Option), /// Scope::NonGlobModule and Scope::GlobModule. - Module(Module<'ra>, Namespace, Shadowing), + Module(Namespace, Module<'ra>), } /// Everything you need to know about a name's location to resolve it. From cef2b26aecf9380bad1af44d55e6298634c3e004 Mon Sep 17 00:00:00 2001 From: b-naber Date: Sat, 16 Aug 2025 18:58:11 +0000 Subject: [PATCH 5/6] don't stop after successful non-glob resolution --- compiler/rustc_resolve/src/ident.rs | 6 ---- tests/ui/imports/imports.rs | 3 +- tests/ui/imports/imports.stderr | 43 ++++++++++++++++++++++++++++ tests/ui/resolve/issue-109153.rs | 1 + tests/ui/resolve/issue-109153.stderr | 22 +++++++++++++- 5 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 tests/ui/imports/imports.stderr diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 78b2bf3449631..01fd802acc579 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -549,12 +549,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); } - // Don't visit Scope::GlobModule after successful resolution in - // Scope::NonGlobModule with ScopeSet::Module. - if matches!(scope_set, ScopeSet::Module(..)) { - return Some(Ok(binding)); - } - let misc_flags = this.create_module_misc_flags(module); Ok((binding, Flags::NON_GLOB_MODULE | misc_flags)) } diff --git a/tests/ui/imports/imports.rs b/tests/ui/imports/imports.rs index b5c25eb044724..e3ef388a86622 100644 --- a/tests/ui/imports/imports.rs +++ b/tests/ui/imports/imports.rs @@ -1,4 +1,3 @@ -//@ run-pass #![allow(unused)] // Like other items, private imports can be imported and used non-lexically in paths. @@ -22,6 +21,7 @@ fn g() { use crate::bar::*; fn f() -> bool { true } let _: bool = f(); + //~^ ERROR `f` is ambiguous } fn h() { @@ -29,6 +29,7 @@ fn h() { use crate::bar::*; use crate::f; let _: bool = f(); + //~^ ERROR `f` is ambiguous } // Here, there appears to be shadowing but isn't because of namespaces. diff --git a/tests/ui/imports/imports.stderr b/tests/ui/imports/imports.stderr new file mode 100644 index 0000000000000..3267611231280 --- /dev/null +++ b/tests/ui/imports/imports.stderr @@ -0,0 +1,43 @@ +error[E0659]: `f` is ambiguous + --> $DIR/imports.rs:23:19 + | +LL | let _: bool = f(); + | ^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `f` could refer to the function imported here + --> $DIR/imports.rs:20:9 + | +LL | use crate::foo::*; + | ^^^^^^^^^^^^^ + = help: consider adding an explicit import of `f` to disambiguate +note: `f` could also refer to the function imported here + --> $DIR/imports.rs:21:9 + | +LL | use crate::bar::*; + | ^^^^^^^^^^^^^ + = help: consider adding an explicit import of `f` to disambiguate + +error[E0659]: `f` is ambiguous + --> $DIR/imports.rs:31:19 + | +LL | let _: bool = f(); + | ^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `f` could refer to the function imported here + --> $DIR/imports.rs:28:9 + | +LL | use crate::foo::*; + | ^^^^^^^^^^^^^ + = help: consider adding an explicit import of `f` to disambiguate +note: `f` could also refer to the function imported here + --> $DIR/imports.rs:29:9 + | +LL | use crate::bar::*; + | ^^^^^^^^^^^^^ + = help: consider adding an explicit import of `f` to disambiguate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/resolve/issue-109153.rs b/tests/ui/resolve/issue-109153.rs index bff6c911236e6..1bfb5f2adb49f 100644 --- a/tests/ui/resolve/issue-109153.rs +++ b/tests/ui/resolve/issue-109153.rs @@ -10,5 +10,6 @@ mod foo { use bar::bar; //~ ERROR `bar` is ambiguous use bar::*; +//~^ ERROR `bar` is ambiguous fn main() { } diff --git a/tests/ui/resolve/issue-109153.stderr b/tests/ui/resolve/issue-109153.stderr index da95029f6e783..9d703bdfd2ded 100644 --- a/tests/ui/resolve/issue-109153.stderr +++ b/tests/ui/resolve/issue-109153.stderr @@ -18,6 +18,26 @@ LL | use bar::*; | ^^^^^^ = help: consider adding an explicit import of `bar` to disambiguate -error: aborting due to 1 previous error +error[E0659]: `bar` is ambiguous + --> $DIR/issue-109153.rs:12:5 + | +LL | use bar::*; + | ^^^ ambiguous name + | + = note: ambiguous because of multiple glob imports of a name in the same module +note: `bar` could refer to the module imported here + --> $DIR/issue-109153.rs:1:5 + | +LL | use foo::*; + | ^^^^^^ + = help: consider adding an explicit import of `bar` to disambiguate +note: `bar` could also refer to the module imported here + --> $DIR/issue-109153.rs:12:5 + | +LL | use bar::*; + | ^^^^^^ + = help: consider adding an explicit import of `bar` to disambiguate + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0659`. From 6104053636b51baedd732e0fcd67f21c94508cfe Mon Sep 17 00:00:00 2001 From: b-naber Date: Sat, 16 Aug 2025 19:25:13 +0000 Subject: [PATCH 6/6] remove ignore_innermost --- compiler/rustc_resolve/src/ident.rs | 7 +--- .../imports/import-after-macro-expand-10.rs | 3 +- .../import-after-macro-expand-10.stderr | 23 +++++++++++++ .../imports/import-after-macro-expand-11.rs | 3 +- .../import-after-macro-expand-11.stderr | 23 +++++++++++++ .../imports/import-after-macro-expand-13.rs | 2 +- .../import-after-macro-expand-13.stderr | 23 +++++++++++++ .../imports/import-after-macro-expand-14.rs | 3 +- .../import-after-macro-expand-14.stderr | 23 +++++++++++++ .../ui/imports/import-after-macro-expand-2.rs | 2 +- .../import-after-macro-expand-2.stderr | 25 ++++++++++++++ .../ui/imports/import-after-macro-expand-6.rs | 2 +- .../import-after-macro-expand-6.stderr | 23 +++++++++++++ .../ui/imports/import-after-macro-expand-9.rs | 3 +- .../import-after-macro-expand-9.stderr | 23 +++++++++++++ tests/ui/imports/issue-114682-1.rs | 1 + tests/ui/imports/issue-114682-1.stderr | 28 +++++++++++++++- .../local-modularized-tricky-fail-1.rs | 1 + .../local-modularized-tricky-fail-1.stderr | 32 ++++++++++++++++-- tests/ui/imports/macro-paths.rs | 1 + tests/ui/imports/macro-paths.stderr | 28 +++++++++++++--- tests/ui/imports/macros.rs | 1 + tests/ui/imports/macros.stderr | 30 ++++++++++++++--- tests/ui/underscore-imports/shadow.rs | 3 +- tests/ui/underscore-imports/shadow.stderr | 33 ++++++++++++++++--- 25 files changed, 310 insertions(+), 36 deletions(-) create mode 100644 tests/ui/imports/import-after-macro-expand-10.stderr create mode 100644 tests/ui/imports/import-after-macro-expand-11.stderr create mode 100644 tests/ui/imports/import-after-macro-expand-13.stderr create mode 100644 tests/ui/imports/import-after-macro-expand-14.stderr create mode 100644 tests/ui/imports/import-after-macro-expand-2.stderr create mode 100644 tests/ui/imports/import-after-macro-expand-6.stderr create mode 100644 tests/ui/imports/import-after-macro-expand-9.stderr diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 01fd802acc579..b12f8cc71ecdf 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -725,12 +725,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Found another solution, if the first one was "weak", report an error. let (res, innermost_res) = (binding.res(), innermost_binding.res()); - // don't report ambiguity errors when we have a glob resolution with a - // non-glob innermost resolution. - let ignore_innermost_result = flags.contains(Flags::GLOB_MODULE) - && innermost_flags.contains(Flags::NON_GLOB_MODULE); - - if res != innermost_res && !ignore_innermost_result { + if res != innermost_res { let is_builtin = |res| { matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Builtin(..))) }; diff --git a/tests/ui/imports/import-after-macro-expand-10.rs b/tests/ui/imports/import-after-macro-expand-10.rs index eb04936a5feb7..9ca90babe936d 100644 --- a/tests/ui/imports/import-after-macro-expand-10.rs +++ b/tests/ui/imports/import-after-macro-expand-10.rs @@ -1,5 +1,3 @@ -//@ check-pass - mod b { pub mod http { pub struct HeaderMap; @@ -14,4 +12,5 @@ use crate::b::*; fn main() { let h: crate::b::HeaderMap = HeaderMap; + //~^ ERROR ambiguous } diff --git a/tests/ui/imports/import-after-macro-expand-10.stderr b/tests/ui/imports/import-after-macro-expand-10.stderr new file mode 100644 index 0000000000000..1948c14d766f0 --- /dev/null +++ b/tests/ui/imports/import-after-macro-expand-10.stderr @@ -0,0 +1,23 @@ +error[E0659]: `HeaderMap` is ambiguous + --> $DIR/import-after-macro-expand-10.rs:14:22 + | +LL | let h: crate::b::HeaderMap = HeaderMap; + | ^^^^^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `HeaderMap` could refer to the struct defined here + --> $DIR/import-after-macro-expand-10.rs:8:5 + | +LL | pub struct HeaderMap; + | ^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::HeaderMap` to refer to this struct unambiguously +note: `HeaderMap` could also refer to the struct imported here + --> $DIR/import-after-macro-expand-10.rs:6:13 + | +LL | pub use self::http::*; + | ^^^^^^^^^^^^^ + = help: use `self::HeaderMap` to refer to this struct unambiguously + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/import-after-macro-expand-11.rs b/tests/ui/imports/import-after-macro-expand-11.rs index 897c3001cc928..5c515bd3e8f0f 100644 --- a/tests/ui/imports/import-after-macro-expand-11.rs +++ b/tests/ui/imports/import-after-macro-expand-11.rs @@ -1,5 +1,3 @@ -//@ check-pass - #[derive(Debug)] struct H; @@ -14,6 +12,7 @@ mod p { fn f() { let h: crate::p::H = H; + //~^ ERROR ambiguous } } } diff --git a/tests/ui/imports/import-after-macro-expand-11.stderr b/tests/ui/imports/import-after-macro-expand-11.stderr new file mode 100644 index 0000000000000..c8affc701c714 --- /dev/null +++ b/tests/ui/imports/import-after-macro-expand-11.stderr @@ -0,0 +1,23 @@ +error[E0659]: `H` is ambiguous + --> $DIR/import-after-macro-expand-11.rs:14:29 + | +LL | let h: crate::p::H = H; + | ^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `H` could refer to the struct defined here + --> $DIR/import-after-macro-expand-11.rs:8:5 + | +LL | struct H; + | ^^^^^^^^^ + = help: use `self::H` to refer to this struct unambiguously +note: `H` could also refer to the struct imported here + --> $DIR/import-after-macro-expand-11.rs:5:9 + | +LL | use super::*; + | ^^^^^^^^ + = help: use `self::H` to refer to this struct unambiguously + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/import-after-macro-expand-13.rs b/tests/ui/imports/import-after-macro-expand-13.rs index 016d897732d9f..ba2cf2561c273 100644 --- a/tests/ui/imports/import-after-macro-expand-13.rs +++ b/tests/ui/imports/import-after-macro-expand-13.rs @@ -1,4 +1,3 @@ -//@ check-pass // similar as `import-after-macro-expand-6.rs` use crate::a::HeaderMap; @@ -19,4 +18,5 @@ mod a { fn main() { let h: crate::b::HeaderMap = HeaderMap; + //~^ ERROR ambiguous } diff --git a/tests/ui/imports/import-after-macro-expand-13.stderr b/tests/ui/imports/import-after-macro-expand-13.stderr new file mode 100644 index 0000000000000..3dc1e5e19a4e9 --- /dev/null +++ b/tests/ui/imports/import-after-macro-expand-13.stderr @@ -0,0 +1,23 @@ +error[E0659]: `HeaderMap` is ambiguous + --> $DIR/import-after-macro-expand-13.rs:20:22 + | +LL | let h: crate::b::HeaderMap = HeaderMap; + | ^^^^^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `HeaderMap` could refer to the struct defined here + --> $DIR/import-after-macro-expand-13.rs:12:5 + | +LL | pub struct HeaderMap; + | ^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::HeaderMap` to refer to this struct unambiguously +note: `HeaderMap` could also refer to the struct imported here + --> $DIR/import-after-macro-expand-13.rs:10:13 + | +LL | pub use self::http::*; + | ^^^^^^^^^^^^^ + = help: use `self::HeaderMap` to refer to this struct unambiguously + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/import-after-macro-expand-14.rs b/tests/ui/imports/import-after-macro-expand-14.rs index 0af312f375efa..c78868353c653 100644 --- a/tests/ui/imports/import-after-macro-expand-14.rs +++ b/tests/ui/imports/import-after-macro-expand-14.rs @@ -1,5 +1,3 @@ -//@ check-pass - use crate::a::HeaderMap; mod b { @@ -19,4 +17,5 @@ mod a { fn main() { let h: crate::b::HeaderMap = HeaderMap; + //~^ ERROR ambiguous } diff --git a/tests/ui/imports/import-after-macro-expand-14.stderr b/tests/ui/imports/import-after-macro-expand-14.stderr new file mode 100644 index 0000000000000..9e899170caff2 --- /dev/null +++ b/tests/ui/imports/import-after-macro-expand-14.stderr @@ -0,0 +1,23 @@ +error[E0659]: `HeaderMap` is ambiguous + --> $DIR/import-after-macro-expand-14.rs:19:22 + | +LL | let h: crate::b::HeaderMap = HeaderMap; + | ^^^^^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `HeaderMap` could refer to the struct defined here + --> $DIR/import-after-macro-expand-14.rs:11:5 + | +LL | pub struct HeaderMap; + | ^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::HeaderMap` to refer to this struct unambiguously +note: `HeaderMap` could also refer to the struct imported here + --> $DIR/import-after-macro-expand-14.rs:9:13 + | +LL | pub use self::http::*; + | ^^^^^^^^^^^^^ + = help: use `self::HeaderMap` to refer to this struct unambiguously + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/import-after-macro-expand-2.rs b/tests/ui/imports/import-after-macro-expand-2.rs index f0b5fbf02d90d..7a5eeabb6a4e3 100644 --- a/tests/ui/imports/import-after-macro-expand-2.rs +++ b/tests/ui/imports/import-after-macro-expand-2.rs @@ -1,4 +1,3 @@ -//@ check-pass // https://github.com/rust-lang/rust/issues/56593#issuecomment-1133174514 use thing::*; @@ -13,6 +12,7 @@ mod tests { fn test_thing() { let thing: crate::Thing = Thing::Foo; + //~^ ERROR ambiguous } } diff --git a/tests/ui/imports/import-after-macro-expand-2.stderr b/tests/ui/imports/import-after-macro-expand-2.stderr new file mode 100644 index 0000000000000..d77c5ad729fb5 --- /dev/null +++ b/tests/ui/imports/import-after-macro-expand-2.stderr @@ -0,0 +1,25 @@ +error[E0659]: `Thing` is ambiguous + --> $DIR/import-after-macro-expand-2.rs:14:27 + | +LL | let thing: crate::Thing = Thing::Foo; + | ^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `Thing` could refer to the enum defined here + --> $DIR/import-after-macro-expand-2.rs:6:1 + | +LL | / pub enum Thing { +LL | | Foo +LL | | } + | |_^ + = help: use `crate::Thing` to refer to this enum unambiguously +note: `Thing` could also refer to the enum imported here + --> $DIR/import-after-macro-expand-2.rs:3:5 + | +LL | use thing::*; + | ^^^^^^^^ + = help: use `crate::Thing` to refer to this enum unambiguously + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/import-after-macro-expand-6.rs b/tests/ui/imports/import-after-macro-expand-6.rs index 73dce5985a841..60e4cd0a27510 100644 --- a/tests/ui/imports/import-after-macro-expand-6.rs +++ b/tests/ui/imports/import-after-macro-expand-6.rs @@ -1,4 +1,3 @@ -//@ check-pass // https://github.com/rust-lang/rust/pull/113099#issuecomment-1633574396 pub mod a { @@ -19,4 +18,5 @@ use crate::a::HeaderMap; fn main() { let h: crate::b::HeaderMap = HeaderMap; + //~^ ERROR ambiguous } diff --git a/tests/ui/imports/import-after-macro-expand-6.stderr b/tests/ui/imports/import-after-macro-expand-6.stderr new file mode 100644 index 0000000000000..a71c82cc534fd --- /dev/null +++ b/tests/ui/imports/import-after-macro-expand-6.stderr @@ -0,0 +1,23 @@ +error[E0659]: `HeaderMap` is ambiguous + --> $DIR/import-after-macro-expand-6.rs:20:22 + | +LL | let h: crate::b::HeaderMap = HeaderMap; + | ^^^^^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `HeaderMap` could refer to the struct defined here + --> $DIR/import-after-macro-expand-6.rs:14:5 + | +LL | pub struct HeaderMap; + | ^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::HeaderMap` to refer to this struct unambiguously +note: `HeaderMap` could also refer to the struct imported here + --> $DIR/import-after-macro-expand-6.rs:12:13 + | +LL | pub use self::http::*; + | ^^^^^^^^^^^^^ + = help: use `self::HeaderMap` to refer to this struct unambiguously + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/import-after-macro-expand-9.rs b/tests/ui/imports/import-after-macro-expand-9.rs index 5caac06e7b984..8df7be0809c9e 100644 --- a/tests/ui/imports/import-after-macro-expand-9.rs +++ b/tests/ui/imports/import-after-macro-expand-9.rs @@ -1,5 +1,3 @@ -//@ check-pass - use crate::b::*; mod b { @@ -14,4 +12,5 @@ mod b { fn main() { let h: crate::b::HeaderMap = HeaderMap; + //~^ ERROR ambiguous } diff --git a/tests/ui/imports/import-after-macro-expand-9.stderr b/tests/ui/imports/import-after-macro-expand-9.stderr new file mode 100644 index 0000000000000..8217a95b164f3 --- /dev/null +++ b/tests/ui/imports/import-after-macro-expand-9.stderr @@ -0,0 +1,23 @@ +error[E0659]: `HeaderMap` is ambiguous + --> $DIR/import-after-macro-expand-9.rs:14:22 + | +LL | let h: crate::b::HeaderMap = HeaderMap; + | ^^^^^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `HeaderMap` could refer to the struct defined here + --> $DIR/import-after-macro-expand-9.rs:10:5 + | +LL | pub struct HeaderMap; + | ^^^^^^^^^^^^^^^^^^^^^ + = help: use `self::HeaderMap` to refer to this struct unambiguously +note: `HeaderMap` could also refer to the struct imported here + --> $DIR/import-after-macro-expand-9.rs:8:13 + | +LL | pub use self::http::*; + | ^^^^^^^^^^^^^ + = help: use `self::HeaderMap` to refer to this struct unambiguously + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/issue-114682-1.rs b/tests/ui/imports/issue-114682-1.rs index 88fe05e51444d..7640915e7d9b8 100644 --- a/tests/ui/imports/issue-114682-1.rs +++ b/tests/ui/imports/issue-114682-1.rs @@ -22,4 +22,5 @@ mac!(); fn main() { A!(); //~^ ERROR `A` is ambiguous + //~^^ ERROR `A` is ambiguous } diff --git a/tests/ui/imports/issue-114682-1.stderr b/tests/ui/imports/issue-114682-1.stderr index 85fb7f7919e4e..de8dc6cfb9ff5 100644 --- a/tests/ui/imports/issue-114682-1.stderr +++ b/tests/ui/imports/issue-114682-1.stderr @@ -23,6 +23,32 @@ LL | pub use m::*; = help: consider adding an explicit import of `A` to disambiguate = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error +error[E0659]: `A` is ambiguous + --> $DIR/issue-114682-1.rs:23:5 + | +LL | A!(); + | ^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `A` could refer to the macro defined here + --> $DIR/issue-114682-1.rs:7:9 + | +LL | / pub macro A() { +LL | | println!("non import") +LL | | } + | |_________^ +... +LL | mac!(); + | ------ in this macro invocation + = help: use `crate::A` to refer to this macro unambiguously +note: `A` could also refer to the macro imported here + --> $DIR/issue-114682-1.rs:19:9 + | +LL | pub use m::*; + | ^^^^ + = help: use `crate::A` to refer to this macro unambiguously + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/local-modularized-tricky-fail-1.rs b/tests/ui/imports/local-modularized-tricky-fail-1.rs index ce700ae0de9b1..781014a455a6b 100644 --- a/tests/ui/imports/local-modularized-tricky-fail-1.rs +++ b/tests/ui/imports/local-modularized-tricky-fail-1.rs @@ -27,6 +27,7 @@ mod inner1 { } exported!(); //~ ERROR `exported` is ambiguous +//~^ ERROR `exported` is ambiguous mod inner2 { define_exported!(); diff --git a/tests/ui/imports/local-modularized-tricky-fail-1.stderr b/tests/ui/imports/local-modularized-tricky-fail-1.stderr index 52a01e8bcdfe3..54d928f7c8121 100644 --- a/tests/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/tests/ui/imports/local-modularized-tricky-fail-1.stderr @@ -23,8 +23,34 @@ LL | use inner1::*; = help: consider adding an explicit import of `exported` to disambiguate = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0659]: `exported` is ambiguous + --> $DIR/local-modularized-tricky-fail-1.rs:29:1 + | +LL | exported!(); + | ^^^^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `exported` could refer to the macro defined here + --> $DIR/local-modularized-tricky-fail-1.rs:6:5 + | +LL | / macro_rules! exported { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_exported!(); + | ------------------ in this macro invocation + = help: use `crate::exported` to refer to this macro unambiguously +note: `exported` could also refer to the macro imported here + --> $DIR/local-modularized-tricky-fail-1.rs:23:5 + | +LL | use inner1::*; + | ^^^^^^^^^ + = help: use `crate::exported` to refer to this macro unambiguously + = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0659]: `panic` is ambiguous - --> $DIR/local-modularized-tricky-fail-1.rs:36:5 + --> $DIR/local-modularized-tricky-fail-1.rs:37:5 | LL | panic!(); | ^^^^^ ambiguous name @@ -45,7 +71,7 @@ LL | define_panic!(); = note: this error originates in the macro `define_panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `include` is ambiguous - --> $DIR/local-modularized-tricky-fail-1.rs:47:1 + --> $DIR/local-modularized-tricky-fail-1.rs:48:1 | LL | include!(); | ^^^^^^^ ambiguous name @@ -65,6 +91,6 @@ LL | define_include!(); = help: use `crate::include` to refer to this macro unambiguously = note: this error originates in the macro `define_include` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/macro-paths.rs b/tests/ui/imports/macro-paths.rs index 916442a7c4eab..fd77cf52c8953 100644 --- a/tests/ui/imports/macro-paths.rs +++ b/tests/ui/imports/macro-paths.rs @@ -11,6 +11,7 @@ mod foo { fn f() { use foo::*; bar::m! { //~ ERROR ambiguous + //~^ ERROR ambiguous mod bar { pub use two_macros::m; } } } diff --git a/tests/ui/imports/macro-paths.stderr b/tests/ui/imports/macro-paths.stderr index 5f113ce2bee5d..5ba92072805e3 100644 --- a/tests/ui/imports/macro-paths.stderr +++ b/tests/ui/imports/macro-paths.stderr @@ -6,7 +6,7 @@ LL | bar::m! { | = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution note: `bar` could refer to the module defined here - --> $DIR/macro-paths.rs:14:9 + --> $DIR/macro-paths.rs:15:9 | LL | mod bar { pub use two_macros::m; } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,20 +17,38 @@ LL | use foo::*; | ^^^^^^ = help: consider adding an explicit import of `bar` to disambiguate +error[E0659]: `bar` is ambiguous + --> $DIR/macro-paths.rs:13:5 + | +LL | bar::m! { + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `bar` could refer to the module defined here + --> $DIR/macro-paths.rs:15:9 + | +LL | mod bar { pub use two_macros::m; } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: `bar` could also refer to the module imported here + --> $DIR/macro-paths.rs:12:9 + | +LL | use foo::*; + | ^^^^^^ + error[E0659]: `baz` is ambiguous - --> $DIR/macro-paths.rs:23:5 + --> $DIR/macro-paths.rs:24:5 | LL | baz::m! { | ^^^ ambiguous name | = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `baz` could refer to the module defined here - --> $DIR/macro-paths.rs:24:9 + --> $DIR/macro-paths.rs:25:9 | LL | mod baz { pub use two_macros::m; } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `baz` could also refer to the module defined here - --> $DIR/macro-paths.rs:18:1 + --> $DIR/macro-paths.rs:19:1 | LL | / pub mod baz { LL | | pub use two_macros::m; @@ -38,6 +56,6 @@ LL | | } | |_^ = help: use `crate::baz` to refer to this module unambiguously -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/macros.rs b/tests/ui/imports/macros.rs index cf67e08c87a30..910cd9503050e 100644 --- a/tests/ui/imports/macros.rs +++ b/tests/ui/imports/macros.rs @@ -14,6 +14,7 @@ mod m1 { mod m2 { use two_macros::*; m! { //~ ERROR ambiguous + //~^ ERROR ambiguous use crate::foo::m; } } diff --git a/tests/ui/imports/macros.stderr b/tests/ui/imports/macros.stderr index 25a678c6b3751..2642525816bd6 100644 --- a/tests/ui/imports/macros.stderr +++ b/tests/ui/imports/macros.stderr @@ -6,7 +6,7 @@ LL | m! { | = note: ambiguous because of a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution note: `m` could refer to the macro imported here - --> $DIR/macros.rs:17:13 + --> $DIR/macros.rs:18:13 | LL | use crate::foo::m; | ^^^^^^^^^^^^^ @@ -18,24 +18,44 @@ LL | use two_macros::*; = help: consider adding an explicit import of `m` to disambiguate error[E0659]: `m` is ambiguous - --> $DIR/macros.rs:29:9 + --> $DIR/macros.rs:16:5 + | +LL | m! { + | ^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `m` could refer to the macro imported here + --> $DIR/macros.rs:18:13 + | +LL | use crate::foo::m; + | ^^^^^^^^^^^^^ + = help: use `self::m` to refer to this macro unambiguously +note: `m` could also refer to the macro imported here + --> $DIR/macros.rs:15:9 + | +LL | use two_macros::*; + | ^^^^^^^^^^^^^ + = help: use `self::m` to refer to this macro unambiguously + +error[E0659]: `m` is ambiguous + --> $DIR/macros.rs:30:9 | LL | m! { | ^ ambiguous name | = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro imported here - --> $DIR/macros.rs:30:17 + --> $DIR/macros.rs:31:17 | LL | use two_macros::n as m; | ^^^^^^^^^^^^^^^^^^ note: `m` could also refer to the macro imported here - --> $DIR/macros.rs:22:9 + --> $DIR/macros.rs:23:9 | LL | use two_macros::m; | ^^^^^^^^^^^^^ = help: use `self::m` to refer to this macro unambiguously -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/underscore-imports/shadow.rs b/tests/ui/underscore-imports/shadow.rs index 325f2001b9ede..a2f8855cf7535 100644 --- a/tests/ui/underscore-imports/shadow.rs +++ b/tests/ui/underscore-imports/shadow.rs @@ -14,9 +14,10 @@ mod b { mod c { use crate::b::Shadow as _; // Only imports the struct + //~^ ERROR `Shadow` is ambiguous fn f(x: &()) { - x.deref(); //~ ERROR no method named `deref` found + x.deref() //~ ERROR no method named `deref` found } } diff --git a/tests/ui/underscore-imports/shadow.stderr b/tests/ui/underscore-imports/shadow.stderr index 4743d14dfb9e6..7b322ec1b6371 100644 --- a/tests/ui/underscore-imports/shadow.stderr +++ b/tests/ui/underscore-imports/shadow.stderr @@ -1,7 +1,31 @@ +error[E0659]: `Shadow` is ambiguous + --> $DIR/shadow.rs:16:19 + | +LL | use crate::b::Shadow as _; // Only imports the struct + | ^^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution +note: `Shadow` could refer to the struct defined here + --> $DIR/shadow.rs:10:25 + | +LL | ($i:ident) => { pub struct $i; } + | ^^^^^^^^^^^^^^ +LL | } +LL | m!(Shadow); + | ---------- in this macro invocation + = help: use `self::Shadow` to refer to this struct unambiguously +note: `Shadow` could also refer to the trait imported here + --> $DIR/shadow.rs:8:13 + | +LL | pub use crate::a::*; + | ^^^^^^^^^^^ + = help: use `self::Shadow` to refer to this trait unambiguously + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0599]: no method named `deref` found for reference `&()` in the current scope - --> $DIR/shadow.rs:19:11 + --> $DIR/shadow.rs:20:11 | -LL | x.deref(); +LL | x.deref() | ^^^^^ method not found in `&()` | = help: items from traits can only be used if the trait is in scope @@ -10,6 +34,7 @@ help: trait `Deref` which provides `deref` is implemented but not in scope; perh LL + use std::ops::Deref; | -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0599`. +Some errors have detailed explanations: E0599, E0659. +For more information about an error, try `rustc --explain E0599`.