Skip to content

Commit bc9556f

Browse files
committed
resolve namespaced crates with virtual root
1 parent 79e7d5e commit bc9556f

8 files changed

Lines changed: 240 additions & 98 deletions

File tree

compiler/rustc_hir/src/def.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,13 @@ pub enum Res<Id = hir::HirId> {
604604
///
605605
/// **Not bound to a specific namespace.**
606606
Err,
607+
608+
/// The resolution for a virtual module in a namespaced crate. E.g. `my_api`
609+
/// in the namespaced crate `my_api::utils` when `my_api` isn't part of the
610+
/// extern prelude.
611+
///
612+
/// **Belongs to the type namespace.**
613+
VirtualMod(Symbol),
607614
}
608615

609616
impl<Id> IntoDiagArg for Res<Id> {
@@ -838,6 +845,7 @@ impl<Id> Res<Id> {
838845
| Res::SelfTyAlias { .. }
839846
| Res::SelfCtor(..)
840847
| Res::ToolMod
848+
| Res::VirtualMod(..)
841849
| Res::NonMacroAttr(..)
842850
| Res::Err => None,
843851
}
@@ -869,6 +877,7 @@ impl<Id> Res<Id> {
869877
Res::Local(..) => "local variable",
870878
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => "self type",
871879
Res::ToolMod => "tool module",
880+
Res::VirtualMod(..) => "namespaced crate",
872881
Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
873882
Res::Err => "unresolved item",
874883
}
@@ -895,6 +904,7 @@ impl<Id> Res<Id> {
895904
Res::SelfTyAlias { alias_to, is_trait_impl }
896905
}
897906
Res::ToolMod => Res::ToolMod,
907+
Res::VirtualMod(sym) => Res::VirtualMod(sym),
898908
Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
899909
Res::Err => Res::Err,
900910
}
@@ -911,6 +921,7 @@ impl<Id> Res<Id> {
911921
Res::SelfTyAlias { alias_to, is_trait_impl }
912922
}
913923
Res::ToolMod => Res::ToolMod,
924+
Res::VirtualMod(sym) => Res::VirtualMod(sym),
914925
Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
915926
Res::Err => Res::Err,
916927
})
@@ -936,9 +947,11 @@ impl<Id> Res<Id> {
936947
pub fn ns(&self) -> Option<Namespace> {
937948
match self {
938949
Res::Def(kind, ..) => kind.ns(),
939-
Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::ToolMod => {
940-
Some(Namespace::TypeNS)
941-
}
950+
Res::PrimTy(..)
951+
| Res::SelfTyParam { .. }
952+
| Res::SelfTyAlias { .. }
953+
| Res::ToolMod
954+
| Res::VirtualMod(..) => Some(Namespace::TypeNS),
942955
Res::SelfCtor(..) | Res::Local(..) => Some(Namespace::ValueNS),
943956
Res::NonMacroAttr(..) => Some(Namespace::MacroNS),
944957
Res::Err => None,

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2786,6 +2786,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
27862786
| Res::SelfCtor(_)
27872787
| Res::Local(_)
27882788
| Res::ToolMod
2789+
| Res::VirtualMod(..)
27892790
| Res::NonMacroAttr(_)
27902791
| Res::Err) => Const::new_error_with_message(
27912792
tcx,

compiler/rustc_passes/src/dead.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
157157
Res::Def(_, def_id) => self.check_def_id(def_id),
158158
Res::SelfTyParam { trait_: t } => self.check_def_id(t),
159159
Res::SelfTyAlias { alias_to: i, .. } => self.check_def_id(i),
160-
Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {}
160+
Res::ToolMod | Res::NonMacroAttr(..) | Res::VirtualMod(..) | Res::Err => {}
161161
}
162162
}
163163

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
326326
_,
327327
)
328328
| Res::PrimTy(..)
329+
| Res::VirtualMod(..)
329330
| Res::ToolMod => define_extern(TypeNS),
330331
Res::Def(
331332
DefKind::Fn

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// ignore-tidy-filelength
12
use std::ops::ControlFlow;
23

34
use itertools::Itertools as _;
@@ -1205,6 +1206,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
12051206
Scope::ModuleGlobs(..) => {
12061207
// Already handled in `ModuleNonGlobs`.
12071208
}
1209+
Scope::NamespacedCrates(..) => {}
12081210
Scope::MacroUsePrelude => {
12091211
suggestions.extend(this.macro_use_prelude.iter().filter_map(
12101212
|(name, binding)| {
@@ -1735,8 +1737,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
17351737
Res::Def(DefKind::Macro(kinds), _) => {
17361738
format!("{} {}", kinds.article(), kinds.descr())
17371739
}
1738-
Res::ToolMod => {
1739-
// Don't confuse the user with tool modules.
1740+
Res::ToolMod | Res::VirtualMod(..) => {
1741+
// Don't confuse the user with tool modules or virtual modules.
17401742
continue;
17411743
}
17421744
Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
@@ -1967,6 +1969,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
19671969
true
19681970
}
19691971

1972+
#[instrument(skip(self), level = "debug")]
19701973
fn decl_description(&self, b: Decl<'_>, ident: Ident, scope: Scope<'_>) -> String {
19711974
let res = b.res();
19721975
if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
@@ -1977,6 +1980,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
19771980
{
19781981
("", " passed with `--extern`")
19791982
}
1983+
Scope::ExternPreludeFlags if matches!(res, Res::VirtualMod(..)) => {
1984+
("", " passed with `--extern`")
1985+
}
19801986
_ => {
19811987
if matches!(res, Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod) {
19821988
// These already contain the "built-in" prefix or look bad with it.

compiler/rustc_resolve/src/ident.rs

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::{
2626
AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingKey, CmResolver, Decl, DeclKind,
2727
Determinacy, Finalize, IdentKey, ImportKind, LateDecl, Module, ModuleKind, ModuleOrUniformRoot,
2828
ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet,
29-
Segment, Stage, Used, errors,
29+
Segment, Stage, Symbol, Used, errors,
3030
};
3131

3232
#[derive(Copy, Clone)]
@@ -109,26 +109,40 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
109109
let (ns, macro_kind) = match scope_set {
110110
ScopeSet::All(ns)
111111
| ScopeSet::Module(ns, _)
112-
| ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
112+
| ScopeSet::ModuleAndExternPrelude(ns, _)
113+
| ScopeSet::NamespacedCrate(ns, _) => (ns, None),
113114
ScopeSet::ExternPrelude => (TypeNS, None),
114115
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
115116
};
116117
let module = match scope_set {
117118
// Start with the specified module.
118-
ScopeSet::Module(_, module) | ScopeSet::ModuleAndExternPrelude(_, module) => module,
119+
ScopeSet::Module(_, module) | ScopeSet::ModuleAndExternPrelude(_, module) => {
120+
Some(module)
121+
}
122+
ScopeSet::NamespacedCrate(_, _) => None,
119123
// Jump out of trait or enum modules, they do not act as scopes.
120-
_ => parent_scope.module.nearest_item_scope(),
124+
_ => Some(parent_scope.module.nearest_item_scope()),
121125
};
122126
let module_only = matches!(scope_set, ScopeSet::Module(..));
123127
let module_and_extern_prelude = matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..));
124128
let extern_prelude = matches!(scope_set, ScopeSet::ExternPrelude);
129+
let namespace_crate_only = matches!(scope_set, ScopeSet::NamespacedCrate(..));
125130
let mut scope = match ns {
126-
_ if module_only || module_and_extern_prelude => Scope::ModuleNonGlobs(module, None),
131+
_ if module_only || module_and_extern_prelude => {
132+
Scope::ModuleNonGlobs(module.unwrap(), None)
133+
}
134+
_ if namespace_crate_only => {
135+
let ScopeSet::NamespacedCrate(_, root_name) = scope_set else {
136+
unreachable!();
137+
};
138+
139+
Scope::NamespacedCrates(root_name)
140+
}
127141
_ if extern_prelude => Scope::ExternPreludeItems,
128-
TypeNS | ValueNS => Scope::ModuleNonGlobs(module, None),
142+
TypeNS | ValueNS => Scope::ModuleNonGlobs(module.unwrap(), None),
129143
MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
130144
};
131-
let mut use_prelude = !module.no_implicit_prelude;
145+
let mut use_prelude = module.map(|m| !m.no_implicit_prelude).unwrap_or_else(|| true);
132146

133147
loop {
134148
let visit = match scope {
@@ -151,7 +165,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
151165
}
152166
true
153167
}
154-
Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..) => true,
168+
Scope::ModuleNonGlobs(..)
169+
| Scope::ModuleGlobs(..)
170+
| Scope::NamespacedCrates(..) => true,
155171
Scope::MacroUsePrelude => use_prelude || orig_ident_span.is_rust_2015(),
156172
Scope::BuiltinAttrs => true,
157173
Scope::ExternPreludeItems | Scope::ExternPreludeFlags => {
@@ -192,7 +208,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
192208
MacroRulesScope::Invocation(invoc_id) => {
193209
Scope::MacroRules(self.invocation_parent_scopes[&invoc_id].macro_rules)
194210
}
195-
MacroRulesScope::Empty => Scope::ModuleNonGlobs(module, None),
211+
MacroRulesScope::Empty => Scope::ModuleNonGlobs(module.unwrap(), None),
196212
},
197213
Scope::ModuleNonGlobs(module, lint_id) => Scope::ModuleGlobs(module, lint_id),
198214
Scope::ModuleGlobs(..) if module_only => break,
@@ -219,6 +235,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
219235
}
220236
}
221237
}
238+
Scope::NamespacedCrates(..) => {
239+
assert!(namespace_crate_only);
240+
break;
241+
}
222242
Scope::MacroUsePrelude => Scope::StdLibPrelude,
223243
Scope::BuiltinAttrs => break, // nowhere else to search
224244
Scope::ExternPreludeItems => Scope::ExternPreludeFlags,
@@ -386,7 +406,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
386406
}
387407

388408
/// Resolve an identifier in the specified set of scopes.
389-
#[instrument(level = "debug", skip(self))]
390409
pub(crate) fn resolve_ident_in_scope_set<'r>(
391410
self: CmResolver<'r, 'ra, 'tcx>,
392411
orig_ident: Ident,
@@ -425,7 +444,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
425444
let (ns, macro_kind) = match scope_set {
426445
ScopeSet::All(ns)
427446
| ScopeSet::Module(ns, _)
428-
| ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
447+
| ScopeSet::ModuleAndExternPrelude(ns, _)
448+
| ScopeSet::NamespacedCrate(ns, _) => (ns, None),
429449
ScopeSet::ExternPrelude => (TypeNS, None),
430450
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
431451
};
@@ -686,6 +706,32 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
686706
Err(ControlFlow::Break(..)) => return binding,
687707
}
688708
}
709+
Scope::NamespacedCrates(sym) => {
710+
let try_find_namespaced_crate = |root_name: &Symbol| {
711+
self.namespaced_crate_names
712+
.get(root_name.as_str())
713+
.into_iter()
714+
.flatten()
715+
.find(|s| s.split("::").nth(1) == Some(ident.name.as_str()))
716+
};
717+
718+
let ns_crate_cand = try_find_namespaced_crate(&sym);
719+
match ns_crate_cand {
720+
Some(ns_cand) => {
721+
let ns_ident = IdentKey::with_root_ctxt(Symbol::intern(ns_cand));
722+
723+
match self.extern_prelude_get_flag(
724+
ns_ident,
725+
orig_ident_span,
726+
finalize.is_some(),
727+
) {
728+
Some(decl) => Ok(decl),
729+
None => Err(Determinacy::Determined),
730+
}
731+
}
732+
None => Err(Determinacy::Determined),
733+
}
734+
}
689735
Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() {
690736
Some(decl) => Ok(decl),
691737
None => Err(Determinacy::determined(
@@ -976,6 +1022,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
9761022
ignore_import,
9771023
)
9781024
}
1025+
ModuleOrUniformRoot::VirtualNamespacedCrate(sym) => self.resolve_ident_in_scope_set(
1026+
ident,
1027+
ScopeSet::NamespacedCrate(ns, sym),
1028+
parent_scope,
1029+
finalize,
1030+
ignore_decl,
1031+
ignore_import,
1032+
),
9791033
ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self.resolve_ident_in_scope_set(
9801034
ident,
9811035
ScopeSet::ModuleAndExternPrelude(ns, module),
@@ -1962,7 +2016,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
19622016
}
19632017

19642018
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
1965-
if let Some(def_id) = binding.res().module_like_def_id() {
2019+
if let Res::VirtualMod(sym) = binding.res() {
2020+
module = Some(ModuleOrUniformRoot::VirtualNamespacedCrate(sym));
2021+
record_segment_res(self.reborrow(), finalize, res, id);
2022+
} else if let Some(def_id) = binding.res().module_like_def_id() {
19662023
if self.mods_with_parse_errors.contains(&def_id) {
19672024
module_had_parse_errors = true;
19682025
}

0 commit comments

Comments
 (0)