resolve: Split extern prelude into two scopes
One for `--extern` options and another for `extern crate` items.
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
|
#### Note: this error code is no longer emitted by the compiler.
|
||||||
|
|
||||||
A module cannot be found and therefore, the visibility cannot be determined.
|
A module cannot be found and therefore, the visibility cannot be determined.
|
||||||
|
|
||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
```compile_fail,E0578,edition2018
|
```ignore (no longer emitted)
|
||||||
foo!();
|
foo!();
|
||||||
|
|
||||||
pub (in ::Sea) struct Shark; // error!
|
pub (in ::Sea) struct Shark; // error!
|
||||||
|
|||||||
@@ -971,40 +971,35 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||||||
let imported_binding = self.r.import(binding, import);
|
let imported_binding = self.r.import(binding, import);
|
||||||
if ident.name != kw::Underscore && parent == self.r.graph_root {
|
if ident.name != kw::Underscore && parent == self.r.graph_root {
|
||||||
let norm_ident = Macros20NormalizedIdent::new(ident);
|
let norm_ident = Macros20NormalizedIdent::new(ident);
|
||||||
|
// FIXME: this error is technically unnecessary now when extern prelude is split into
|
||||||
|
// two scopes, remove it with lang team approval.
|
||||||
if let Some(entry) = self.r.extern_prelude.get(&norm_ident)
|
if let Some(entry) = self.r.extern_prelude.get(&norm_ident)
|
||||||
&& expansion != LocalExpnId::ROOT
|
&& expansion != LocalExpnId::ROOT
|
||||||
&& orig_name.is_some()
|
&& orig_name.is_some()
|
||||||
&& !entry.is_import()
|
&& entry.item_binding.is_none()
|
||||||
{
|
{
|
||||||
self.r.dcx().emit_err(
|
self.r.dcx().emit_err(
|
||||||
errors::MacroExpandedExternCrateCannotShadowExternArguments { span: item.span },
|
errors::MacroExpandedExternCrateCannotShadowExternArguments { span: item.span },
|
||||||
);
|
);
|
||||||
// `return` is intended to discard this binding because it's an
|
|
||||||
// unregistered ambiguity error which would result in a panic
|
|
||||||
// caused by inconsistency `path_res`
|
|
||||||
// more details: https://github.com/rust-lang/rust/pull/111761
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use indexmap::map::Entry;
|
use indexmap::map::Entry;
|
||||||
match self.r.extern_prelude.entry(norm_ident) {
|
match self.r.extern_prelude.entry(norm_ident) {
|
||||||
Entry::Occupied(mut occupied) => {
|
Entry::Occupied(mut occupied) => {
|
||||||
let entry = occupied.get_mut();
|
let entry = occupied.get_mut();
|
||||||
if let Some(old_binding) = entry.binding.get()
|
if entry.item_binding.is_some() {
|
||||||
&& old_binding.is_import()
|
|
||||||
{
|
|
||||||
let msg = format!("extern crate `{ident}` already in extern prelude");
|
let msg = format!("extern crate `{ident}` already in extern prelude");
|
||||||
self.r.tcx.dcx().span_delayed_bug(item.span, msg);
|
self.r.tcx.dcx().span_delayed_bug(item.span, msg);
|
||||||
} else {
|
} else {
|
||||||
// Binding from `extern crate` item in source code can replace
|
entry.item_binding = Some(imported_binding);
|
||||||
// a binding from `--extern` on command line here.
|
|
||||||
entry.binding.set(Some(imported_binding));
|
|
||||||
entry.introduced_by_item = orig_name.is_some();
|
entry.introduced_by_item = orig_name.is_some();
|
||||||
}
|
}
|
||||||
entry
|
entry
|
||||||
}
|
}
|
||||||
Entry::Vacant(vacant) => vacant.insert(ExternPreludeEntry {
|
Entry::Vacant(vacant) => vacant.insert(ExternPreludeEntry {
|
||||||
binding: Cell::new(Some(imported_binding)),
|
item_binding: Some(imported_binding),
|
||||||
|
flag_binding: Cell::new(None),
|
||||||
|
only_item: true,
|
||||||
introduced_by_item: true,
|
introduced_by_item: true,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1096,12 +1096,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scope::ExternPrelude => {
|
Scope::ExternPreludeItems => {
|
||||||
|
// Add idents from both item and flag scopes.
|
||||||
suggestions.extend(this.extern_prelude.keys().filter_map(|ident| {
|
suggestions.extend(this.extern_prelude.keys().filter_map(|ident| {
|
||||||
let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
|
let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
|
||||||
filter_fn(res).then_some(TypoSuggestion::typo_from_ident(ident.0, res))
|
filter_fn(res).then_some(TypoSuggestion::typo_from_ident(ident.0, res))
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
Scope::ExternPreludeFlags => {}
|
||||||
Scope::ToolPrelude => {
|
Scope::ToolPrelude => {
|
||||||
let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
|
let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
|
||||||
suggestions.extend(
|
suggestions.extend(
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
ScopeSet::All(ns)
|
ScopeSet::All(ns)
|
||||||
| ScopeSet::ModuleAndExternPrelude(ns, _)
|
| ScopeSet::ModuleAndExternPrelude(ns, _)
|
||||||
| ScopeSet::Late(ns, ..) => (ns, None),
|
| ScopeSet::Late(ns, ..) => (ns, None),
|
||||||
|
ScopeSet::ExternPrelude => (TypeNS, None),
|
||||||
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
|
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
|
||||||
};
|
};
|
||||||
let module = match scope_set {
|
let module = match scope_set {
|
||||||
@@ -111,8 +112,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
_ => parent_scope.module.nearest_item_scope(),
|
_ => parent_scope.module.nearest_item_scope(),
|
||||||
};
|
};
|
||||||
let module_and_extern_prelude = matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..));
|
let module_and_extern_prelude = matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..));
|
||||||
|
let extern_prelude = matches!(scope_set, ScopeSet::ExternPrelude);
|
||||||
let mut scope = match ns {
|
let mut scope = match ns {
|
||||||
_ if module_and_extern_prelude => Scope::Module(module, None),
|
_ if module_and_extern_prelude => Scope::Module(module, None),
|
||||||
|
_ if extern_prelude => Scope::ExternPreludeItems,
|
||||||
TypeNS | ValueNS => Scope::Module(module, None),
|
TypeNS | ValueNS => Scope::Module(module, None),
|
||||||
MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
|
MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
|
||||||
};
|
};
|
||||||
@@ -143,7 +146,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
Scope::Module(..) => true,
|
Scope::Module(..) => true,
|
||||||
Scope::MacroUsePrelude => use_prelude || rust_2015,
|
Scope::MacroUsePrelude => use_prelude || rust_2015,
|
||||||
Scope::BuiltinAttrs => true,
|
Scope::BuiltinAttrs => true,
|
||||||
Scope::ExternPrelude => use_prelude || module_and_extern_prelude,
|
Scope::ExternPreludeItems | Scope::ExternPreludeFlags => {
|
||||||
|
use_prelude || module_and_extern_prelude || extern_prelude
|
||||||
|
}
|
||||||
Scope::ToolPrelude => use_prelude,
|
Scope::ToolPrelude => use_prelude,
|
||||||
Scope::StdLibPrelude => use_prelude || ns == MacroNS,
|
Scope::StdLibPrelude => use_prelude || ns == MacroNS,
|
||||||
Scope::BuiltinTypes => true,
|
Scope::BuiltinTypes => true,
|
||||||
@@ -182,7 +187,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
Scope::Module(..) if module_and_extern_prelude => match ns {
|
Scope::Module(..) if module_and_extern_prelude => match ns {
|
||||||
TypeNS => {
|
TypeNS => {
|
||||||
ctxt.adjust(ExpnId::root());
|
ctxt.adjust(ExpnId::root());
|
||||||
Scope::ExternPrelude
|
Scope::ExternPreludeItems
|
||||||
}
|
}
|
||||||
ValueNS | MacroNS => break,
|
ValueNS | MacroNS => break,
|
||||||
},
|
},
|
||||||
@@ -199,7 +204,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
None => {
|
None => {
|
||||||
ctxt.adjust(ExpnId::root());
|
ctxt.adjust(ExpnId::root());
|
||||||
match ns {
|
match ns {
|
||||||
TypeNS => Scope::ExternPrelude,
|
TypeNS => Scope::ExternPreludeItems,
|
||||||
ValueNS => Scope::StdLibPrelude,
|
ValueNS => Scope::StdLibPrelude,
|
||||||
MacroNS => Scope::MacroUsePrelude,
|
MacroNS => Scope::MacroUsePrelude,
|
||||||
}
|
}
|
||||||
@@ -208,8 +213,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
Scope::MacroUsePrelude => Scope::StdLibPrelude,
|
Scope::MacroUsePrelude => Scope::StdLibPrelude,
|
||||||
Scope::BuiltinAttrs => break, // nowhere else to search
|
Scope::BuiltinAttrs => break, // nowhere else to search
|
||||||
Scope::ExternPrelude if module_and_extern_prelude => break,
|
Scope::ExternPreludeItems => Scope::ExternPreludeFlags,
|
||||||
Scope::ExternPrelude => Scope::ToolPrelude,
|
Scope::ExternPreludeFlags if module_and_extern_prelude || extern_prelude => break,
|
||||||
|
Scope::ExternPreludeFlags => Scope::ToolPrelude,
|
||||||
Scope::ToolPrelude => Scope::StdLibPrelude,
|
Scope::ToolPrelude => Scope::StdLibPrelude,
|
||||||
Scope::StdLibPrelude => match ns {
|
Scope::StdLibPrelude => match ns {
|
||||||
TypeNS => Scope::BuiltinTypes,
|
TypeNS => Scope::BuiltinTypes,
|
||||||
@@ -413,6 +419,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
ScopeSet::All(ns)
|
ScopeSet::All(ns)
|
||||||
| ScopeSet::ModuleAndExternPrelude(ns, _)
|
| ScopeSet::ModuleAndExternPrelude(ns, _)
|
||||||
| ScopeSet::Late(ns, ..) => (ns, None),
|
| ScopeSet::Late(ns, ..) => (ns, None),
|
||||||
|
ScopeSet::ExternPrelude => (TypeNS, None),
|
||||||
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
|
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -429,6 +436,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// to detect potential ambiguities.
|
// to detect potential ambiguities.
|
||||||
let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None;
|
let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None;
|
||||||
let mut determinacy = Determinacy::Determined;
|
let mut determinacy = Determinacy::Determined;
|
||||||
|
// Shadowed bindings don't need to be marked as used or non-speculatively loaded.
|
||||||
|
macro finalize_scope() {
|
||||||
|
if innermost_result.is_none() { finalize } else { None }
|
||||||
|
}
|
||||||
|
|
||||||
// Go through all the scopes and try to resolve the name.
|
// Go through all the scopes and try to resolve the name.
|
||||||
let break_result = self.visit_scopes(
|
let break_result = self.visit_scopes(
|
||||||
@@ -494,7 +505,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
_ => Err(Determinacy::Determined),
|
_ => Err(Determinacy::Determined),
|
||||||
},
|
},
|
||||||
Scope::Module(module, derive_fallback_lint_id) => {
|
Scope::Module(module, derive_fallback_lint_id) => {
|
||||||
let (adjusted_parent_scope, finalize) =
|
// FIXME: use `finalize_scope` here.
|
||||||
|
let (adjusted_parent_scope, adjusted_finalize) =
|
||||||
if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) {
|
if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) {
|
||||||
(parent_scope, finalize)
|
(parent_scope, finalize)
|
||||||
} else {
|
} else {
|
||||||
@@ -513,7 +525,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
Shadowing::Restricted
|
Shadowing::Restricted
|
||||||
},
|
},
|
||||||
finalize,
|
adjusted_finalize,
|
||||||
ignore_binding,
|
ignore_binding,
|
||||||
ignore_import,
|
ignore_import,
|
||||||
);
|
);
|
||||||
@@ -561,14 +573,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
Some(binding) => Ok((*binding, Flags::empty())),
|
Some(binding) => Ok((*binding, Flags::empty())),
|
||||||
None => Err(Determinacy::Determined),
|
None => Err(Determinacy::Determined),
|
||||||
},
|
},
|
||||||
Scope::ExternPrelude => {
|
Scope::ExternPreludeItems => {
|
||||||
match this.reborrow().extern_prelude_get(ident, finalize.is_some()) {
|
// FIXME: use `finalize_scope` here.
|
||||||
|
match this.reborrow().extern_prelude_get_item(ident, finalize.is_some()) {
|
||||||
Some(binding) => Ok((binding, Flags::empty())),
|
Some(binding) => Ok((binding, Flags::empty())),
|
||||||
None => Err(Determinacy::determined(
|
None => Err(Determinacy::determined(
|
||||||
this.graph_root.unexpanded_invocations.borrow().is_empty(),
|
this.graph_root.unexpanded_invocations.borrow().is_empty(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Scope::ExternPreludeFlags => {
|
||||||
|
match this.extern_prelude_get_flag(ident, finalize_scope!().is_some()) {
|
||||||
|
Some(binding) => Ok((binding, Flags::empty())),
|
||||||
|
None => Err(Determinacy::Determined),
|
||||||
|
}
|
||||||
|
}
|
||||||
Scope::ToolPrelude => match this.registered_tool_bindings.get(&ident) {
|
Scope::ToolPrelude => match this.registered_tool_bindings.get(&ident) {
|
||||||
Some(binding) => Ok((*binding, Flags::empty())),
|
Some(binding) => Ok((*binding, Flags::empty())),
|
||||||
None => Err(Determinacy::Determined),
|
None => Err(Determinacy::Determined),
|
||||||
@@ -599,8 +618,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
if matches!(ident.name, sym::f16)
|
if matches!(ident.name, sym::f16)
|
||||||
&& !this.tcx.features().f16()
|
&& !this.tcx.features().f16()
|
||||||
&& !ident.span.allows_unstable(sym::f16)
|
&& !ident.span.allows_unstable(sym::f16)
|
||||||
&& finalize.is_some()
|
&& finalize_scope!().is_some()
|
||||||
&& innermost_result.is_none()
|
|
||||||
{
|
{
|
||||||
feature_err(
|
feature_err(
|
||||||
this.tcx.sess,
|
this.tcx.sess,
|
||||||
@@ -613,8 +631,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
if matches!(ident.name, sym::f128)
|
if matches!(ident.name, sym::f128)
|
||||||
&& !this.tcx.features().f128()
|
&& !this.tcx.features().f128()
|
||||||
&& !ident.span.allows_unstable(sym::f128)
|
&& !ident.span.allows_unstable(sym::f128)
|
||||||
&& finalize.is_some()
|
&& finalize_scope!().is_some()
|
||||||
&& innermost_result.is_none()
|
|
||||||
{
|
{
|
||||||
feature_err(
|
feature_err(
|
||||||
this.tcx.sess,
|
this.tcx.sess,
|
||||||
@@ -829,15 +846,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
assert_eq!(shadowing, Shadowing::Unrestricted);
|
assert_eq!(shadowing, Shadowing::Unrestricted);
|
||||||
return if ns != TypeNS {
|
return if ns != TypeNS {
|
||||||
Err((Determined, Weak::No))
|
Err((Determined, Weak::No))
|
||||||
} else if let Some(binding) =
|
|
||||||
self.reborrow().extern_prelude_get(ident, finalize.is_some())
|
|
||||||
{
|
|
||||||
Ok(binding)
|
|
||||||
} else if !self.graph_root.unexpanded_invocations.borrow().is_empty() {
|
|
||||||
// Macro-expanded `extern crate` items can add names to extern prelude.
|
|
||||||
Err((Undetermined, Weak::No))
|
|
||||||
} else {
|
} else {
|
||||||
Err((Determined, Weak::No))
|
let binding = self.early_resolve_ident_in_lexical_scope(
|
||||||
|
ident,
|
||||||
|
ScopeSet::ExternPrelude,
|
||||||
|
parent_scope,
|
||||||
|
finalize,
|
||||||
|
finalize.is_some(),
|
||||||
|
ignore_binding,
|
||||||
|
ignore_import,
|
||||||
|
);
|
||||||
|
return binding.map_err(|determinacy| (determinacy, Weak::No));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
ModuleOrUniformRoot::CurrentScope => {
|
ModuleOrUniformRoot::CurrentScope => {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#![feature(arbitrary_self_types)]
|
#![feature(arbitrary_self_types)]
|
||||||
#![feature(assert_matches)]
|
#![feature(assert_matches)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
|
#![feature(decl_macro)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(iter_intersperse)]
|
#![feature(iter_intersperse)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
@@ -113,34 +114,46 @@ impl Determinacy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A specific scope in which a name can be looked up.
|
/// A specific scope in which a name can be looked up.
|
||||||
/// This enum is currently used only for early resolution (imports and macros),
|
|
||||||
/// but not for late resolution yet.
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
enum Scope<'ra> {
|
enum Scope<'ra> {
|
||||||
|
/// Inert attributes registered by derive macros.
|
||||||
DeriveHelpers(LocalExpnId),
|
DeriveHelpers(LocalExpnId),
|
||||||
|
/// Inert attributes registered by derive macros, but used before they are actually declared.
|
||||||
|
/// This scope will exist until the compatibility lint `LEGACY_DERIVE_HELPERS`
|
||||||
|
/// is turned into a hard error.
|
||||||
DeriveHelpersCompat,
|
DeriveHelpersCompat,
|
||||||
|
/// Textual `let`-like scopes introduced by `macro_rules!` items.
|
||||||
MacroRules(MacroRulesScopeRef<'ra>),
|
MacroRules(MacroRulesScopeRef<'ra>),
|
||||||
// The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK`
|
/// Names declared in the given module.
|
||||||
// lint if it should be reported.
|
/// The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK`
|
||||||
|
/// lint if it should be reported.
|
||||||
Module(Module<'ra>, Option<NodeId>),
|
Module(Module<'ra>, Option<NodeId>),
|
||||||
|
/// Names introduced by `#[macro_use]` attributes on `extern crate` items.
|
||||||
MacroUsePrelude,
|
MacroUsePrelude,
|
||||||
|
/// Built-in attributes.
|
||||||
BuiltinAttrs,
|
BuiltinAttrs,
|
||||||
ExternPrelude,
|
/// Extern prelude names introduced by `extern crate` items.
|
||||||
|
ExternPreludeItems,
|
||||||
|
/// Extern prelude names introduced by `--extern` flags.
|
||||||
|
ExternPreludeFlags,
|
||||||
|
/// Tool modules introduced with `#![register_tool]`.
|
||||||
ToolPrelude,
|
ToolPrelude,
|
||||||
|
/// Standard library prelude introduced with an internal `#[prelude_import]` import.
|
||||||
StdLibPrelude,
|
StdLibPrelude,
|
||||||
|
/// Built-in types.
|
||||||
BuiltinTypes,
|
BuiltinTypes,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Names from different contexts may want to visit different subsets of all specific scopes
|
/// Names from different contexts may want to visit different subsets of all specific scopes
|
||||||
/// with different restrictions when looking up the resolution.
|
/// with different restrictions when looking up the resolution.
|
||||||
/// This enum is currently used only for early resolution (imports and macros),
|
|
||||||
/// but not for late resolution yet.
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
enum ScopeSet<'ra> {
|
enum ScopeSet<'ra> {
|
||||||
/// All scopes with the given namespace.
|
/// All scopes with the given namespace.
|
||||||
All(Namespace),
|
All(Namespace),
|
||||||
/// A module, then extern prelude (used for mixed 2015-2018 mode in macros).
|
/// A module, then extern prelude (used for mixed 2015-2018 mode in macros).
|
||||||
ModuleAndExternPrelude(Namespace, Module<'ra>),
|
ModuleAndExternPrelude(Namespace, Module<'ra>),
|
||||||
|
/// Just two extern prelude scopes.
|
||||||
|
ExternPrelude,
|
||||||
/// All scopes with macro namespace and the given macro kind restriction.
|
/// All scopes with macro namespace and the given macro kind restriction.
|
||||||
Macro(MacroKind),
|
Macro(MacroKind),
|
||||||
/// All scopes with the given namespace, used for partially performing late resolution.
|
/// All scopes with the given namespace, used for partially performing late resolution.
|
||||||
@@ -1012,16 +1025,18 @@ impl<'ra> NameBindingData<'ra> {
|
|||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
struct ExternPreludeEntry<'ra> {
|
struct ExternPreludeEntry<'ra> {
|
||||||
binding: Cell<Option<NameBinding<'ra>>>,
|
/// Binding from an `extern crate` item.
|
||||||
|
item_binding: Option<NameBinding<'ra>>,
|
||||||
|
/// Binding from an `--extern` flag, lazily populated on first use.
|
||||||
|
flag_binding: Cell<Option<NameBinding<'ra>>>,
|
||||||
|
/// There was no `--extern` flag introducing this name,
|
||||||
|
/// `flag_binding` doesn't need to be populated.
|
||||||
|
only_item: bool,
|
||||||
|
/// `item_binding` is non-redundant, happens either when `only_item` is true,
|
||||||
|
/// or when `extern crate` introducing `item_binding` used renaming.
|
||||||
introduced_by_item: bool,
|
introduced_by_item: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExternPreludeEntry<'_> {
|
|
||||||
fn is_import(&self) -> bool {
|
|
||||||
self.binding.get().is_some_and(|binding| binding.is_import())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DeriveData {
|
struct DeriveData {
|
||||||
resolutions: Vec<DeriveResolution>,
|
resolutions: Vec<DeriveResolution>,
|
||||||
helper_attrs: Vec<(usize, Ident)>,
|
helper_attrs: Vec<(usize, Ident)>,
|
||||||
@@ -1889,7 +1904,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
this.get_mut().traits_in_module(module, assoc_item, &mut found_traits);
|
this.get_mut().traits_in_module(module, assoc_item, &mut found_traits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scope::ExternPrelude | Scope::ToolPrelude | Scope::BuiltinTypes => {}
|
Scope::ExternPreludeItems
|
||||||
|
| Scope::ExternPreludeFlags
|
||||||
|
| Scope::ToolPrelude
|
||||||
|
| Scope::BuiltinTypes => {}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
None::<()>
|
None::<()>
|
||||||
@@ -2054,7 +2072,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// but not introduce it, as used if they are accessed from lexical scope.
|
// but not introduce it, as used if they are accessed from lexical scope.
|
||||||
if used == Used::Scope {
|
if used == Used::Scope {
|
||||||
if let Some(entry) = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)) {
|
if let Some(entry) = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)) {
|
||||||
if !entry.introduced_by_item && entry.binding.get() == Some(used_binding) {
|
if !entry.introduced_by_item && entry.item_binding == Some(used_binding) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2210,26 +2228,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extern_prelude_get<'r>(
|
fn extern_prelude_get_item<'r>(
|
||||||
mut self: CmResolver<'r, 'ra, 'tcx>,
|
mut self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
finalize: bool,
|
finalize: bool,
|
||||||
) -> Option<NameBinding<'ra>> {
|
) -> Option<NameBinding<'ra>> {
|
||||||
let mut record_use = None;
|
|
||||||
let entry = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident));
|
let entry = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident));
|
||||||
let binding = entry.and_then(|entry| match entry.binding.get() {
|
entry.and_then(|entry| entry.item_binding).map(|binding| {
|
||||||
Some(binding) if binding.is_import() => {
|
if finalize {
|
||||||
if finalize {
|
self.get_mut().record_use(ident, binding, Used::Scope);
|
||||||
record_use = Some(binding);
|
|
||||||
}
|
|
||||||
Some(binding)
|
|
||||||
}
|
}
|
||||||
|
binding
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extern_prelude_get_flag(&self, ident: Ident, finalize: bool) -> Option<NameBinding<'ra>> {
|
||||||
|
let entry = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident));
|
||||||
|
entry.and_then(|entry| match entry.flag_binding.get() {
|
||||||
Some(binding) => {
|
Some(binding) => {
|
||||||
if finalize {
|
if finalize {
|
||||||
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
|
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
|
||||||
}
|
}
|
||||||
Some(binding)
|
Some(binding)
|
||||||
}
|
}
|
||||||
|
None if entry.only_item => None,
|
||||||
None => {
|
None => {
|
||||||
let crate_id = if finalize {
|
let crate_id = if finalize {
|
||||||
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span)
|
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span)
|
||||||
@@ -2241,19 +2263,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
let res = Res::Def(DefKind::Mod, crate_id.as_def_id());
|
let res = Res::Def(DefKind::Mod, crate_id.as_def_id());
|
||||||
let binding =
|
let binding =
|
||||||
self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT);
|
self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT);
|
||||||
entry.binding.set(Some(binding));
|
entry.flag_binding.set(Some(binding));
|
||||||
Some(binding)
|
Some(binding)
|
||||||
}
|
}
|
||||||
None => finalize.then_some(self.dummy_binding),
|
None => finalize.then_some(self.dummy_binding),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
if let Some(binding) = record_use {
|
|
||||||
self.get_mut().record_use(ident, binding, Used::Scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
binding
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rustdoc uses this to resolve doc link paths in a recoverable way. `PathResult<'a>`
|
/// Rustdoc uses this to resolve doc link paths in a recoverable way. `PathResult<'a>`
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ macro_rules! m {
|
|||||||
|
|
||||||
m!();
|
m!();
|
||||||
|
|
||||||
use std::mem;
|
use std::mem; //~ ERROR `std` is ambiguous
|
||||||
|
use ::std::mem as _; //~ ERROR `std` is ambiguous
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -9,5 +9,47 @@ LL | m!();
|
|||||||
|
|
|
|
||||||
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error[E0659]: `std` is ambiguous
|
||||||
|
--> $DIR/issue-109148.rs:13:5
|
||||||
|
|
|
||||||
|
LL | use std::mem;
|
||||||
|
| ^^^ 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: `std` could refer to a built-in crate
|
||||||
|
= help: use `::std` to refer to this crate unambiguously
|
||||||
|
note: `std` could also refer to the crate imported here
|
||||||
|
--> $DIR/issue-109148.rs:6:9
|
||||||
|
|
|
||||||
|
LL | extern crate core as std;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | m!();
|
||||||
|
| ---- in this macro invocation
|
||||||
|
= help: use `::std` to refer to this crate unambiguously
|
||||||
|
= help: or use `crate::std` to refer to this crate unambiguously
|
||||||
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error[E0659]: `std` is ambiguous
|
||||||
|
--> $DIR/issue-109148.rs:14:7
|
||||||
|
|
|
||||||
|
LL | use ::std::mem as _;
|
||||||
|
| ^^^ 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: `std` could refer to a built-in crate
|
||||||
|
= help: use `::std` to refer to this crate unambiguously
|
||||||
|
note: `std` could also refer to the crate imported here
|
||||||
|
--> $DIR/issue-109148.rs:6:9
|
||||||
|
|
|
||||||
|
LL | extern crate core as std;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | m!();
|
||||||
|
| ---- in this macro invocation
|
||||||
|
= help: use `::std` to refer to this crate unambiguously
|
||||||
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0659`.
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//@ edition: 2018
|
||||||
|
|
||||||
macro_rules! define_other_core {
|
macro_rules! define_other_core {
|
||||||
( ) => {
|
( ) => {
|
||||||
extern crate std as core;
|
extern crate std as core;
|
||||||
@@ -6,7 +8,8 @@ macro_rules! define_other_core {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
core::panic!();
|
core::panic!(); //~ ERROR `core` is ambiguous
|
||||||
|
::core::panic!(); //~ ERROR `core` is ambiguous
|
||||||
}
|
}
|
||||||
|
|
||||||
define_other_core!();
|
define_other_core!();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
error: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
|
error: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
|
||||||
--> $DIR/issue-78325-inconsistent-resolution.rs:3:9
|
--> $DIR/issue-78325-inconsistent-resolution.rs:5:9
|
||||||
|
|
|
|
||||||
LL | extern crate std as core;
|
LL | extern crate std as core;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@@ -9,5 +9,47 @@ LL | define_other_core!();
|
|||||||
|
|
|
|
||||||
= note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error[E0659]: `core` is ambiguous
|
||||||
|
--> $DIR/issue-78325-inconsistent-resolution.rs:11:5
|
||||||
|
|
|
||||||
|
LL | core::panic!();
|
||||||
|
| ^^^^ 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: `core` could refer to a built-in crate
|
||||||
|
= help: use `::core` to refer to this crate unambiguously
|
||||||
|
note: `core` could also refer to the crate imported here
|
||||||
|
--> $DIR/issue-78325-inconsistent-resolution.rs:5:9
|
||||||
|
|
|
||||||
|
LL | extern crate std as core;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | define_other_core!();
|
||||||
|
| -------------------- in this macro invocation
|
||||||
|
= help: use `::core` to refer to this crate unambiguously
|
||||||
|
= help: or use `crate::core` to refer to this crate unambiguously
|
||||||
|
= note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error[E0659]: `core` is ambiguous
|
||||||
|
--> $DIR/issue-78325-inconsistent-resolution.rs:12:7
|
||||||
|
|
|
||||||
|
LL | ::core::panic!();
|
||||||
|
| ^^^^ 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: `core` could refer to a built-in crate
|
||||||
|
= help: use `::core` to refer to this crate unambiguously
|
||||||
|
note: `core` could also refer to the crate imported here
|
||||||
|
--> $DIR/issue-78325-inconsistent-resolution.rs:5:9
|
||||||
|
|
|
||||||
|
LL | extern crate std as core;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | define_other_core!();
|
||||||
|
| -------------------- in this macro invocation
|
||||||
|
= help: use `::core` to refer to this crate unambiguously
|
||||||
|
= note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0659`.
|
||||||
|
|||||||
10
tests/ui/resolve/extern-prelude-speculative.rs
Normal file
10
tests/ui/resolve/extern-prelude-speculative.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// Non-existent path in `--extern` doesn't result in an error if it's shadowed by `extern crate`.
|
||||||
|
|
||||||
|
//@ check-pass
|
||||||
|
//@ compile-flags: --extern something=/path/to/nowhere
|
||||||
|
|
||||||
|
extern crate std as something;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
something::println!();
|
||||||
|
}
|
||||||
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
foo!(); //~ ERROR cannot find macro `foo` in this scope
|
foo!(); //~ ERROR cannot find macro `foo` in this scope
|
||||||
|
|
||||||
pub(in ::bar) struct Baz {} //~ ERROR cannot determine resolution for the visibility
|
pub(in ::bar) struct Baz {} //~ ERROR failed to resolve: could not find `bar` in the list of imported crates
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
error[E0578]: cannot determine resolution for the visibility
|
error[E0433]: failed to resolve: could not find `bar` in the list of imported crates
|
||||||
--> $DIR/visibility-indeterminate.rs:5:8
|
--> $DIR/visibility-indeterminate.rs:5:10
|
||||||
|
|
|
|
||||||
LL | pub(in ::bar) struct Baz {}
|
LL | pub(in ::bar) struct Baz {}
|
||||||
| ^^^^^
|
| ^^^ could not find `bar` in the list of imported crates
|
||||||
|
|
||||||
error: cannot find macro `foo` in this scope
|
error: cannot find macro `foo` in this scope
|
||||||
--> $DIR/visibility-indeterminate.rs:3:1
|
--> $DIR/visibility-indeterminate.rs:3:1
|
||||||
@@ -12,4 +12,4 @@ LL | foo!();
|
|||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0578`.
|
For more information about this error, try `rustc --explain E0433`.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//@ compile-flags:--extern foo --extern bar
|
//@ compile-flags:--extern foo --extern bar
|
||||||
|
|
||||||
use bar::foo; //~ ERROR can't find crate for `bar`
|
use bar::foo; //~ ERROR can't find crate for `bar`
|
||||||
use foo::bar; //~ ERROR can't find crate for `foo`
|
use foo::bar;
|
||||||
//~^^ ERROR unresolved imports `bar::foo`, `foo::bar`
|
//~^^ ERROR unresolved imports `bar::foo`, `foo::bar`
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|||||||
@@ -4,12 +4,6 @@ error[E0463]: can't find crate for `bar`
|
|||||||
LL | use bar::foo;
|
LL | use bar::foo;
|
||||||
| ^^^ can't find crate
|
| ^^^ can't find crate
|
||||||
|
|
||||||
error[E0463]: can't find crate for `foo`
|
|
||||||
--> $DIR/deadlock.rs:5:5
|
|
||||||
|
|
|
||||||
LL | use foo::bar;
|
|
||||||
| ^^^ can't find crate
|
|
||||||
|
|
||||||
error[E0432]: unresolved imports `bar::foo`, `foo::bar`
|
error[E0432]: unresolved imports `bar::foo`, `foo::bar`
|
||||||
--> $DIR/deadlock.rs:4:5
|
--> $DIR/deadlock.rs:4:5
|
||||||
|
|
|
|
||||||
@@ -18,7 +12,7 @@ LL | use bar::foo;
|
|||||||
LL | use foo::bar;
|
LL | use foo::bar;
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0432, E0463.
|
Some errors have detailed explanations: E0432, E0463.
|
||||||
For more information about an error, try `rustc --explain E0432`.
|
For more information about an error, try `rustc --explain E0432`.
|
||||||
|
|||||||
Reference in New Issue
Block a user