Auto merge of #15422 - Veykril:import-sources, r=Veykril

internal: Record import source IDs

cc https://github.com/rust-lang/rust-analyzer/issues/14079
This commit is contained in:
bors 2023-08-09 15:09:15 +00:00
commit b78d69c795
7 changed files with 220 additions and 185 deletions

View File

@ -487,7 +487,7 @@ pub(crate) fn extern_crate_decl_data_query(
db.crate_def_map(loc.container.krate())
.extern_prelude()
.find(|&(prelude_name, ..)| *prelude_name == name)
.map(|(_, root)| root.krate())
.map(|(_, (root, _))| root.krate())
};
Arc::new(Self {

View File

@ -11,7 +11,7 @@
nameres::DefMap,
path::{ModPath, PathKind},
visibility::Visibility,
ModuleDefId, ModuleId,
CrateRootModuleId, ModuleDefId, ModuleId,
};
/// Find a path that can be used to refer to a certain item. This can depend on
@ -81,7 +81,7 @@ fn find_path_inner(
}
let def_map = from.def_map(db);
let crate_root = def_map.crate_root().into();
let crate_root = def_map.crate_root();
// - if the item is a module, jump straight to module search
if let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item {
let mut visited_modules = FxHashSet::default();
@ -149,7 +149,7 @@ fn find_path_for_module(
db: &dyn DefDatabase,
def_map: &DefMap,
visited_modules: &mut FxHashSet<ModuleId>,
crate_root: ModuleId,
crate_root: CrateRootModuleId,
from: ModuleId,
module_id: ModuleId,
max_len: usize,
@ -183,7 +183,7 @@ fn find_path_for_module(
// - if the item is the crate root of a dependency crate, return the name from the extern prelude
let root_def_map = crate_root.def_map(db);
for (name, def_id) in root_def_map.extern_prelude() {
for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude() {
if module_id == def_id {
let name = scope_name.unwrap_or_else(|| name.clone());
@ -192,7 +192,7 @@ fn find_path_for_module(
def_map[local_id]
.scope
.type_(&name)
.filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id))
.filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id.into()))
})
.is_some();
let kind = if name_already_occupied_in_type_ns {
@ -244,7 +244,7 @@ fn find_in_prelude(
item: ItemInNs,
from: ModuleId,
) -> Option<ModPath> {
let prelude_module = root_def_map.prelude()?;
let (prelude_module, _) = root_def_map.prelude()?;
// Preludes in block DefMaps are ignored, only the crate DefMap is searched
let prelude_def_map = prelude_module.def_map(db);
let prelude_scope = &prelude_def_map[prelude_module.local_id].scope;
@ -293,7 +293,7 @@ fn calculate_best_path(
db: &dyn DefDatabase,
def_map: &DefMap,
visited_modules: &mut FxHashSet<ModuleId>,
crate_root: ModuleId,
crate_root: CrateRootModuleId,
max_len: usize,
item: ItemInNs,
from: ModuleId,

View File

@ -109,6 +109,17 @@ pub fn krate(self) -> CrateId {
}
}
impl PartialEq<ModuleId> for CrateRootModuleId {
fn eq(&self, other: &ModuleId) -> bool {
other.block.is_none() && other.local_id == DefMap::ROOT && self.krate == other.krate
}
}
impl PartialEq<CrateRootModuleId> for ModuleId {
fn eq(&self, other: &CrateRootModuleId) -> bool {
other == self
}
}
impl From<CrateRootModuleId> for ModuleId {
fn from(CrateRootModuleId { krate }: CrateRootModuleId) -> Self {
ModuleId { krate, block: None, local_id: DefMap::ROOT }

View File

@ -77,8 +77,8 @@
path::ModPath,
per_ns::PerNs,
visibility::Visibility,
AstId, BlockId, BlockLoc, CrateRootModuleId, FunctionId, LocalModuleId, Lookup, MacroExpander,
MacroId, ModuleId, ProcMacroId,
AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, LocalModuleId, Lookup,
MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
};
/// Contains the results of (early) name resolution.
@ -105,10 +105,10 @@ pub struct DefMap {
/// The prelude is empty for non-block DefMaps (unless `#[prelude_import]` was used,
/// but that attribute is nightly and when used in a block, it affects resolution globally
/// so we aren't handling this correctly anyways).
prelude: Option<ModuleId>,
prelude: Option<(ModuleId, Option<UseId>)>,
/// `macro_use` prelude that contains macros from `#[macro_use]`'d external crates. Note that
/// this contains all kinds of macro, not just `macro_rules!` macro.
macro_use_prelude: FxHashMap<Name, MacroId>,
macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>,
/// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
/// attributes.
@ -125,7 +125,7 @@ pub struct DefMap {
#[derive(Clone, Debug, PartialEq, Eq)]
struct DefMapCrateData {
/// The extern prelude which contains all root modules of external crates that are in scope.
extern_prelude: FxHashMap<Name, CrateRootModuleId>,
extern_prelude: FxHashMap<Name, (CrateRootModuleId, Option<ExternCrateId>)>,
/// Side table for resolving derive helpers.
exported_derives: FxHashMap<MacroDefId, Box<[Name]>>,
@ -427,15 +427,19 @@ pub(crate) fn block_id(&self) -> Option<BlockId> {
self.block.map(|block| block.block)
}
pub(crate) fn prelude(&self) -> Option<ModuleId> {
pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
self.prelude
}
pub(crate) fn extern_prelude(&self) -> impl Iterator<Item = (&Name, ModuleId)> + '_ {
self.data.extern_prelude.iter().map(|(name, &def)| (name, def.into()))
pub(crate) fn extern_prelude(
&self,
) -> impl Iterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_ {
self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
}
pub(crate) fn macro_use_prelude(&self) -> impl Iterator<Item = (&Name, MacroId)> + '_ {
pub(crate) fn macro_use_prelude(
&self,
) -> impl Iterator<Item = (&Name, (MacroId, Option<ExternCrateId>))> + '_ {
self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
}

View File

@ -52,10 +52,10 @@
tt,
visibility::{RawVisibility, Visibility},
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId,
ExternBlockLoc, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ItemContainerId,
LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, MacroRulesLoc,
ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc,
TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseLoc,
ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern,
ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId,
MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc,
TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId, UseLoc,
};
static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
@ -146,8 +146,8 @@ fn namespaces(self) -> PerNs {
#[derive(Clone, Debug, Eq, PartialEq)]
enum ImportSource {
Use { id: ItemTreeId<item_tree::Use>, use_tree: Idx<ast::UseTree> },
ExternCrate(ItemTreeId<item_tree::ExternCrate>),
Use { use_tree: Idx<ast::UseTree>, id: UseId, is_prelude: bool },
ExternCrate { id: ExternCrateId },
}
#[derive(Debug, Eq, PartialEq)]
@ -157,52 +157,42 @@ struct Import {
visibility: RawVisibility,
kind: ImportKind,
source: ImportSource,
is_prelude: bool,
is_macro_use: bool,
}
impl Import {
fn from_use(
db: &dyn DefDatabase,
krate: CrateId,
tree: &ItemTree,
id: ItemTreeId<item_tree::Use>,
item_tree_id: ItemTreeId<item_tree::Use>,
id: UseId,
is_prelude: bool,
mut cb: impl FnMut(Self),
) {
let it = &tree[id.value];
let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
let it = &tree[item_tree_id.value];
let visibility = &tree[it.visibility];
let is_prelude = attrs.by_key("prelude_import").exists();
it.use_tree.expand(|idx, path, kind, alias| {
cb(Self {
path,
alias,
visibility: visibility.clone(),
kind,
is_prelude,
is_macro_use: false,
source: ImportSource::Use { id, use_tree: idx },
source: ImportSource::Use { use_tree: idx, id, is_prelude },
});
});
}
fn from_extern_crate(
db: &dyn DefDatabase,
krate: CrateId,
tree: &ItemTree,
id: ItemTreeId<item_tree::ExternCrate>,
item_tree_id: ItemTreeId<item_tree::ExternCrate>,
id: ExternCrateId,
) -> Self {
let it = &tree[id.value];
let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
let it = &tree[item_tree_id.value];
let visibility = &tree[it.visibility];
Self {
path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())),
alias: it.alias.clone(),
visibility: visibility.clone(),
kind: ImportKind::Plain,
is_prelude: false,
is_macro_use: attrs.by_key("macro_use").exists(),
source: ImportSource::ExternCrate(id),
source: ImportSource::ExternCrate { id },
}
}
}
@ -280,7 +270,7 @@ fn seed_with_top_level(&mut self) {
if dep.is_prelude() {
crate_data
.extern_prelude
.insert(name.clone(), CrateRootModuleId { krate: dep.crate_id });
.insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None));
}
}
@ -557,7 +547,7 @@ fn inject_prelude(&mut self) {
match per_ns.types {
Some((ModuleDefId::ModuleId(m), _)) => {
self.def_map.prelude = Some(m);
self.def_map.prelude = Some((m, None));
}
types => {
tracing::debug!(
@ -720,7 +710,13 @@ fn define_proc_macro(&mut self, name: Name, macro_: ProcMacroId) {
/// Exported macros are just all macros in the root module scope.
/// Note that it contains not only all `#[macro_export]` macros, but also all aliases
/// created by `use` in the root module, ignoring the visibility of `use`.
fn import_macros_from_extern_crate(&mut self, krate: CrateId, names: Option<Vec<Name>>) {
fn import_macros_from_extern_crate(
&mut self,
krate: CrateId,
names: Option<Vec<Name>>,
extern_crate: Option<ExternCrateId>,
) {
let def_map = self.db.crate_def_map(krate);
// `#[macro_use]` brings macros into macro_use prelude. Yes, even non-`macro_rules!`
// macros.
@ -729,12 +725,12 @@ fn import_macros_from_extern_crate(&mut self, krate: CrateId, names: Option<Vec<
for name in names {
// FIXME: Report diagnostic on 404.
if let Some(def) = root_scope.get(&name).take_macros() {
self.def_map.macro_use_prelude.insert(name, def);
self.def_map.macro_use_prelude.insert(name, (def, extern_crate));
}
}
} else {
for (name, def) in root_scope.macros() {
self.def_map.macro_use_prelude.insert(name.clone(), def);
self.def_map.macro_use_prelude.insert(name.clone(), (def, extern_crate));
}
}
}
@ -771,48 +767,52 @@ fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialRe
let _p = profile::span("resolve_import")
.detail(|| format!("{}", import.path.display(self.db.upcast())));
tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition);
if matches!(import.source, ImportSource::ExternCrate { .. }) {
let name = import
.path
.as_ident()
.expect("extern crate should have been desugared to one-element path");
match import.source {
ImportSource::ExternCrate { .. } => {
let name = import
.path
.as_ident()
.expect("extern crate should have been desugared to one-element path");
let res = self.resolve_extern_crate(name);
let res = self.resolve_extern_crate(name);
match res {
Some(res) => {
PartialResolvedImport::Resolved(PerNs::types(res.into(), Visibility::Public))
}
None => PartialResolvedImport::Unresolved,
}
} else {
let res = self.def_map.resolve_path_fp_with_macro(
self.db,
ResolveMode::Import,
module_id,
&import.path,
BuiltinShadowMode::Module,
None, // An import may resolve to any kind of macro.
);
let def = res.resolved_def;
if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
return PartialResolvedImport::Unresolved;
}
if let Some(krate) = res.krate {
if krate != self.def_map.krate {
return PartialResolvedImport::Resolved(
def.filter_visibility(|v| matches!(v, Visibility::Public)),
);
match res {
Some(res) => PartialResolvedImport::Resolved(PerNs::types(
res.into(),
Visibility::Public,
)),
None => PartialResolvedImport::Unresolved,
}
}
ImportSource::Use { .. } => {
let res = self.def_map.resolve_path_fp_with_macro(
self.db,
ResolveMode::Import,
module_id,
&import.path,
BuiltinShadowMode::Module,
None, // An import may resolve to any kind of macro.
);
// Check whether all namespaces are resolved.
if def.is_full() {
PartialResolvedImport::Resolved(def)
} else {
PartialResolvedImport::Indeterminate(def)
let def = res.resolved_def;
if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
return PartialResolvedImport::Unresolved;
}
if let Some(krate) = res.krate {
if krate != self.def_map.krate {
return PartialResolvedImport::Resolved(
def.filter_visibility(|v| matches!(v, Visibility::Public)),
);
}
}
// Check whether all namespaces are resolved.
if def.is_full() {
PartialResolvedImport::Resolved(def)
} else {
PartialResolvedImport::Indeterminate(def)
}
}
}
}
@ -859,17 +859,17 @@ fn record_resolved_import(&mut self, directive: &ImportDirective) {
tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
// extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
if matches!(import.source, ImportSource::ExternCrate { .. })
&& self.def_map.block.is_none()
&& module_id == DefMap::ROOT
{
if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name)
{
if let Ok(def) = def.try_into() {
Arc::get_mut(&mut self.def_map.data)
.unwrap()
.extern_prelude
.insert(name.clone(), def);
if let ImportSource::ExternCrate { id, .. } = import.source {
if self.def_map.block.is_none() && module_id == DefMap::ROOT {
if let (Some(ModuleDefId::ModuleId(def)), Some(name)) =
(def.take_types(), name)
{
if let Ok(def) = def.try_into() {
Arc::get_mut(&mut self.def_map.data)
.unwrap()
.extern_prelude
.insert(name.clone(), (def, Some(id)));
}
}
}
}
@ -880,11 +880,11 @@ fn record_resolved_import(&mut self, directive: &ImportDirective) {
tracing::debug!("glob import: {:?}", import);
match def.take_types() {
Some(ModuleDefId::ModuleId(m)) => {
if import.is_prelude {
if let ImportSource::Use { id, is_prelude: true, .. } = import.source {
// Note: This dodgily overrides the injected prelude. The rustc
// implementation seems to work the same though.
cov_mark::hit!(std_prelude);
self.def_map.prelude = Some(m);
self.def_map.prelude = Some((m, Some(id)));
} else if m.krate != self.def_map.krate {
cov_mark::hit!(glob_across_crates);
// glob import from other crate => we can just import everything once
@ -1460,31 +1460,32 @@ fn finish(mut self) -> DefMap {
// heuristic, but it works in practice.
let mut diagnosed_extern_crates = FxHashSet::default();
for directive in &self.unresolved_imports {
if let ImportSource::ExternCrate(krate) = directive.import.source {
let item_tree = krate.item_tree(self.db);
let extern_crate = &item_tree[krate.value];
if let ImportSource::ExternCrate { id } = directive.import.source {
let item_tree_id = self.db.lookup_intern_extern_crate(id).id;
let item_tree = item_tree_id.item_tree(self.db);
let extern_crate = &item_tree[item_tree_id.value];
diagnosed_extern_crates.insert(extern_crate.name.clone());
self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
directive.module_id,
InFile::new(krate.file_id(), extern_crate.ast_id),
InFile::new(item_tree_id.file_id(), extern_crate.ast_id),
));
}
}
for directive in &self.unresolved_imports {
if let ImportSource::Use { id: import, use_tree } = directive.import.source {
if let ImportSource::Use { use_tree, id, is_prelude: _ } = directive.import.source {
if matches!(
(directive.import.path.segments().first(), &directive.import.path.kind),
(Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate)
) {
continue;
}
let item_tree_id = self.db.lookup_intern_use(id).id;
self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
directive.module_id,
import,
item_tree_id,
use_tree,
));
}
@ -1519,72 +1520,66 @@ fn collect(&mut self, items: &[ModItem], container: ItemContainerId) {
self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
// Prelude module is always considered to be `#[macro_use]`.
if let Some(prelude_module) = self.def_collector.def_map.prelude {
if let Some((prelude_module, _use)) = self.def_collector.def_map.prelude {
if prelude_module.krate != krate && is_crate_root {
cov_mark::hit!(prelude_is_macro_use);
self.def_collector.import_macros_from_extern_crate(prelude_module.krate, None);
self.def_collector.import_macros_from_extern_crate(
prelude_module.krate,
None,
None,
);
}
}
let db = self.def_collector.db;
let module_id = self.module_id;
let update_def =
|def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| {
def_collector.def_map.modules[module_id].scope.declare(id);
def_collector.update(
module_id,
&[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
vis,
ImportType::Named,
)
};
let resolve_vis = |def_map: &DefMap, visibility| {
def_map
.resolve_visibility(db, module_id, visibility, false)
.unwrap_or(Visibility::Public)
};
// This should be processed eagerly instead of deferred to resolving.
// `#[macro_use] extern crate` is hoisted to imports macros before collecting
// any other items.
//
// If we're not at the crate root, `macro_use`d extern crates are an error so let's just
// ignore them.
if is_crate_root {
for &item in items {
if let ModItem::ExternCrate(id) = item {
self.process_macro_use_extern_crate(id);
}
}
}
for &item in items {
let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
let mut process_mod_item = |item: ModItem| {
let attrs = self.item_tree.attrs(db, krate, item.into());
if let Some(cfg) = attrs.cfg() {
if !self.is_cfg_enabled(&cfg) {
self.emit_unconfigured_diagnostic(item, &cfg);
continue;
return;
}
}
if let Err(()) = self.resolve_attributes(&attrs, item, container) {
// Do not process the item. It has at least one non-builtin attribute, so the
// fixed-point algorithm is required to resolve the rest of them.
continue;
return;
}
let db = self.def_collector.db;
let module = self.def_collector.def_map.module_id(self.module_id);
let module = self.def_collector.def_map.module_id(module_id);
let def_map = &mut self.def_collector.def_map;
let update_def =
|def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| {
def_collector.def_map.modules[self.module_id].scope.declare(id);
def_collector.update(
self.module_id,
&[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
vis,
ImportType::Named,
)
};
let resolve_vis = |def_map: &DefMap, visibility| {
def_map
.resolve_visibility(db, self.module_id, visibility, false)
.unwrap_or(Visibility::Public)
};
match item {
ModItem::Mod(m) => self.collect_module(m, &attrs),
ModItem::Use(import_id) => {
let _import_id =
UseLoc { container: module, id: ItemTreeId::new(self.tree_id, import_id) }
.intern(db);
ModItem::Use(item_tree_id) => {
let id = UseLoc {
container: module,
id: ItemTreeId::new(self.tree_id, item_tree_id),
}
.intern(db);
let is_prelude = attrs.by_key("prelude_import").exists();
Import::from_use(
db,
krate,
self.item_tree,
ItemTreeId::new(self.tree_id, import_id),
ItemTreeId::new(self.tree_id, item_tree_id),
id,
is_prelude,
|import| {
self.def_collector.unresolved_imports.push(ImportDirective {
module_id: self.module_id,
@ -1594,22 +1589,29 @@ fn collect(&mut self, items: &[ModItem], container: ItemContainerId) {
},
)
}
ModItem::ExternCrate(import_id) => {
let extern_crate_id = ExternCrateLoc {
ModItem::ExternCrate(item_tree_id) => {
let id = ExternCrateLoc {
container: module,
id: ItemTreeId::new(self.tree_id, import_id),
id: ItemTreeId::new(self.tree_id, item_tree_id),
}
.intern(db);
if is_crate_root {
self.process_macro_use_extern_crate(
item_tree_id,
id,
attrs.by_key("macro_use").attrs(),
);
}
self.def_collector.def_map.modules[self.module_id]
.scope
.define_extern_crate_decl(extern_crate_id);
.define_extern_crate_decl(id);
self.def_collector.unresolved_imports.push(ImportDirective {
module_id: self.module_id,
import: Import::from_extern_crate(
db,
krate,
self.item_tree,
ItemTreeId::new(self.tree_id, import_id),
ItemTreeId::new(self.tree_id, item_tree_id),
id,
),
status: PartialResolvedImport::Unresolved,
})
@ -1768,21 +1770,34 @@ fn collect(&mut self, items: &[ModItem], container: ItemContainerId) {
);
}
}
};
// extern crates should be processed eagerly instead of deferred to resolving.
// `#[macro_use] extern crate` is hoisted to imports macros before collecting
// any other items.
if is_crate_root {
items
.iter()
.filter(|it| matches!(it, ModItem::ExternCrate(..)))
.copied()
.for_each(&mut process_mod_item);
items
.iter()
.filter(|it| !matches!(it, ModItem::ExternCrate(..)))
.copied()
.for_each(process_mod_item);
} else {
items.iter().copied().for_each(process_mod_item);
}
}
fn process_macro_use_extern_crate(&mut self, extern_crate: FileItemTreeId<ExternCrate>) {
fn process_macro_use_extern_crate<'a>(
&mut self,
extern_crate: FileItemTreeId<ExternCrate>,
extern_crate_id: ExternCrateId,
macro_use_attrs: impl Iterator<Item = &'a Attr>,
) {
let db = self.def_collector.db;
let attrs = self.item_tree.attrs(
db,
self.def_collector.def_map.krate,
ModItem::from(extern_crate).into(),
);
if let Some(cfg) = attrs.cfg() {
if !self.is_cfg_enabled(&cfg) {
return;
}
}
let target_crate =
match self.def_collector.resolve_extern_crate(&self.item_tree[extern_crate].name) {
@ -1798,11 +1813,11 @@ fn process_macro_use_extern_crate(&mut self, extern_crate: FileItemTreeId<Extern
let mut single_imports = Vec::new();
let hygiene = Hygiene::new_unhygienic();
for attr in attrs.by_key("macro_use").attrs() {
for attr in macro_use_attrs {
let Some(paths) = attr.parse_path_comma_token_tree(db.upcast(), &hygiene) else {
// `#[macro_use]` (without any paths) found, forget collected names and just import
// all visible macros.
self.def_collector.import_macros_from_extern_crate(target_crate, None);
self.def_collector.import_macros_from_extern_crate(target_crate, None, Some(extern_crate_id));
return;
};
for path in paths {
@ -1812,7 +1827,11 @@ fn process_macro_use_extern_crate(&mut self, extern_crate: FileItemTreeId<Extern
}
}
self.def_collector.import_macros_from_extern_crate(target_crate, Some(single_imports));
self.def_collector.import_macros_from_extern_crate(
target_crate,
Some(single_imports),
Some(extern_crate_id),
);
}
fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
@ -2198,7 +2217,7 @@ fn collect_macro_call(&mut self, mac: &MacroCall, container: ItemContainerId) {
map[module].scope.get_legacy_macro(name)?.last().copied()
})
.or_else(|| def_map[self.module_id].scope.get(name).take_macros())
.or_else(|| def_map.macro_use_prelude.get(name).copied())
.or_else(|| Some(def_map.macro_use_prelude.get(name).copied()?.0))
.filter(|&id| {
sub_namespace_match(
Some(MacroSubNs::from_id(db, id)),

View File

@ -299,7 +299,7 @@ pub(super) fn resolve_path_fp_with_macro_single(
Some((_, segment)) => segment,
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
};
if let Some(&def) = self.data.extern_prelude.get(segment) {
if let Some(&(def, _extern_crate)) = self.data.extern_prelude.get(segment) {
tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def);
PerNs::types(def.into(), Visibility::Public)
} else {
@ -452,15 +452,14 @@ fn resolve_name_in_module(
// Don't resolve extern prelude in block `DefMap`s.
return PerNs::none();
}
self.data
.extern_prelude
.get(name)
.map_or(PerNs::none(), |&it| PerNs::types(it.into(), Visibility::Public))
self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| {
PerNs::types(it.into(), Visibility::Public)
})
};
let macro_use_prelude = || {
self.macro_use_prelude
.get(name)
.map_or(PerNs::none(), |&it| PerNs::macros(it.into(), Visibility::Public))
self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| {
PerNs::macros(it.into(), Visibility::Public)
})
};
let prelude = || self.resolve_in_prelude(db, name);
@ -492,14 +491,16 @@ fn resolve_name_in_crate_root_or_extern_prelude(
.extern_prelude
.get(name)
.copied()
.map_or(PerNs::none(), |it| PerNs::types(it.into(), Visibility::Public))
.map_or(PerNs::none(), |(it, _extern_crate)| {
PerNs::types(it.into(), Visibility::Public)
})
};
from_crate_root.or_else(from_extern_prelude)
}
fn resolve_in_prelude(&self, db: &dyn DefDatabase, name: &Name) -> PerNs {
if let Some(prelude) = self.prelude {
if let Some((prelude, _use)) = self.prelude {
let keep;
let def_map = if prelude.krate == self.krate {
self

View File

@ -433,16 +433,16 @@ pub fn names_in_scope(
res.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac)));
})
});
def_map.macro_use_prelude().for_each(|(name, def)| {
def_map.macro_use_prelude().for_each(|(name, (def, _extern_crate))| {
res.add(name, ScopeDef::ModuleDef(def.into()));
});
def_map.extern_prelude().for_each(|(name, def)| {
res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def)));
def_map.extern_prelude().for_each(|(name, (def, _extern_crate))| {
res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def.into())));
});
BUILTIN_SCOPE.iter().for_each(|(name, &def)| {
res.add_per_ns(name, def);
});
if let Some(prelude) = def_map.prelude() {
if let Some((prelude, _use)) = def_map.prelude() {
let prelude_def_map = prelude.def_map(db);
for (name, def) in prelude_def_map[prelude.local_id].scope.entries() {
res.add_per_ns(name, def)
@ -473,7 +473,7 @@ pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet<TraitId> {
}
// Fill in the prelude traits
if let Some(prelude) = self.module_scope.def_map.prelude() {
if let Some((prelude, _use)) = self.module_scope.def_map.prelude() {
let prelude_def_map = prelude.def_map(db);
traits.extend(prelude_def_map[prelude.local_id].scope.traits());
}