diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs index 2b0be9865799d..b7848bc261d8d 100644 --- a/compiler/rustc_middle/src/metadata.rs +++ b/compiler/rustc_middle/src/metadata.rs @@ -45,16 +45,9 @@ pub struct ModChild { pub reexport_chain: SmallVec<[Reexport; 2]>, } -#[derive(Debug, TyEncodable, TyDecodable, HashStable)] -pub enum AmbigModChildKind { - GlobVsGlob, - GlobVsExpanded, -} - /// Same as `ModChild`, however, it includes ambiguity error. #[derive(Debug, TyEncodable, TyDecodable, HashStable)] pub struct AmbigModChild { pub main: ModChild, pub second: ModChild, - pub kind: AmbigModChildKind, } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index b9c945a440f88..241c13663ae5d 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -22,7 +22,7 @@ use rustc_hir::def::{self, *}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_index::bit_set::DenseBitSet; use rustc_metadata::creader::LoadedMacro; -use rustc_middle::metadata::{AmbigModChildKind, ModChild, Reexport}; +use rustc_middle::metadata::{ModChild, Reexport}; use rustc_middle::ty::{Feed, Visibility}; use rustc_middle::{bug, span_bug}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; @@ -36,9 +36,9 @@ use crate::imports::{ImportData, ImportKind}; use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; use crate::ref_mut::CmCell; use crate::{ - AmbiguityKind, BindingKey, ExternPreludeEntry, Finalize, MacroData, Module, ModuleKind, - ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult, - ResolutionError, Resolver, Segment, Used, VisResolutionError, errors, + BindingKey, ExternPreludeEntry, Finalize, MacroData, Module, ModuleKind, ModuleOrUniformRoot, + NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult, ResolutionError, + Resolver, Segment, Used, VisResolutionError, errors, }; type Res = def::Res; @@ -82,7 +82,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { vis: Visibility, span: Span, expansion: LocalExpnId, - ambiguity: Option<(NameBinding<'ra>, AmbiguityKind)>, + ambiguity: Option>, ) { let binding = self.arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Res(res), @@ -254,7 +254,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &child.main, parent_scope, children.len() + i, - Some((&child.second, child.kind)), + Some(&child.second), ) } } @@ -265,7 +265,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { child: &ModChild, parent_scope: ParentScope<'ra>, child_index: usize, - ambig_child: Option<(&ModChild, AmbigModChildKind)>, + ambig_child: Option<&ModChild>, ) { let parent = parent_scope.module; let child_span = |this: &Self, reexport_chain: &[Reexport], res: def::Res<_>| { @@ -280,15 +280,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let span = child_span(self, reexport_chain, res); let res = res.expect_non_local(); let expansion = parent_scope.expansion; - let ambig = ambig_child.map(|(ambig_child, ambig_kind)| { + let ambig = ambig_child.map(|ambig_child| { let ModChild { ident: _, res, vis, ref reexport_chain } = *ambig_child; let span = child_span(self, reexport_chain, res); let res = res.expect_non_local(); - let ambig_kind = match ambig_kind { - AmbigModChildKind::GlobVsGlob => AmbiguityKind::GlobVsGlob, - AmbigModChildKind::GlobVsExpanded => AmbiguityKind::GlobVsExpanded, - }; - (self.arenas.new_res_binding(res, vis, span, expansion), ambig_kind) + self.arenas.new_res_binding(res, vis, span, expansion) }); // Record primary definitions. diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 8f20b5fe5745f..716e1d5a2e7ff 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1206,9 +1206,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } } - Scope::Module(module, _) => { + Scope::ModuleNonGlobs(module, _) => { this.add_module_candidates(module, suggestions, filter_fn, None); } + Scope::ModuleGlobs(..) => { + // Already handled in `ModuleNonGlobs`. + } Scope::MacroUsePrelude => { suggestions.extend(this.macro_use_prelude.iter().filter_map( |(name, binding)| { @@ -2033,7 +2036,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously")) } - if let Scope::Module(module, _) = scope { + if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope { if module == self.graph_root { help_msgs.push(format!( "use `crate::{ident}` to refer to this {thing} unambiguously" diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 669f045681b7d..c9f560d2a6fa5 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -103,22 +103,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let rust_2015 = ctxt.edition().is_rust_2015(); let (ns, macro_kind) = match scope_set { - ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None), + ScopeSet::All(ns) + | ScopeSet::Module(ns, _) + | ScopeSet::ModuleAndExternPrelude(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::ModuleAndExternPrelude(_, module) => module, + ScopeSet::Module(_, module) | ScopeSet::ModuleAndExternPrelude(_, module) => module, // Jump out of trait or enum modules, they do not act as scopes. _ => parent_scope.module.nearest_item_scope(), }; + let module_only = 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::Module(module, None), + _ if module_only || module_and_extern_prelude => Scope::ModuleNonGlobs(module, None), _ if extern_prelude => Scope::ExternPreludeItems, - TypeNS | ValueNS => Scope::Module(module, None), + TypeNS | ValueNS => Scope::ModuleNonGlobs(module, None), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; let mut ctxt = ctxt.normalize_to_macros_2_0(); @@ -145,7 +148,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } true } - Scope::Module(..) => true, + Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..) => true, Scope::MacroUsePrelude => use_prelude || rust_2015, Scope::BuiltinAttrs => true, Scope::ExternPreludeItems | Scope::ExternPreludeFlags => { @@ -186,20 +189,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::ModuleNonGlobs(module, None), }, - Scope::Module(..) if module_and_extern_prelude => match ns { + Scope::ModuleNonGlobs(module, lint_id) => Scope::ModuleGlobs(module, lint_id), + Scope::ModuleGlobs(..) if module_only => break, + Scope::ModuleGlobs(..) if module_and_extern_prelude => match ns { TypeNS => { ctxt.adjust(ExpnId::root()); Scope::ExternPreludeItems } ValueNS | MacroNS => break, }, - Scope::Module(module, prev_lint_id) => { + Scope::ModuleGlobs(module, prev_lint_id) => { use_prelude = !module.no_implicit_prelude; 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::ModuleNonGlobs(parent_module, lint_id.or(prev_lint_id)) } None => { ctxt.adjust(ExpnId::root()); @@ -335,13 +340,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { diag_metadata, ))); } else if let RibKind::Block(Some(module)) = rib.kind - && let Ok(binding) = self.cm().resolve_ident_in_module_unadjusted( - module, + && let Ok(binding) = self.cm().resolve_ident_in_scope_set( ident, - ns, + ScopeSet::Module(ns, module), parent_scope, - Shadowing::Unrestricted, finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), + finalize.is_some(), ignore_binding, None, ) @@ -394,12 +398,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { assert!(force || finalize.is_none()); // `finalize` implies `force` // Make sure `self`, `super` etc produce an error when passed to here. - if orig_ident.is_path_segment_keyword() { + if orig_ident.is_path_segment_keyword() && !matches!(scope_set, ScopeSet::Module(..)) { return Err(Determinacy::Determined); } let (ns, macro_kind) = match scope_set { - ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None), + ScopeSet::All(ns) + | ScopeSet::Module(ns, _) + | ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None), ScopeSet::ExternPrelude => (TypeNS, None), ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)), }; @@ -429,10 +435,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { orig_ident.span.ctxt(), derive_fallback_lint_id, |this, scope, use_prelude, ctxt| { - // We can break with an error at this step, it means we cannot determine the - // resolution right now, but we must block and wait until we can instead of - // considering outer scopes. - match this.reborrow().resolve_ident_in_scope( + let res = match this.reborrow().resolve_ident_in_scope( orig_ident, ns, scope, @@ -445,7 +448,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { force, ignore_binding, ignore_import, - )? { + ) { + Ok(binding) => Ok(binding), + // We can break with an error at this step, it means we cannot determine the + // resolution right now, but we must block and wait until we can, instead of + // considering outer scopes. Although there's no need to do that if we already + // have a better solution. + Err(ControlFlow::Break(determinacy)) if innermost_results.is_empty() => { + return ControlFlow::Break(Err(determinacy)); + } + Err(determinacy) => Err(determinacy.into_value()), + }; + match res { Ok(binding) if sub_namespace_match(binding.macro_kinds(), macro_kind) => { // Below we report various ambiguity errors. // We do not need to report them if we are either in speculative resolution, @@ -459,6 +473,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Found another solution, if the first one was "weak", report an error. if this.get_mut().maybe_push_ambiguity( orig_ident, + ns, + scope_set, parent_scope, binding, scope, @@ -504,8 +520,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { force: bool, ignore_binding: Option>, ignore_import: Option>, - ) -> ControlFlow, Determinacy>, Result, Determinacy>> - { + ) -> Result, ControlFlow> { let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt)); let ret = match scope { Scope::DeriveHelpers(expn_id) => { @@ -553,22 +568,78 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { MacroRulesScope::Invocation(_) => Err(Determinacy::Undetermined), _ => Err(Determinacy::Determined), }, - Scope::Module(module, derive_fallback_lint_id) => { - let (adjusted_parent_scope, adjusted_finalize) = - if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) { - (parent_scope, finalize) + Scope::ModuleNonGlobs(module, derive_fallback_lint_id) => { + let (adjusted_parent_scope, adjusted_finalize) = if matches!( + scope_set, + ScopeSet::Module(..) | ScopeSet::ModuleAndExternPrelude(..) + ) { + (parent_scope, finalize) + } else { + ( + &ParentScope { module, ..*parent_scope }, + finalize.map(|f| Finalize { used: Used::Scope, ..f }), + ) + }; + let binding = self.reborrow().resolve_ident_in_module_non_globs_unadjusted( + module, + ident, + ns, + adjusted_parent_scope, + if matches!(scope_set, ScopeSet::Module(..)) { + Shadowing::Unrestricted } else { - ( - &ParentScope { module, ..*parent_scope }, - finalize.map(|f| Finalize { used: Used::Scope, ..f }), - ) - }; - let binding = self.reborrow().resolve_ident_in_module_unadjusted( + Shadowing::Restricted + }, + adjusted_finalize, + ignore_binding, + ignore_import, + ); + match binding { + Ok(binding) => { + if let Some(lint_id) = derive_fallback_lint_id { + self.get_mut().lint_buffer.buffer_lint( + PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, + lint_id, + orig_ident.span, + errors::ProcMacroDeriveResolutionFallback { + span: orig_ident.span, + ns_descr: ns.descr(), + ident, + }, + ); + } + Ok(binding) + } + Err(ControlFlow::Continue(determinacy)) => Err(determinacy), + Err(ControlFlow::Break(determinacy)) => { + return Err(ControlFlow::Break(Determinacy::determined( + determinacy == Determinacy::Determined || force, + ))); + } + } + } + Scope::ModuleGlobs(module, derive_fallback_lint_id) => { + let (adjusted_parent_scope, adjusted_finalize) = if matches!( + scope_set, + ScopeSet::Module(..) | ScopeSet::ModuleAndExternPrelude(..) + ) { + (parent_scope, finalize) + } else { + ( + &ParentScope { module, ..*parent_scope }, + finalize.map(|f| Finalize { used: Used::Scope, ..f }), + ) + }; + let binding = self.reborrow().resolve_ident_in_module_globs_unadjusted( module, ident, ns, adjusted_parent_scope, - Shadowing::Restricted, + if matches!(scope_set, ScopeSet::Module(..)) { + Shadowing::Unrestricted + } else { + Shadowing::Restricted + }, adjusted_finalize, ignore_binding, ignore_import, @@ -590,11 +661,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Ok(binding) } Err(ControlFlow::Continue(determinacy)) => Err(determinacy), - Err(ControlFlow::Break(Determinacy::Undetermined)) => { - return ControlFlow::Break(Err(Determinacy::determined(force))); + Err(ControlFlow::Break(determinacy)) => { + return Err(ControlFlow::Break(Determinacy::determined( + determinacy == Determinacy::Determined || force, + ))); } - // Privacy errors, do not happen during in scope resolution. - Err(ControlFlow::Break(Determinacy::Determined)) => unreachable!(), } } Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() { @@ -628,13 +699,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Scope::StdLibPrelude => { let mut result = Err(Determinacy::Determined); if let Some(prelude) = self.prelude - && let Ok(binding) = self.reborrow().resolve_ident_in_module_unadjusted( - prelude, + && let Ok(binding) = self.reborrow().resolve_ident_in_scope_set( ident, - ns, + ScopeSet::Module(ns, prelude), parent_scope, - Shadowing::Unrestricted, None, + false, ignore_binding, ignore_import, ) @@ -680,12 +750,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }, }; - ControlFlow::Continue(ret) + ret.map_err(ControlFlow::Continue) } fn maybe_push_ambiguity( &mut self, orig_ident: Ident, + ns: Namespace, + scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, binding: NameBinding<'ra>, scope: Scope<'ra>, @@ -699,6 +771,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // FIXME: Use `scope` instead of `res` to detect built-in attrs and derive helpers, // it will exclude imports, make slightly more code legal, and will require lang approval. + let module_only = matches!(scope_set, ScopeSet::Module(..)); let is_builtin = |res| matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Builtin(..))); let derive_helper = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); let derive_helper_compat = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat); @@ -710,12 +783,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else if res == derive_helper_compat && innermost_res != derive_helper { span_bug!(orig_ident.span, "impossible inner resolution kind") } else if matches!(innermost_scope, Scope::MacroRules(_)) - && matches!(scope, Scope::Module(..)) + && matches!(scope, Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..)) && !self.disambiguate_macro_rules_vs_modularized(innermost_binding, binding) { Some(AmbiguityKind::MacroRulesVsModularized) } else if matches!(scope, Scope::MacroRules(_)) - && matches!(innermost_scope, Scope::Module(..)) + && matches!(innermost_scope, Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..)) { // should be impossible because of visitation order in // visit_scopes @@ -729,11 +802,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) } else if innermost_binding.is_glob_import() { Some(AmbiguityKind::GlobVsOuter) - } else if innermost_binding.may_appear_after(parent_scope.expansion, binding) { + } else if !module_only + && innermost_binding.may_appear_after(parent_scope.expansion, binding) + { Some(AmbiguityKind::MoreExpandedVsOuter) + } else if innermost_binding.expansion != LocalExpnId::ROOT + && (!module_only || ns == MacroNS) + && let Scope::ModuleGlobs(m1, _) = scope + && let Scope::ModuleNonGlobs(m2, _) = innermost_scope + && m1 == m2 + { + // FIXME: this error is too conservative and technically unnecessary now when module + // scope is split into two scopes, at least when not resolving in `ScopeSet::Module`, + // remove it with lang team approval. + Some(AmbiguityKind::GlobVsExpanded) } else { None }; + if let Some(kind) = ambiguity_error_kind { // Skip ambiguity errors for extern flag bindings "overridden" // by extern item bindings. @@ -742,8 +828,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && innermost_results[1..].iter().any(|(b, s)| { matches!(s, Scope::ExternPreludeItems) && *b != innermost_binding }); + // Skip ambiguity errors for nonglob module bindings "overridden" + // by glob module bindings in the same module. + // FIXME: Remove with lang team approval. + let issue_149681_hack = match scope { + Scope::ModuleGlobs(m1, _) + if innermost_results[1..] + .iter() + .any(|(_, s)| matches!(*s, Scope::ModuleNonGlobs(m2, _) if m1 == m2)) => + { + true + } + _ => false, + }; - if issue_145575_hack { + if issue_145575_hack || issue_149681_hack { self.issue_145575_hack_applied = true; } else { self.ambiguity_errors.push(AmbiguityError { @@ -826,18 +925,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ignore_import: Option>, ) -> Result, Determinacy> { match module { - ModuleOrUniformRoot::Module(module) => self - .resolve_ident_in_module_unadjusted( - module, - ident, - ns, - parent_scope, - Shadowing::Unrestricted, - finalize, - ignore_binding, - ignore_import, - ) - .map_err(|determinacy| determinacy.into_value()), + ModuleOrUniformRoot::Module(module) => self.resolve_ident_in_scope_set( + ident, + ScopeSet::Module(ns, module), + parent_scope, + finalize, + finalize.is_some(), + ignore_binding, + ignore_import, + ), ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self.resolve_ident_in_scope_set( ident, ScopeSet::ModuleAndExternPrelude(ns, module), @@ -887,48 +983,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - /// Attempts to resolve `ident` in namespace `ns` of `module`. - fn resolve_ident_in_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, ControlFlow> { - let res = self.reborrow().resolve_ident_in_module_non_globs_unadjusted( - module, - ident, - ns, - parent_scope, - shadowing, - finalize, - ignore_binding, - ignore_import, - ); - - match res { - Ok(_) | Err(ControlFlow::Break(_)) => return res, - Err(ControlFlow::Continue(_)) => {} - } - - self.resolve_ident_in_module_globs_unadjusted( - module, - ident, - ns, - parent_scope, - shadowing, - finalize, - ignore_binding, - ignore_import, - ) - } - /// Attempts to resolve `ident` in namespace `ns` of non-glob bindings in `module`. fn resolve_ident_in_module_non_globs_unadjusted<'r>( mut self: CmResolver<'r, 'ra, 'tcx>, @@ -938,6 +992,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { 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, ControlFlow> { @@ -956,7 +1012,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return self.get_mut().finalize_module_binding( ident, binding, - if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None }, parent_scope, module, finalize, @@ -1018,7 +1073,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return self.get_mut().finalize_module_binding( ident, binding, - if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None }, parent_scope, module, finalize, @@ -1097,28 +1151,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Some(None) => {} None => continue, }; - let result = self.reborrow().resolve_ident_in_module_unadjusted( - module, + let result = self.reborrow().resolve_ident_in_scope_set( ident, - ns, + ScopeSet::Module(ns, module), adjusted_parent_scope, - Shadowing::Unrestricted, None, + false, ignore_binding, ignore_import, ); match result { - Err(ControlFlow::Break(Determined) | ControlFlow::Continue(Determined)) => continue, + Err(Determined) => continue, Ok(binding) if !self.is_accessible_from(binding.vis, glob_import.parent_scope.module) => { continue; } - Ok(_) - | Err(ControlFlow::Break(Undetermined) | ControlFlow::Continue(Undetermined)) => { - return Err(ControlFlow::Continue(Undetermined)); - } + Ok(_) | Err(Undetermined) => return Err(ControlFlow::Continue(Undetermined)), } } @@ -1130,7 +1180,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &mut self, ident: Ident, binding: Option>, - shadowed_glob: Option>, parent_scope: &ParentScope<'ra>, module: Module<'ra>, finalize: Finalize, @@ -1158,24 +1207,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - // Forbid expanded shadowing to avoid time travel. - if let Some(shadowed_glob) = shadowed_glob - && shadowing == Shadowing::Restricted - && finalize.stage == Stage::Early - && binding.expansion != LocalExpnId::ROOT - && binding.res() != shadowed_glob.res() - { - self.ambiguity_errors.push(AmbiguityError { - kind: AmbiguityKind::GlobVsExpanded, - ident, - b1: binding, - b2: shadowed_glob, - scope1: Scope::Module(self.empty_module, None), - scope2: Scope::Module(self.empty_module, None), - warning: false, - }); - } - if shadowing == Shadowing::Unrestricted && binding.expansion != LocalExpnId::ROOT && let NameBindingKind::Import { import, .. } = binding.kind @@ -1231,6 +1262,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { parent_scope: &ParentScope<'ra>, ) -> bool { for single_import in &resolution.single_imports { + if let Some(binding) = resolution.non_glob_binding + && let NameBindingKind::Import { import, .. } = binding.kind + && import == *single_import + { + // Single import has already defined the name and we are aware of it, + // no need to block the globs. + continue; + } if ignore_import == Some(*single_import) { continue; } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 4e0f3db59821f..558f769eda191 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -9,7 +9,7 @@ use rustc_errors::codes::*; use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err}; use rustc_hir::def::{self, DefKind, PartialRes}; use rustc_hir::def_id::{DefId, LocalDefIdMap}; -use rustc_middle::metadata::{AmbigModChild, AmbigModChildKind, ModChild, Reexport}; +use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; use rustc_middle::span_bug; use rustc_middle::ty::Visibility; use rustc_session::lint::BuiltinLintDiag; @@ -32,10 +32,9 @@ use crate::errors::{ }; use crate::ref_mut::CmCell; use crate::{ - AmbiguityError, AmbiguityKind, BindingKey, CmResolver, Determinacy, Finalize, ImportSuggestion, - Module, ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope, - PathResult, PerNS, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, - names_to_string, + AmbiguityError, BindingKey, CmResolver, Determinacy, Finalize, ImportSuggestion, Module, + ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult, + PerNS, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string, }; type Res = def::Res; @@ -373,7 +372,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { resolution.glob_binding = Some(glob_binding); } else if res != old_glob_binding.res() { resolution.glob_binding = Some(this.new_ambiguity_binding( - AmbiguityKind::GlobVsGlob, old_glob_binding, glob_binding, warn_ambiguity, @@ -389,25 +387,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (old_glob @ true, false) | (old_glob @ false, true) => { let (glob_binding, non_glob_binding) = if old_glob { (old_binding, binding) } else { (binding, old_binding) }; - if ns == MacroNS - && non_glob_binding.expansion != LocalExpnId::ROOT - && glob_binding.res() != non_glob_binding.res() - { - resolution.non_glob_binding = Some(this.new_ambiguity_binding( - AmbiguityKind::GlobVsExpanded, - non_glob_binding, - glob_binding, - false, - )); - } else { - resolution.non_glob_binding = Some(non_glob_binding); - } - + resolution.non_glob_binding = Some(non_glob_binding); if let Some(old_glob_binding) = resolution.glob_binding { assert!(old_glob_binding.is_glob_import()); if glob_binding.res() != old_glob_binding.res() { resolution.glob_binding = Some(this.new_ambiguity_binding( - AmbiguityKind::GlobVsGlob, old_glob_binding, glob_binding, false, @@ -437,12 +421,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn new_ambiguity_binding( &self, - ambiguity_kind: AmbiguityKind, primary_binding: NameBinding<'ra>, secondary_binding: NameBinding<'ra>, warn_ambiguity: bool, ) -> NameBinding<'ra> { - let ambiguity = Some((secondary_binding, ambiguity_kind)); + let ambiguity = Some(secondary_binding); let data = NameBindingData { ambiguity, warn_ambiguity, ..*primary_binding }; self.arenas.alloc_name_binding(data) } @@ -658,7 +641,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let Some(binding) = resolution.best_binding() else { continue }; if let NameBindingKind::Import { import, .. } = binding.kind - && let Some((amb_binding, _)) = binding.ambiguity + && let Some(amb_binding) = binding.ambiguity && binding.res() != Res::Err && exported_ambiguities.contains(&binding) { @@ -1566,9 +1549,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { vis: binding.vis, reexport_chain, }; - if let Some((ambig_binding1, ambig_binding2, ambig_kind)) = - binding.descent_to_ambiguity() - { + if let Some((ambig_binding1, ambig_binding2)) = binding.descent_to_ambiguity() { let main = child(ambig_binding1.reexport_chain(this)); let second = ModChild { ident: ident.0, @@ -1576,13 +1557,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { vis: ambig_binding2.vis, reexport_chain: ambig_binding2.reexport_chain(this), }; - let kind = match ambig_kind { - AmbiguityKind::GlobVsGlob => AmbigModChildKind::GlobVsGlob, - AmbiguityKind::GlobVsExpanded => AmbigModChildKind::GlobVsExpanded, - _ => unreachable!(), - }; - - ambig_children.push(AmbigModChild { main, second, kind }) + ambig_children.push(AmbigModChild { main, second }) } else { children.push(child(binding.reexport_chain(this))); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index dd80f5da508c3..290d21cad4b90 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -44,8 +44,8 @@ use tracing::{debug, instrument, trace}; use crate::{ BindingError, BindingKey, Finalize, LexicalScopeBinding, Module, ModuleOrUniformRoot, - NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, TyCtxt, UseError, - Used, errors, path_names_to_string, rustdoc, + NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, Stage, TyCtxt, + UseError, Used, errors, path_names_to_string, rustdoc, }; mod diagnostics; @@ -1514,7 +1514,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { opt_ns, &self.parent_scope, Some(source), - finalize, + finalize.map(|finalize| Finalize { stage: Stage::Late, ..finalize }), Some(&self.ribs), None, None, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7cbf2088efce5..fbd16072c2c04 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -123,10 +123,14 @@ enum Scope<'ra> { DeriveHelpersCompat, /// Textual `let`-like scopes introduced by `macro_rules!` items. MacroRules(MacroRulesScopeRef<'ra>), - /// Names declared in the given module. + /// Non-glob 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), + ModuleNonGlobs(Module<'ra>, Option), + /// Glob names declared in the given module. + /// The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK` + /// lint if it should be reported. + ModuleGlobs(Module<'ra>, Option), /// Names introduced by `#[macro_use]` attributes on `extern crate` items. MacroUsePrelude, /// Built-in attributes. @@ -149,6 +153,8 @@ enum Scope<'ra> { enum ScopeSet<'ra> { /// All scopes with the given namespace. All(Namespace), + /// Two scopes inside a module, for non-glob and glob bindings. + Module(Namespace, Module<'ra>), /// A module, then extern prelude (used for mixed 2015-2018 mode in macros). ModuleAndExternPrelude(Namespace, Module<'ra>), /// Just two extern prelude scopes. @@ -801,7 +807,7 @@ impl<'ra> fmt::Debug for Module<'ra> { #[derive(Clone, Copy, Debug)] struct NameBindingData<'ra> { kind: NameBindingKind<'ra>, - ambiguity: Option<(NameBinding<'ra>, AmbiguityKind)>, + ambiguity: Option>, /// Produce a warning instead of an error when reporting ambiguities inside this binding. /// May apply to indirect ambiguities under imports, so `ambiguity.is_some()` is not required. warn_ambiguity: bool, @@ -931,9 +937,9 @@ impl<'ra> NameBindingData<'ra> { fn descent_to_ambiguity( self: NameBinding<'ra>, - ) -> Option<(NameBinding<'ra>, NameBinding<'ra>, AmbiguityKind)> { + ) -> Option<(NameBinding<'ra>, NameBinding<'ra>)> { match self.ambiguity { - Some((ambig_binding, ambig_kind)) => Some((self, ambig_binding, ambig_kind)), + Some(ambig_binding) => Some((self, ambig_binding)), None => match self.kind { NameBindingKind::Import { binding, .. } => binding.descent_to_ambiguity(), _ => None, @@ -1926,9 +1932,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let scope_set = ScopeSet::All(TypeNS); self.cm().visit_scopes(scope_set, parent_scope, ctxt, None, |this, scope, _, _| { match scope { - Scope::Module(module, _) => { + Scope::ModuleNonGlobs(module, _) => { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); } + Scope::ModuleGlobs(..) => { + // Already handled in `ModuleNonGlobs` (but see #144993). + } Scope::StdLibPrelude => { if let Some(module) = this.prelude { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); @@ -2055,14 +2064,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { used: Used, warn_ambiguity: bool, ) { - if let Some((b2, kind)) = used_binding.ambiguity { + if let Some(b2) = used_binding.ambiguity { let ambiguity_error = AmbiguityError { - kind, + kind: AmbiguityKind::GlobVsGlob, ident, b1: used_binding, b2, - scope1: Scope::Module(self.empty_module, None), - scope2: Scope::Module(self.empty_module, None), + scope1: Scope::ModuleGlobs(self.empty_module, None), + scope2: Scope::ModuleGlobs(self.empty_module, None), warning: warn_ambiguity, }; if !self.matches_previous_ambiguity_error(&ambiguity_error) { diff --git a/tests/ui/imports/ambiguous-glob-vs-expanded-extern.rs b/tests/ui/imports/ambiguous-glob-vs-expanded-extern.rs index de632119ecba0..0277da46f7505 100644 --- a/tests/ui/imports/ambiguous-glob-vs-expanded-extern.rs +++ b/tests/ui/imports/ambiguous-glob-vs-expanded-extern.rs @@ -1,6 +1,6 @@ +//@ check-pass //@ aux-crate: glob_vs_expanded=glob-vs-expanded.rs fn main() { - glob_vs_expanded::mac!(); //~ ERROR `mac` is ambiguous - //~| WARN this was previously accepted + glob_vs_expanded::mac!(); // OK } diff --git a/tests/ui/imports/ambiguous-glob-vs-expanded-extern.stderr b/tests/ui/imports/ambiguous-glob-vs-expanded-extern.stderr deleted file mode 100644 index 4a9a6c99819b0..0000000000000 --- a/tests/ui/imports/ambiguous-glob-vs-expanded-extern.stderr +++ /dev/null @@ -1,53 +0,0 @@ -error: `mac` is ambiguous - --> $DIR/ambiguous-glob-vs-expanded-extern.rs:4:23 - | -LL | glob_vs_expanded::mac!(); - | ^^^ ambiguous name - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #114095 - = 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: `mac` could refer to the macro defined here - --> $DIR/auxiliary/glob-vs-expanded.rs:9:13 - | -LL | () => { pub macro mac() {} } - | ^^^^^^^^^^^^^ -LL | } -LL | define_mac!(); - | ------------- in this macro invocation -note: `mac` could also refer to the macro defined here - --> $DIR/auxiliary/glob-vs-expanded.rs:5:9 - | -LL | pub use inner::*; - | ^^^^^ - = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `define_mac` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 1 previous error - -Future incompatibility report: Future breakage diagnostic: -error: `mac` is ambiguous - --> $DIR/ambiguous-glob-vs-expanded-extern.rs:4:23 - | -LL | glob_vs_expanded::mac!(); - | ^^^ ambiguous name - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #114095 - = 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: `mac` could refer to the macro defined here - --> $DIR/auxiliary/glob-vs-expanded.rs:9:13 - | -LL | () => { pub macro mac() {} } - | ^^^^^^^^^^^^^ -LL | } -LL | define_mac!(); - | ------------- in this macro invocation -note: `mac` could also refer to the macro defined here - --> $DIR/auxiliary/glob-vs-expanded.rs:5:9 - | -LL | pub use inner::*; - | ^^^^^ - = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `define_mac` (in Nightly builds, run with -Z macro-backtrace for more info) - diff --git a/tests/ui/imports/issue-114682-1.stderr b/tests/ui/imports/issue-114682-1.stderr index 85fb7f7919e4e..fd2776f50ad77 100644 --- a/tests/ui/imports/issue-114682-1.stderr +++ b/tests/ui/imports/issue-114682-1.stderr @@ -4,7 +4,7 @@ error[E0659]: `A` is ambiguous LL | A!(); | ^ ambiguous name | - = 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: 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 | @@ -15,12 +15,13 @@ 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: consider adding an explicit import of `A` to disambiguate + = 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 1 previous error diff --git a/tests/ui/imports/local-modularized-tricky-fail-1.stderr b/tests/ui/imports/local-modularized-tricky-fail-1.stderr index 52a01e8bcdfe3..b5b3be5953f93 100644 --- a/tests/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/tests/ui/imports/local-modularized-tricky-fail-1.stderr @@ -4,7 +4,7 @@ error[E0659]: `exported` is ambiguous LL | exported!(); | ^^^^^^^^ ambiguous name | - = 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: 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 | @@ -15,12 +15,13 @@ 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: consider adding an explicit import of `exported` to disambiguate + = 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 diff --git a/tests/ui/imports/macro-paths.stderr b/tests/ui/imports/macro-paths.stderr index 5f113ce2bee5d..56a40e908258b 100644 --- a/tests/ui/imports/macro-paths.stderr +++ b/tests/ui/imports/macro-paths.stderr @@ -4,7 +4,7 @@ error[E0659]: `bar` is ambiguous LL | bar::m! { | ^^^ ambiguous name | - = 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: 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:14:9 | @@ -15,7 +15,6 @@ note: `bar` could also refer to the module imported here | LL | use foo::*; | ^^^^^^ - = help: consider adding an explicit import of `bar` to disambiguate error[E0659]: `baz` is ambiguous --> $DIR/macro-paths.rs:23:5 diff --git a/tests/ui/imports/macros.rs b/tests/ui/imports/macros.rs index cf67e08c87a30..121f1f7ae043e 100644 --- a/tests/ui/imports/macros.rs +++ b/tests/ui/imports/macros.rs @@ -13,7 +13,7 @@ mod m1 { mod m2 { use two_macros::*; - m! { //~ ERROR ambiguous + m! { //~ ERROR `m` is ambiguous use crate::foo::m; } } diff --git a/tests/ui/imports/macros.stderr b/tests/ui/imports/macros.stderr index 25a678c6b3751..9c081cc7af8b1 100644 --- a/tests/ui/imports/macros.stderr +++ b/tests/ui/imports/macros.stderr @@ -4,18 +4,19 @@ error[E0659]: `m` is ambiguous LL | m! { | ^ ambiguous name | - = 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: 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:17: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: consider adding an explicit import of `m` to disambiguate + = help: use `self::m` to refer to this macro unambiguously error[E0659]: `m` is ambiguous --> $DIR/macros.rs:29:9 diff --git a/tests/ui/imports/overwritten-glob-ambig.rs b/tests/ui/imports/overwritten-glob-ambig.rs new file mode 100644 index 0000000000000..a5918568c62a4 --- /dev/null +++ b/tests/ui/imports/overwritten-glob-ambig.rs @@ -0,0 +1,26 @@ +// Test for a regression introduced by splitting module scope into two scopes +// (similar to issue #145575). + +//@ check-pass +//@ edition: 2018.. + +#[macro_use] +mod one { + // Macro that is in a different module, but still in scope due to `macro_use` + macro_rules! mac { () => {} } + pub(crate) use mac; +} + +mod other { + macro_rules! mac { () => {} } + pub(crate) use mac; +} + +// Single import of the same in the current module. +use one::mac; +// Glob import of a different macro in the current module (should be an ambiguity). +use other::*; + +fn main() { + mac!(); // OK for now, the ambiguity is not reported +}