Rollup merge of #149681 - petrochenkov:openapi1, r=davidtwco
resolve: Split `Scope::Module` into two scopes for non-glob and glob bindings
This is a re-implementation of https://github.com/rust-lang/rust/pull/144131 with all the issues mentioned there fixed.
As it turned out, the non-trivial part of the split was already done in https://github.com/rust-lang/rust/pull/149454/commits/c91b6ca58d4d870d3099db1defbd8c1f26a7d851, so the remaining part implemented in this PR is *mostly* mechanical.
After addressing the issue of already found bindings being lost due to indeterminacies in outer scopes (7e890bfa87) and adding one missing `Stage::Late` in `Finalize` the scope splitting refactoring just worked.
(One more ICE was revealed by the refactoring, but not caused by it, fixed up in the last commit.)
This is a part of implementation for the [Open API](https://rust-lang.github.io/rust-project-goals/2025h1/open-namespaces.html) proposal.
This commit is contained in:
commit
df246c107a
15 changed files with 254 additions and 264 deletions
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<NodeId>;
|
||||
|
|
@ -82,7 +82,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
vis: Visibility<DefId>,
|
||||
span: Span,
|
||||
expansion: LocalExpnId,
|
||||
ambiguity: Option<(NameBinding<'ra>, AmbiguityKind)>,
|
||||
ambiguity: Option<NameBinding<'ra>>,
|
||||
) {
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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<NameBinding<'ra>>,
|
||||
ignore_import: Option<Import<'ra>>,
|
||||
) -> ControlFlow<Result<NameBinding<'ra>, Determinacy>, Result<NameBinding<'ra>, Determinacy>>
|
||||
{
|
||||
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
|
||||
let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
|
||||
let ret = match scope {
|
||||
Scope::DeriveHelpers(expn_id) => {
|
||||
|
|
@ -553,22 +568,28 @@ 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)
|
||||
} else {
|
||||
(
|
||||
&ParentScope { module, ..*parent_scope },
|
||||
finalize.map(|f| Finalize { used: Used::Scope, ..f }),
|
||||
)
|
||||
};
|
||||
let binding = self.reborrow().resolve_ident_in_module_unadjusted(
|
||||
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,
|
||||
Shadowing::Restricted,
|
||||
if matches!(scope_set, ScopeSet::Module(..)) {
|
||||
Shadowing::Unrestricted
|
||||
} else {
|
||||
Shadowing::Restricted
|
||||
},
|
||||
adjusted_finalize,
|
||||
ignore_binding,
|
||||
ignore_import,
|
||||
|
|
@ -590,11 +611,61 @@ 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,
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
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,
|
||||
if matches!(scope_set, ScopeSet::Module(..)) {
|
||||
Shadowing::Unrestricted
|
||||
} else {
|
||||
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,
|
||||
)));
|
||||
}
|
||||
// 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<Import<'ra>>,
|
||||
) -> Result<NameBinding<'ra>, 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<Finalize>,
|
||||
// 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<NameBinding<'ra>>,
|
||||
ignore_import: Option<Import<'ra>>,
|
||||
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
|
||||
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<Finalize>,
|
||||
// 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<NameBinding<'ra>>,
|
||||
ignore_import: Option<Import<'ra>>,
|
||||
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
|
||||
|
|
@ -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<NameBinding<'ra>>,
|
||||
shadowed_glob: Option<NameBinding<'ra>>,
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<NodeId>;
|
||||
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<NodeId>),
|
||||
ModuleNonGlobs(Module<'ra>, Option<NodeId>),
|
||||
/// 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<NodeId>),
|
||||
/// 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<NameBinding<'ra>>,
|
||||
/// 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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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)
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ mod m1 {
|
|||
|
||||
mod m2 {
|
||||
use two_macros::*;
|
||||
m! { //~ ERROR ambiguous
|
||||
m! { //~ ERROR `m` is ambiguous
|
||||
use crate::foo::m;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
26
tests/ui/imports/overwritten-glob-ambig.rs
Normal file
26
tests/ui/imports/overwritten-glob-ambig.rs
Normal file
|
|
@ -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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue