Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions compiler/rustc_hir/src/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,13 @@ pub enum Res<Id = hir::HirId> {
///
/// **Not bound to a specific namespace.**
Err,

/// The resolution for a virtual module in a namespaced crate. E.g. `my_api`
/// in the namespaced crate `my_api::utils` when `my_api` isn't part of the
/// extern prelude.
///
/// **Belongs to the type namespace.**
VirtualMod(Symbol),
}

impl<Id> IntoDiagArg for Res<Id> {
Expand Down Expand Up @@ -834,6 +841,7 @@ impl<Id> Res<Id> {
| Res::SelfTyAlias { .. }
| Res::SelfCtor(..)
| Res::ToolMod
| Res::VirtualMod(..)
| Res::NonMacroAttr(..)
| Res::Err => None,
}
Expand Down Expand Up @@ -865,6 +873,7 @@ impl<Id> Res<Id> {
Res::Local(..) => "local variable",
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => "self type",
Res::ToolMod => "tool module",
Res::VirtualMod(..) => "virtual module for namespaced crate",
Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
Res::Err => "unresolved item",
}
Expand All @@ -891,6 +900,7 @@ impl<Id> Res<Id> {
Res::SelfTyAlias { alias_to, is_trait_impl }
}
Res::ToolMod => Res::ToolMod,
Res::VirtualMod(sym) => Res::VirtualMod(sym),
Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
Res::Err => Res::Err,
}
Expand All @@ -907,6 +917,7 @@ impl<Id> Res<Id> {
Res::SelfTyAlias { alias_to, is_trait_impl }
}
Res::ToolMod => Res::ToolMod,
Res::VirtualMod(sym) => Res::VirtualMod(sym),
Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
Res::Err => Res::Err,
})
Expand All @@ -932,9 +943,11 @@ impl<Id> Res<Id> {
pub fn ns(&self) -> Option<Namespace> {
match self {
Res::Def(kind, ..) => kind.ns(),
Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::ToolMod => {
Some(Namespace::TypeNS)
}
Res::PrimTy(..)
| Res::SelfTyParam { .. }
| Res::SelfTyAlias { .. }
| Res::ToolMod
| Res::VirtualMod(..) => Some(Namespace::TypeNS),
Res::SelfCtor(..) | Res::Local(..) => Some(Namespace::ValueNS),
Res::NonMacroAttr(..) => Some(Namespace::MacroNS),
Res::Err => None,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2769,6 +2769,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
| Res::SelfCtor(_)
| Res::Local(_)
| Res::ToolMod
| Res::VirtualMod(..)
| Res::NonMacroAttr(_)
| Res::Err) => Const::new_error_with_message(
tcx,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
Res::Def(_, def_id) => self.check_def_id(def_id),
Res::SelfTyParam { trait_: t } => self.check_def_id(t),
Res::SelfTyAlias { alias_to: i, .. } => self.check_def_id(i),
Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {}
Res::ToolMod | Res::NonMacroAttr(..) | Res::VirtualMod(..) | Res::Err => {}
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
_,
)
| Res::PrimTy(..)
| Res::VirtualMod(..)
| Res::ToolMod => define_extern(TypeNS),
Res::Def(
DefKind::Fn
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1204,6 +1204,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
Scope::ModuleGlobs(..) => {
// Already handled in `ModuleNonGlobs`.
}
Scope::NamespacedCrates(..) => {}
Scope::MacroUsePrelude => {
suggestions.extend(this.macro_use_prelude.iter().filter_map(
|(name, binding)| {
Expand Down Expand Up @@ -1735,8 +1736,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
Res::Def(DefKind::Macro(kinds), _) => {
format!("{} {}", kinds.article(), kinds.descr())
}
Res::ToolMod => {
// Don't confuse the user with tool modules.
Res::ToolMod | Res::VirtualMod(..) => {
// Don't confuse the user with tool modules or virtual modules.
continue;
}
Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
Expand Down
126 changes: 111 additions & 15 deletions compiler/rustc_resolve/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use crate::macros::{MacroRulesScope, sub_namespace_match};
use crate::{
AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingKey, CmResolver, Decl, DeclKind,
Determinacy, Finalize, IdentKey, ImportKind, LateDecl, Module, ModuleKind, ModuleOrUniformRoot,
ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet,
Segment, Stage, Used, errors,
NamespacedCrateRoot, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver,
Scope, ScopeSet, Segment, Stage, Symbol, Used, errors,
};

#[derive(Copy, Clone)]
Expand Down Expand Up @@ -109,26 +109,40 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let (ns, macro_kind) = match scope_set {
ScopeSet::All(ns)
| ScopeSet::Module(ns, _)
| ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
| ScopeSet::ModuleAndExternPrelude(ns, _)
| ScopeSet::NamespacedCrate(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::Module(_, module) | ScopeSet::ModuleAndExternPrelude(_, module) => module,
ScopeSet::Module(_, module) | ScopeSet::ModuleAndExternPrelude(_, module) => {
Some(module)
}
ScopeSet::NamespacedCrate(_, _) => None,
// Jump out of trait or enum modules, they do not act as scopes.
_ => parent_scope.module.nearest_item_scope(),
_ => Some(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 namespace_crate_only = matches!(scope_set, ScopeSet::NamespacedCrate(..));
let mut scope = match ns {
_ if module_only || module_and_extern_prelude => Scope::ModuleNonGlobs(module, None),
_ if module_only || module_and_extern_prelude => {
Scope::ModuleNonGlobs(module.unwrap(), None)
}
_ if namespace_crate_only => {
let ScopeSet::NamespacedCrate(_, root_name) = scope_set else {
unreachable!();
};

Scope::NamespacedCrates(NamespacedCrateRoot::VirtualMod(root_name), None)
}
_ if extern_prelude => Scope::ExternPreludeItems,
TypeNS | ValueNS => Scope::ModuleNonGlobs(module, None),
TypeNS | ValueNS => Scope::ModuleNonGlobs(module.unwrap(), None),
MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
};
let mut use_prelude = !module.no_implicit_prelude;
let mut use_prelude = module.map(|m| !m.no_implicit_prelude).unwrap_or_else(|| true);

loop {
let visit = match scope {
Expand All @@ -151,7 +165,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
true
}
Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..) => true,
Scope::ModuleNonGlobs(..)
| Scope::ModuleGlobs(..)
| Scope::NamespacedCrates(..) => true,
Scope::MacroUsePrelude => use_prelude || orig_ident_span.is_rust_2015(),
Scope::BuiltinAttrs => true,
Scope::ExternPreludeItems | Scope::ExternPreludeFlags => {
Expand Down Expand Up @@ -192,18 +208,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
MacroRulesScope::Invocation(invoc_id) => {
Scope::MacroRules(self.invocation_parent_scopes[&invoc_id].macro_rules)
}
MacroRulesScope::Empty => Scope::ModuleNonGlobs(module, None),
MacroRulesScope::Empty => Scope::ModuleNonGlobs(module.unwrap(), None),
},
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 {
Scope::ModuleGlobs(module, lint_id) if module_only => {
Scope::NamespacedCrates(NamespacedCrateRoot::Mod(module), lint_id)
}
Scope::NamespacedCrates(..) if module_only | namespace_crate_only => break,
Scope::ModuleGlobs(module, lint_id) if module_and_extern_prelude => {
Scope::NamespacedCrates(NamespacedCrateRoot::Mod(module), lint_id)
}
Scope::NamespacedCrates(..) if module_and_extern_prelude => match ns {
TypeNS => {
ctxt.update_unchecked(|ctxt| ctxt.adjust(ExpnId::root()));
Scope::ExternPreludeItems
}
ValueNS | MacroNS => break,
},
Scope::ModuleGlobs(module, prev_lint_id) => {
Scope::NamespacedCrates(NamespacedCrateRoot::Mod(module), prev_lint_id)
}
Scope::NamespacedCrates(namespace_crate_root, prev_lint_id) => {
let module = namespace_crate_root.get_mod();
use_prelude = !module.no_implicit_prelude;
match self.hygienic_lexical_parent(module, &mut ctxt, derive_fallback_lint_id) {
Some((parent_module, lint_id)) => {
Expand Down Expand Up @@ -386,7 +412,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}

/// Resolve an identifier in the specified set of scopes.
#[instrument(level = "debug", skip(self))]
pub(crate) fn resolve_ident_in_scope_set<'r>(
self: CmResolver<'r, 'ra, 'tcx>,
orig_ident: Ident,
Expand Down Expand Up @@ -425,7 +450,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let (ns, macro_kind) = match scope_set {
ScopeSet::All(ns)
| ScopeSet::Module(ns, _)
| ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
| ScopeSet::ModuleAndExternPrelude(ns, _)
| ScopeSet::NamespacedCrate(ns, _) => (ns, None),
ScopeSet::ExternPrelude => (TypeNS, None),
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
};
Expand Down Expand Up @@ -686,6 +712,65 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
Err(ControlFlow::Break(..)) => return binding,
}
}
Scope::NamespacedCrates(ns_root, _) => {
let try_find_namespaced_crate = |root_name: &Symbol| {
self.namespaced_crate_names
.get(root_name.as_str())
.into_iter()
.flatten()
.find(|s| s.split("::").nth(1) == Some(ident.name.as_str()))
};

match ns_root {
NamespacedCrateRoot::Mod(module) => {
if let Some(def_id) = module.opt_def_id() {
if let Some(ns_base_name) =
self.def_id_to_namespaced_crate_names.borrow().get(&def_id)
{
let ns_crate_cand = try_find_namespaced_crate(ns_base_name);
match ns_crate_cand {
Some(ns_cand) => {
let ns_ident =
IdentKey::with_root_ctxt(Symbol::intern(ns_cand));

match self.extern_prelude_get_flag(
ns_ident,
module.span,
finalize.is_some(),
) {
Some(decl) => Ok(decl),
None => Err(Determinacy::Determined),
}
}
None => Err(Determinacy::Determined),
}
} else {
Err(Determinacy::Determined)
}
} else {
Err(Determinacy::Determined)
}
}
NamespacedCrateRoot::VirtualMod(sym) => {
let ns_crate_cand = try_find_namespaced_crate(&sym);
match ns_crate_cand {
Some(ns_cand) => {
let ns_ident = IdentKey::with_root_ctxt(Symbol::intern(ns_cand));

match self.extern_prelude_get_flag(
ns_ident,
orig_ident_span,
finalize.is_some(),
) {
Some(decl) => Ok(decl),
None => Err(Determinacy::Determined),
}
}
None => Err(Determinacy::Determined),
}
}
}
}
Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() {
Some(decl) => Ok(decl),
None => Err(Determinacy::determined(
Expand Down Expand Up @@ -951,6 +1036,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ignore_import,
)
}
ModuleOrUniformRoot::VirtualNamespacedCrate(sym) => self.resolve_ident_in_scope_set(
ident,
ScopeSet::NamespacedCrate(ns, sym),
parent_scope,
finalize,
ignore_decl,
ignore_import,
),
ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self.resolve_ident_in_scope_set(
ident,
ScopeSet::ModuleAndExternPrelude(ns, module),
Expand Down Expand Up @@ -1905,7 +1998,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}

let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
if let Some(def_id) = binding.res().module_like_def_id() {
if let Res::VirtualMod(sym) = binding.res() {
module = Some(ModuleOrUniformRoot::VirtualNamespacedCrate(sym));
record_segment_res(self.reborrow(), finalize, res, id);
} else if let Some(def_id) = binding.res().module_like_def_id() {
if self.mods_with_parse_errors.contains(&def_id) {
module_had_parse_errors = true;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type Res = def::Res<NodeId>;

/// A potential import declaration in the process of being planted into a module.
/// Also used for lazily planting names from `--extern` flags to extern prelude.
#[derive(Clone, Copy, Default, PartialEq)]
#[derive(Clone, Copy, Default, PartialEq, Debug)]
pub(crate) enum PendingDecl<'ra> {
Ready(Option<Decl<'ra>>),
#[default]
Expand Down
Loading
Loading