diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index 91db68058b..68defa3858 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -487,7 +487,7 @@ impl ExternCrateDeclData { 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 { diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index df2af4c89b..59c250d750 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -11,7 +11,7 @@ use crate::{ 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, - 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 { - 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, - crate_root: ModuleId, + crate_root: CrateRootModuleId, max_len: usize, item: ItemInNs, from: ModuleId, diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 1901db8a0f..c40bbc0380 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -109,6 +109,17 @@ impl CrateRootModuleId { } } +impl PartialEq for CrateRootModuleId { + fn eq(&self, other: &ModuleId) -> bool { + other.block.is_none() && other.local_id == DefMap::ROOT && self.krate == other.krate + } +} +impl PartialEq for ModuleId { + fn eq(&self, other: &CrateRootModuleId) -> bool { + other == self + } +} + impl From for ModuleId { fn from(CrateRootModuleId { krate }: CrateRootModuleId) -> Self { ModuleId { krate, block: None, local_id: DefMap::ROOT } diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 86818ce26d..5c99f691a6 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -77,8 +77,8 @@ use crate::{ 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, + prelude: Option<(ModuleId, Option)>, /// `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, + macro_use_prelude: FxHashMap)>, /// 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, + extern_prelude: FxHashMap)>, /// Side table for resolving derive helpers. exported_derives: FxHashMap>, @@ -427,15 +427,19 @@ impl DefMap { self.block.map(|block| block.block) } - pub(crate) fn prelude(&self) -> Option { + pub(crate) fn prelude(&self) -> Option<(ModuleId, Option)> { self.prelude } - pub(crate) fn extern_prelude(&self) -> impl Iterator + '_ { - self.data.extern_prelude.iter().map(|(name, &def)| (name, def.into())) + pub(crate) fn extern_prelude( + &self, + ) -> impl Iterator))> + '_ { + self.data.extern_prelude.iter().map(|(name, &def)| (name, def)) } - pub(crate) fn macro_use_prelude(&self) -> impl Iterator + '_ { + pub(crate) fn macro_use_prelude( + &self, + ) -> impl Iterator))> + '_ { self.macro_use_prelude.iter().map(|(name, &def)| (name, def)) } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index eef54fc492..f79f4ab0ba 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -52,10 +52,10 @@ use crate::{ 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); @@ -144,10 +144,11 @@ impl PartialResolvedImport { } } +// FIXME: `item_tree_id` can be derived from `id`, look into deduplicating this #[derive(Clone, Debug, Eq, PartialEq)] enum ImportSource { - Use { id: ItemTreeId, use_tree: Idx }, - ExternCrate(ItemTreeId), + Use { item_tree_id: ItemTreeId, use_tree: Idx, id: UseId }, + ExternCrate { item_tree_id: ItemTreeId, id: ExternCrateId }, } #[derive(Debug, Eq, PartialEq)] @@ -166,11 +167,12 @@ impl Import { db: &dyn DefDatabase, krate: CrateId, tree: &ItemTree, - id: ItemTreeId, + item_tree_id: ItemTreeId, + id: UseId, 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 attrs = &tree.attrs(db, krate, ModItem::from(item_tree_id.value).into()); let visibility = &tree[it.visibility]; let is_prelude = attrs.by_key("prelude_import").exists(); it.use_tree.expand(|idx, path, kind, alias| { @@ -181,7 +183,7 @@ impl Import { kind, is_prelude, is_macro_use: false, - source: ImportSource::Use { id, use_tree: idx }, + source: ImportSource::Use { item_tree_id, use_tree: idx, id }, }); }); } @@ -190,10 +192,11 @@ impl Import { db: &dyn DefDatabase, krate: CrateId, tree: &ItemTree, - id: ItemTreeId, + item_tree_id: ItemTreeId, + 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 attrs = &tree.attrs(db, krate, ModItem::from(item_tree_id.value).into()); let visibility = &tree[it.visibility]; Self { path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), @@ -202,7 +205,7 @@ impl Import { kind: ImportKind::Plain, is_prelude: false, is_macro_use: attrs.by_key("macro_use").exists(), - source: ImportSource::ExternCrate(id), + source: ImportSource::ExternCrate { item_tree_id, id }, } } } @@ -280,7 +283,7 @@ impl DefCollector<'_> { 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 +560,7 @@ impl DefCollector<'_> { 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 +723,13 @@ impl DefCollector<'_> { /// 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>) { + fn import_macros_from_extern_crate( + &mut self, + krate: CrateId, + names: Option>, + + extern_crate: Option, + ) { 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 +738,12 @@ impl DefCollector<'_> { 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 +780,52 @@ impl DefCollector<'_> { 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 +872,17 @@ impl DefCollector<'_> { 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))); + } } } } @@ -884,7 +897,13 @@ impl DefCollector<'_> { // 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, + match import.source { + ImportSource::Use { id, .. } => Some(id), + ImportSource::ExternCrate { .. } => None, + }, + )); } 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,21 +1479,21 @@ impl DefCollector<'_> { // 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 { item_tree_id, id: _ } = directive.import.source { + 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 { item_tree_id, use_tree, id: _ } = 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) @@ -1484,7 +1503,7 @@ impl DefCollector<'_> { self.def_map.diagnostics.push(DefDiagnostic::unresolved_import( directive.module_id, - import, + item_tree_id, use_tree, )); } @@ -1519,72 +1538,66 @@ impl ModCollector<'_, '_> { 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); Import::from_use( db, krate, self.item_tree, - ItemTreeId::new(self.tree_id, import_id), + ItemTreeId::new(self.tree_id, item_tree_id), + id, |import| { self.def_collector.unresolved_imports.push(ImportDirective { module_id: self.module_id, @@ -1594,22 +1607,27 @@ impl ModCollector<'_, '_> { }, ) } - 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); + } + 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,10 +1786,32 @@ impl ModCollector<'_, '_> { ); } } + }; + + // 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) { + fn process_macro_use_extern_crate( + &mut self, + extern_crate: FileItemTreeId, + extern_crate_id: ExternCrateId, + ) { let db = self.def_collector.db; let attrs = self.item_tree.attrs( db, @@ -1802,7 +1842,7 @@ impl ModCollector<'_, '_> { 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 +1852,11 @@ impl ModCollector<'_, '_> { } } - 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, attrs: &Attrs) { @@ -2198,7 +2242,7 @@ impl ModCollector<'_, '_> { 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)), diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index de22ea1014..64cdbdce77 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -299,7 +299,7 @@ impl DefMap { 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 @@ impl DefMap { // 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 @@ impl DefMap { .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 diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index d04d2fa0e9..17a1bf50b5 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -433,16 +433,16 @@ impl Resolver { 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 @@ impl Resolver { } // 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()); }