From af8048266cd87e7855cb150803260887aa93d01a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 16 Aug 2023 11:18:11 +0200 Subject: [PATCH 1/3] Prepare ItemScope for IDE import resolution --- crates/hir-def/src/find_path.rs | 18 +++ crates/hir-def/src/import_map.rs | 17 ++- crates/hir-def/src/item_scope.rs | 130 +++++++++++++----- crates/hir-def/src/lib.rs | 21 +++ crates/hir-def/src/nameres.rs | 1 + crates/hir-def/src/nameres/collector.rs | 7 +- crates/hir-def/src/nameres/path_resolution.rs | 2 +- .../hir-def/src/nameres/tests/incremental.rs | 2 +- crates/hir-def/src/per_ns.rs | 34 +++-- crates/hir-def/src/resolver.rs | 6 +- crates/ide-db/src/lib.rs | 3 + 11 files changed, 174 insertions(+), 67 deletions(-) diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index 59c250d7506..234d3eaed56 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -1293,4 +1293,22 @@ pub mod prelude { "None", ); } + + #[test] + fn different_crate_renamed_through_dep() { + check_found_path( + r#" +//- /main.rs crate:main deps:intermediate +$0 +//- /intermediate.rs crate:intermediate deps:std +pub extern crate std as std_renamed; +//- /std.rs crate:std +pub struct S; + "#, + "intermediate::std_renamed::S", + "intermediate::std_renamed::S", + "intermediate::std_renamed::S", + "intermediate::std_renamed::S", + ); + } } diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index d742b2eef0a..5d7bb0b49d7 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -114,6 +114,9 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap FxIndexMap { - entry.insert(depth); - } + Entry::Vacant(entry) => _ = entry.insert((depth, is_doc_hidden)), Entry::Occupied(mut entry) => { - if depth < *entry.get() { - entry.insert(depth); - } else { + let &(occ_depth, occ_is_doc_hidden) = entry.get(); + // Prefer the one that is not doc(hidden), + // Otherwise, if both have the same doc(hidden)-ness and the new path is shorter, prefer that one. + let overwrite_entry = occ_is_doc_hidden && !is_doc_hidden + || occ_is_doc_hidden == is_doc_hidden && depth < occ_depth; + if !overwrite_entry { continue; } + entry.insert((depth, is_doc_hidden)); } } diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 873accafb43..03fc5c3abde 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -6,6 +6,7 @@ use std::collections::hash_map::Entry; use base_db::CrateId; use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId}; use itertools::Itertools; +use la_arena::Idx; use once_cell::sync::Lazy; use profile::Count; use rustc_hash::{FxHashMap, FxHashSet}; @@ -32,15 +33,50 @@ pub struct PerNsGlobImports { macros: FxHashSet<(LocalModuleId, Name)>, } +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum ImportOrExternCrate { + Import(ImportId), + Glob(UseId), + ExternCrate(ExternCrateId), +} + +impl ImportOrExternCrate { + pub fn into_import(self) -> Option { + match self { + ImportOrExternCrate::Import(it) => Some(it), + _ => None, + } + } + + pub fn into_glob(self) -> Option { + match self { + ImportOrExternCrate::Glob(it) => Some(it), + _ => None, + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum ImportOrDef { + Import(ImportId), + ExternCrate(ExternCrateId), + Def(ModuleDefId), +} +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct ImportId { + pub import: UseId, + pub idx: Idx, +} + #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { _c: Count, /// Defs visible in this scope. This includes `declarations`, but also /// imports. - types: FxHashMap, - values: FxHashMap, - macros: FxHashMap, + types: FxHashMap)>, + values: FxHashMap)>, + macros: FxHashMap)>, unresolved: FxHashSet, /// The defs declared in this scope. Each def has a single scope where it is @@ -50,7 +86,14 @@ pub struct ItemScope { impls: Vec, unnamed_consts: Vec, /// Traits imported via `use Trait as _;`. - unnamed_trait_imports: FxHashMap, + unnamed_trait_imports: FxHashMap)>, + + // the resolutions of the imports of this scope + use_imports_types: FxHashMap, + use_imports_values: FxHashMap, + use_imports_macros: FxHashMap, + + use_decls: Vec, extern_crate_decls: Vec, /// Macros visible in current module in legacy textual scope /// @@ -121,8 +164,7 @@ impl ItemScope { } pub fn use_decls(&self) -> impl Iterator + ExactSizeIterator + '_ { - // FIXME: to be implemented - std::iter::empty() + self.use_decls.iter().copied() } pub fn impls(&self) -> impl Iterator + ExactSizeIterator + '_ { @@ -132,13 +174,13 @@ impl ItemScope { pub fn values( &self, ) -> impl Iterator + ExactSizeIterator + '_ { - self.values.values().copied() + self.values.values().copied().map(|(a, b, _)| (a, b)) } - pub fn types( + pub(crate) fn types( &self, ) -> impl Iterator + ExactSizeIterator + '_ { - self.types.values().copied() + self.types.values().copied().map(|(def, vis, _)| (def, vis)) } pub fn unnamed_consts(&self) -> impl Iterator + '_ { @@ -165,33 +207,48 @@ impl ItemScope { } pub(crate) fn type_(&self, name: &Name) -> Option<(ModuleDefId, Visibility)> { - self.types.get(name).copied() + self.types.get(name).copied().map(|(a, b, _)| (a, b)) } /// XXX: this is O(N) rather than O(1), try to not introduce new usages. pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> { - let (def, mut iter) = match item { - ItemInNs::Macros(def) => { - return self.macros.iter().find_map(|(name, &(other_def, vis))| { - (other_def == def).then_some((name, vis)) - }); - } - ItemInNs::Types(def) => (def, self.types.iter()), - ItemInNs::Values(def) => (def, self.values.iter()), - }; - iter.find_map(|(name, &(other_def, vis))| (other_def == def).then_some((name, vis))) + match item { + ItemInNs::Macros(def) => self + .macros + .iter() + .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), + ItemInNs::Types(def) => self + .types + .iter() + .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), + + ItemInNs::Values(def) => self + .values + .iter() + .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))), + } } pub(crate) fn traits(&self) -> impl Iterator + '_ { self.types .values() - .filter_map(|&(def, _)| match def { + .filter_map(|&(def, _, _)| match def { ModuleDefId::TraitId(t) => Some(t), _ => None, }) .chain(self.unnamed_trait_imports.keys().copied()) } + pub(crate) fn resolutions(&self) -> impl Iterator, PerNs)> + '_ { + self.entries().map(|(name, res)| (Some(name.clone()), res)).chain( + self.unnamed_trait_imports + .iter() + .map(|(tr, (vis, _))| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))), + ) + } +} + +impl ItemScope { pub(crate) fn declare(&mut self, def: ModuleDefId) { self.declarations.push(def) } @@ -278,11 +335,11 @@ impl ItemScope { } pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option { - self.unnamed_trait_imports.get(&tr).copied() + self.unnamed_trait_imports.get(&tr).copied().map(|(a, _)| a) } pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) { - self.unnamed_trait_imports.insert(tr, vis); + self.unnamed_trait_imports.insert(tr, (vis, None)); } pub(crate) fn push_res_with_import( @@ -343,27 +400,18 @@ impl ItemScope { changed } - pub(crate) fn resolutions(&self) -> impl Iterator, PerNs)> + '_ { - self.entries().map(|(name, res)| (Some(name.clone()), res)).chain( - self.unnamed_trait_imports - .iter() - .map(|(tr, vis)| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))), - ) - } - /// Marks everything that is not a procedural macro as private to `this_module`. pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) { self.types .values_mut() - .chain(self.values.values_mut()) + .map(|(def, vis, _)| (def, vis)) + .chain(self.values.values_mut().map(|(def, vis, _)| (def, vis))) .map(|(_, v)| v) - .chain(self.unnamed_trait_imports.values_mut()) + .chain(self.unnamed_trait_imports.values_mut().map(|(vis, _)| vis)) .for_each(|vis| *vis = Visibility::Module(this_module)); - for (mac, vis) in self.macros.values_mut() { - if let MacroId::ProcMacroId(_) = mac { - // FIXME: Technically this is insufficient since reexports of proc macros are also - // forbidden. Practically nobody does that. + for (mac, vis, import) in self.macros.values_mut() { + if matches!(mac, MacroId::ProcMacroId(_) if import.is_none()) { continue; } @@ -415,10 +463,17 @@ impl ItemScope { attr_macros, derive_macros, extern_crate_decls, + use_decls, + use_imports_values, + use_imports_types, + use_imports_macros, } = self; types.shrink_to_fit(); values.shrink_to_fit(); macros.shrink_to_fit(); + use_imports_types.shrink_to_fit(); + use_imports_values.shrink_to_fit(); + use_imports_macros.shrink_to_fit(); unresolved.shrink_to_fit(); declarations.shrink_to_fit(); impls.shrink_to_fit(); @@ -428,6 +483,7 @@ impl ItemScope { attr_macros.shrink_to_fit(); derive_macros.shrink_to_fit(); extern_crate_decls.shrink_to_fit(); + use_decls.shrink_to_fit(); } } diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index c40bbc0380e..3c0ed8c2e51 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -865,6 +865,7 @@ impl_from!( ConstId, FunctionId, TraitId, + TraitAliasId, TypeAliasId, MacroId(Macro2Id, MacroRulesId, ProcMacroId), ImplId, @@ -873,6 +874,26 @@ impl_from!( for AttrDefId ); +impl TryFrom for AttrDefId { + type Error = (); + + fn try_from(value: ModuleDefId) -> Result { + match value { + ModuleDefId::ModuleId(it) => Ok(it.into()), + ModuleDefId::FunctionId(it) => Ok(it.into()), + ModuleDefId::AdtId(it) => Ok(it.into()), + ModuleDefId::EnumVariantId(it) => Ok(it.into()), + ModuleDefId::ConstId(it) => Ok(it.into()), + ModuleDefId::StaticId(it) => Ok(it.into()), + ModuleDefId::TraitId(it) => Ok(it.into()), + ModuleDefId::TypeAliasId(it) => Ok(it.into()), + ModuleDefId::TraitAliasId(id) => Ok(id.into()), + ModuleDefId::MacroId(id) => Ok(id.into()), + ModuleDefId::BuiltinType(_) => Err(()), + } + } +} + impl From for AttrDefId { fn from(acid: ItemContainerId) -> Self { match acid { diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index f93125e224d..f2110410980 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -108,6 +108,7 @@ pub struct DefMap { 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. + /// ExternCrateId being None implies it being imported from the general prelude import. macro_use_prelude: FxHashMap)>, /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index e3253404d49..b6658e4552c 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -33,7 +33,7 @@ use crate::{ attr_macro_as_call_id, db::DefDatabase, derive_macro_as_call_id, - item_scope::{ImportType, PerNsGlobImports}, + item_scope::{ImportOrExternCrate, ImportType, PerNsGlobImports}, item_tree::{ self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId, @@ -546,8 +546,8 @@ impl DefCollector<'_> { self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None); match per_ns.types { - Some((ModuleDefId::ModuleId(m), _)) => { - self.def_map.prelude = Some((m, None)); + Some((ModuleDefId::ModuleId(m), _, import)) => { + self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::into_glob))); } types => { tracing::debug!( @@ -714,7 +714,6 @@ impl DefCollector<'_> { &mut self, krate: CrateId, names: Option>, - extern_crate: Option, ) { let def_map = self.db.crate_def_map(krate); diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 64cdbdce770..fc296e1e588 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -65,7 +65,7 @@ impl PerNs { db: &dyn DefDatabase, expected: Option, ) -> Self { - self.macros = self.macros.filter(|&(id, _)| { + self.macros = self.macros.filter(|&(id, _, _)| { let this = MacroSubNs::from_id(db, id); sub_namespace_match(Some(this), expected) }); diff --git a/crates/hir-def/src/nameres/tests/incremental.rs b/crates/hir-def/src/nameres/tests/incremental.rs index 40d3a16540d..4a86f88e57a 100644 --- a/crates/hir-def/src/nameres/tests/incremental.rs +++ b/crates/hir-def/src/nameres/tests/incremental.rs @@ -212,7 +212,7 @@ pub type Ty = (); } for (_, res) in module_data.scope.resolutions() { - match res.values.or(res.types).unwrap().0 { + match res.values.map(|(a, _, _)| a).or(res.types.map(|(a, _, _)| a)).unwrap() { ModuleDefId::FunctionId(f) => _ = db.function_data(f), ModuleDefId::AdtId(adt) => match adt { AdtId::StructId(it) => _ = db.struct_data(it), diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs index 2bc1f8e926e..f32a97d1a3a 100644 --- a/crates/hir-def/src/per_ns.rs +++ b/crates/hir-def/src/per_ns.rs @@ -3,13 +3,17 @@ //! //! `PerNs` (per namespace) captures this. -use crate::{item_scope::ItemInNs, visibility::Visibility, MacroId, ModuleDefId}; +use crate::{ + item_scope::{ImportId, ImportOrExternCrate, ItemInNs}, + visibility::Visibility, + MacroId, ModuleDefId, +}; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct PerNs { - pub types: Option<(ModuleDefId, Visibility)>, - pub values: Option<(ModuleDefId, Visibility)>, - pub macros: Option<(MacroId, Visibility)>, + pub types: Option<(ModuleDefId, Visibility, Option)>, + pub values: Option<(ModuleDefId, Visibility, Option)>, + pub macros: Option<(MacroId, Visibility, Option)>, } impl Default for PerNs { @@ -24,19 +28,19 @@ impl PerNs { } pub fn values(t: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: None, values: Some((t, v)), macros: None } + PerNs { types: None, values: Some((t, v, None)), macros: None } } pub fn types(t: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: Some((t, v)), values: None, macros: None } + PerNs { types: Some((t, v, None)), values: None, macros: None } } pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: Some((types, v)), values: Some((values, v)), macros: None } + PerNs { types: Some((types, v, None)), values: Some((values, v, None)), macros: None } } pub fn macros(macro_: MacroId, v: Visibility) -> PerNs { - PerNs { types: None, values: None, macros: Some((macro_, v)) } + PerNs { types: None, values: None, macros: Some((macro_, v, None)) } } pub fn is_none(&self) -> bool { @@ -52,7 +56,7 @@ impl PerNs { } pub fn take_types_vis(self) -> Option<(ModuleDefId, Visibility)> { - self.types + self.types.map(|(a, b, _)| (a, b)) } pub fn take_values(self) -> Option { @@ -66,17 +70,17 @@ impl PerNs { pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { let _p = profile::span("PerNs::filter_visibility"); PerNs { - types: self.types.filter(|(_, v)| f(*v)), - values: self.values.filter(|(_, v)| f(*v)), - macros: self.macros.filter(|(_, v)| f(*v)), + types: self.types.filter(|&(_, v, _)| f(v)), + values: self.values.filter(|&(_, v, _)| f(v)), + macros: self.macros.filter(|&(_, v, _)| f(v)), } } pub fn with_visibility(self, vis: Visibility) -> PerNs { PerNs { - types: self.types.map(|(it, _)| (it, vis)), - values: self.values.map(|(it, _)| (it, vis)), - macros: self.macros.map(|(it, _)| (it, vis)), + types: self.types.map(|(it, _, c)| (it, vis, c)), + values: self.values.map(|(it, _, c)| (it, vis, c)), + macros: self.macros.map(|(it, _, import)| (it, vis, import)), } } diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 17a1bf50b5e..28ab0f8f6ee 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -864,13 +864,13 @@ impl ScopeNames { } } fn add_per_ns(&mut self, name: &Name, def: PerNs) { - if let &Some((ty, _)) = &def.types { + if let &Some((ty, _, _)) = &def.types { self.add(name, ScopeDef::ModuleDef(ty)) } - if let &Some((def, _)) = &def.values { + if let &Some((def, _, _)) = &def.values { self.add(name, ScopeDef::ModuleDef(def)) } - if let &Some((mac, _)) = &def.macros { + if let &Some((mac, _, _)) = &def.macros { self.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac))) } if def.is_none() { diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs index f27ed485d81..ac3511ba47b 100644 --- a/crates/ide-db/src/lib.rs +++ b/crates/ide-db/src/lib.rs @@ -94,18 +94,21 @@ impl fmt::Debug for RootDatabase { } impl Upcast for RootDatabase { + #[inline] fn upcast(&self) -> &(dyn ExpandDatabase + 'static) { &*self } } impl Upcast for RootDatabase { + #[inline] fn upcast(&self) -> &(dyn DefDatabase + 'static) { &*self } } impl Upcast for RootDatabase { + #[inline] fn upcast(&self) -> &(dyn HirDatabase + 'static) { &*self } From c4e9b5ac649c62a46110660b612776468ba0d07f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 17 Aug 2023 09:33:15 +0200 Subject: [PATCH 2/3] Add import info to item scope dumps --- crates/hir-def/src/body/tests/block.rs | 20 +- crates/hir-def/src/item_scope.rs | 248 ++++++++++++++---- crates/hir-def/src/nameres/collector.rs | 125 +++++---- crates/hir-def/src/nameres/tests.rs | 80 +++--- crates/hir-def/src/nameres/tests/globs.rs | 18 +- crates/hir-def/src/nameres/tests/macros.rs | 52 ++-- .../src/nameres/tests/mod_resolution.rs | 32 +-- .../hir-def/src/nameres/tests/primitives.rs | 4 +- 8 files changed, 364 insertions(+), 215 deletions(-) diff --git a/crates/hir-def/src/body/tests/block.rs b/crates/hir-def/src/body/tests/block.rs index 4e015a7fbbb..44eeed9e3fb 100644 --- a/crates/hir-def/src/body/tests/block.rs +++ b/crates/hir-def/src/body/tests/block.rs @@ -38,9 +38,9 @@ fn outer() { "#, expect![[r#" block scope - CrateStruct: t - PlainStruct: t v - SelfStruct: t + CrateStruct: ti + PlainStruct: ti vi + SelfStruct: ti Struct: v SuperStruct: _ @@ -66,7 +66,7 @@ fn outer() { "#, expect![[r#" block scope - imported: t v + imported: ti vi name: v crate @@ -92,9 +92,9 @@ fn outer() { "#, expect![[r#" block scope - inner1: t + inner1: ti inner2: v - outer: v + outer: vi block scope inner: v @@ -121,7 +121,7 @@ struct Struct {} "#, expect![[r#" block scope - Struct: t + Struct: ti crate Struct: t @@ -153,7 +153,7 @@ fn outer() { "#, expect![[r#" block scope - ResolveMe: t + ResolveMe: ti block scope m2: t @@ -214,7 +214,7 @@ fn f() { "#, expect![[r#" block scope - ResolveMe: t + ResolveMe: ti block scope h: v @@ -292,7 +292,7 @@ pub mod cov_mark { nested: v crate - cov_mark: t + cov_mark: ti f: v "#]], ); diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 03fc5c3abde..59a1c5f49e2 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -20,12 +20,6 @@ use crate::{ UseId, }; -#[derive(Copy, Clone, Debug)] -pub(crate) enum ImportType { - Glob, - Named, -} - #[derive(Debug, Default)] pub struct PerNsGlobImports { types: FxHashSet<(LocalModuleId, Name)>, @@ -35,6 +29,12 @@ pub struct PerNsGlobImports { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum ImportOrExternCrate { + Import(ImportId), + ExternCrate(ExternCrateId), +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum ImportType { Import(ImportId), Glob(UseId), ExternCrate(ExternCrateId), @@ -47,13 +47,6 @@ impl ImportOrExternCrate { _ => None, } } - - pub fn into_glob(self) -> Option { - match self { - ImportOrExternCrate::Glob(it) => Some(it), - _ => None, - } - } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -89,9 +82,9 @@ pub struct ItemScope { unnamed_trait_imports: FxHashMap)>, // the resolutions of the imports of this scope - use_imports_types: FxHashMap, - use_imports_values: FxHashMap, - use_imports_macros: FxHashMap, + use_imports_types: FxHashMap, + use_imports_values: FxHashMap, + use_imports_macros: FxHashMap, use_decls: Vec, extern_crate_decls: Vec, @@ -347,51 +340,185 @@ impl ItemScope { glob_imports: &mut PerNsGlobImports, lookup: (LocalModuleId, Name), def: PerNs, - def_import_type: ImportType, + import: Option, ) -> bool { let mut changed = false; - macro_rules! check_changed { - ( - $changed:ident, - ( $this:ident / $def:ident ) . $field:ident, - $glob_imports:ident [ $lookup:ident ], - $def_import_type:ident - ) => {{ - if let Some(fld) = $def.$field { - let existing = $this.$field.entry($lookup.1.clone()); - match existing { - Entry::Vacant(entry) => { - match $def_import_type { - ImportType::Glob => { - $glob_imports.$field.insert($lookup.clone()); - } - ImportType::Named => { - $glob_imports.$field.remove(&$lookup); - } - } - - entry.insert(fld); - $changed = true; + if let Some(mut fld) = def.types { + let existing = self.types.entry(lookup.1.clone()); + match existing { + Entry::Vacant(entry) => { + match import { + Some(ImportType::Glob(_)) => { + glob_imports.types.insert(lookup.clone()); } - Entry::Occupied(mut entry) - if matches!($def_import_type, ImportType::Named) => - { - if $glob_imports.$field.remove(&$lookup) { - cov_mark::hit!(import_shadowed); - entry.insert(fld); - $changed = true; - } + _ => _ = glob_imports.types.remove(&lookup), + } + let import = match import { + Some(ImportType::ExternCrate(extern_crate)) => { + Some(ImportOrExternCrate::ExternCrate(extern_crate)) } - _ => {} + Some(ImportType::Import(import)) => { + Some(ImportOrExternCrate::Import(import)) + } + None | Some(ImportType::Glob(_)) => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(ImportOrExternCrate::Import(import)) = import { + self.use_imports_values.insert( + import, + match prev { + Some(ImportOrExternCrate::Import(import)) => { + ImportOrDef::Import(import) + } + Some(ImportOrExternCrate::ExternCrate(import)) => { + ImportOrDef::ExternCrate(import) + } + None => ImportOrDef::Def(fld.0), + }, + ); + } + entry.insert(fld); + changed = true; + } + Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => { + if glob_imports.types.remove(&lookup) { + let import = match import { + Some(ImportType::ExternCrate(extern_crate)) => { + Some(ImportOrExternCrate::ExternCrate(extern_crate)) + } + Some(ImportType::Import(import)) => { + Some(ImportOrExternCrate::Import(import)) + } + None | Some(ImportType::Glob(_)) => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(ImportOrExternCrate::Import(import)) = import { + self.use_imports_values.insert( + import, + match prev { + Some(ImportOrExternCrate::Import(import)) => { + ImportOrDef::Import(import) + } + Some(ImportOrExternCrate::ExternCrate(import)) => { + ImportOrDef::ExternCrate(import) + } + None => ImportOrDef::Def(fld.0), + }, + ); + } + cov_mark::hit!(import_shadowed); + entry.insert(fld); + changed = true; } } - }}; + _ => {} + } } - check_changed!(changed, (self / def).types, glob_imports[lookup], def_import_type); - check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type); - check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type); + if let Some(mut fld) = def.values { + let existing = self.values.entry(lookup.1.clone()); + match existing { + Entry::Vacant(entry) => { + match import { + Some(ImportType::Glob(_)) => { + glob_imports.values.insert(lookup.clone()); + } + _ => _ = glob_imports.values.remove(&lookup), + } + let import = match import { + Some(ImportType::Import(import)) => Some(import), + _ => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(import) = import { + self.use_imports_values.insert( + import, + match prev { + Some(import) => ImportOrDef::Import(import), + None => ImportOrDef::Def(fld.0), + }, + ); + } + entry.insert(fld); + changed = true; + } + Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => { + if glob_imports.values.remove(&lookup) { + cov_mark::hit!(import_shadowed); + let import = match import { + Some(ImportType::Import(import)) => Some(import), + _ => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(import) = import { + self.use_imports_values.insert( + import, + match prev { + Some(import) => ImportOrDef::Import(import), + None => ImportOrDef::Def(fld.0), + }, + ); + } + entry.insert(fld); + changed = true; + } + } + _ => {} + } + } + + if let Some(mut fld) = def.macros { + let existing = self.macros.entry(lookup.1.clone()); + match existing { + Entry::Vacant(entry) => { + match import { + Some(ImportType::Glob(_)) => { + glob_imports.macros.insert(lookup.clone()); + } + _ => _ = glob_imports.macros.remove(&lookup), + } + let import = match import { + Some(ImportType::Import(import)) => Some(import), + _ => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(import) = import { + self.use_imports_macros.insert( + import, + match prev { + Some(import) => ImportOrDef::Import(import), + None => ImportOrDef::Def(fld.0.into()), + }, + ); + } + entry.insert(fld); + changed = true; + } + Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => { + if glob_imports.macros.remove(&lookup) { + cov_mark::hit!(import_shadowed); + let import = match import { + Some(ImportType::Import(import)) => Some(import), + _ => None, + }; + let prev = std::mem::replace(&mut fld.2, import); + if let Some(import) = import { + self.use_imports_macros.insert( + import, + match prev { + Some(import) => ImportOrDef::Import(import), + None => ImportOrDef::Def(fld.0.into()), + }, + ); + } + entry.insert(fld); + changed = true; + } + } + _ => {} + } + } if def.is_none() && self.unresolved.insert(lookup.1) { changed = true; @@ -430,14 +557,25 @@ impl ItemScope { name.map_or("_".to_string(), |name| name.display(db).to_string()) ); - if def.types.is_some() { + if let Some((.., i)) = def.types { buf.push_str(" t"); + match i { + Some(ImportOrExternCrate::Import(_)) => buf.push('i'), + Some(ImportOrExternCrate::ExternCrate(_)) => buf.push('e'), + None => (), + } } - if def.values.is_some() { + if let Some((.., i)) = def.values { buf.push_str(" v"); + if i.is_some() { + buf.push('i'); + } } - if def.macros.is_some() { + if let Some((.., i)) = def.macros { buf.push_str(" m"); + if i.is_some() { + buf.push('i'); + } } if def.is_none() { buf.push_str(" _"); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index b6658e4552c..48eaec0f4e5 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -33,7 +33,7 @@ use crate::{ attr_macro_as_call_id, db::DefDatabase, derive_macro_as_call_id, - item_scope::{ImportOrExternCrate, ImportType, PerNsGlobImports}, + item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports}, item_tree::{ self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId, @@ -146,7 +146,7 @@ impl PartialResolvedImport { #[derive(Clone, Debug, Eq, PartialEq)] enum ImportSource { - Use { use_tree: Idx, id: UseId, is_prelude: bool }, + Use { use_tree: Idx, id: UseId, is_prelude: bool, kind: ImportKind }, ExternCrate { id: ExternCrateId }, } @@ -155,7 +155,6 @@ struct Import { path: ModPath, alias: Option, visibility: RawVisibility, - kind: ImportKind, source: ImportSource, } @@ -174,8 +173,7 @@ impl Import { path, alias, visibility: visibility.clone(), - kind, - source: ImportSource::Use { use_tree: idx, id, is_prelude }, + source: ImportSource::Use { use_tree: idx, id, is_prelude, kind }, }); }); } @@ -191,7 +189,6 @@ impl Import { path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), alias: it.alias.clone(), visibility: visibility.clone(), - kind: ImportKind::Plain, source: ImportSource::ExternCrate { id }, } } @@ -225,7 +222,7 @@ struct DefCollector<'a> { db: &'a dyn DefDatabase, def_map: DefMap, deps: FxHashMap, - glob_imports: FxHashMap>, + glob_imports: FxHashMap>, unresolved_imports: Vec, indeterminate_imports: Vec, unresolved_macros: Vec, @@ -547,7 +544,11 @@ impl DefCollector<'_> { match per_ns.types { Some((ModuleDefId::ModuleId(m), _, import)) => { - self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::into_glob))); + // FIXME: This should specifically look for a glob import somehow and record that here + self.def_map.prelude = Some(( + m, + import.and_then(ImportOrExternCrate::into_import).map(|it| it.import), + )); } types => { tracing::debug!( @@ -649,7 +650,7 @@ impl DefCollector<'_> { module_id, &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], Visibility::Public, - ImportType::Named, + None, ); } } @@ -685,7 +686,7 @@ impl DefCollector<'_> { module_id, &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], vis, - ImportType::Named, + None, ); } @@ -700,7 +701,7 @@ impl DefCollector<'_> { module_id, &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], Visibility::Public, - ImportType::Named, + None, ); } @@ -720,16 +721,19 @@ impl DefCollector<'_> { // `#[macro_use]` brings macros into macro_use prelude. Yes, even non-`macro_rules!` // macros. let root_scope = &def_map[DefMap::ROOT].scope; - if let Some(names) = names { - 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, extern_crate)); + match names { + Some(names) => { + 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, extern_crate)); + } } } - } else { - for (name, def) in root_scope.macros() { - self.def_map.macro_use_prelude.insert(name.clone(), (def, extern_crate)); + None => { + for (name, def) in root_scope.macros() { + self.def_map.macro_use_prelude.insert(name.clone(), (def, extern_crate)); + } } } } @@ -836,8 +840,9 @@ impl DefCollector<'_> { .resolve_visibility(self.db, module_id, &directive.import.visibility, false) .unwrap_or(Visibility::Public); - match import.kind { - ImportKind::Plain | ImportKind::TypeOnly => { + match import.source { + ImportSource::ExternCrate { .. } + | ImportSource::Use { kind: ImportKind::Plain | ImportKind::TypeOnly, .. } => { let name = match &import.alias { Some(ImportAlias::Alias(name)) => Some(name), Some(ImportAlias::Underscore) => None, @@ -850,32 +855,36 @@ impl DefCollector<'_> { }, }; - if import.kind == ImportKind::TypeOnly { - def.values = None; - def.macros = None; - } - - 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 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))); + let imp = match import.source { + // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 + ImportSource::ExternCrate { id, .. } => { + 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))); + } } } + ImportType::ExternCrate(id) } - } + ImportSource::Use { kind, id, use_tree, .. } => { + if kind == ImportKind::TypeOnly { + def.values = None; + def.macros = None; + } + ImportType::Import(ImportId { import: id, idx: use_tree }) + } + }; + tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); - self.update(module_id, &[(name.cloned(), def)], vis, ImportType::Named); + self.update(module_id, &[(name.cloned(), def)], vis, Some(imp)); } - ImportKind::Glob => { + ImportSource::Use { kind: ImportKind::Glob, id, .. } => { tracing::debug!("glob import: {:?}", import); match def.take_types() { Some(ModuleDefId::ModuleId(m)) => { @@ -900,7 +909,7 @@ impl DefCollector<'_> { .filter(|(_, res)| !res.is_none()) .collect::>(); - self.update(module_id, &items, vis, ImportType::Glob); + self.update(module_id, &items, vis, Some(ImportType::Glob(id))); } else { // glob import from same crate => we do an initial // import, and then need to propagate any further @@ -932,11 +941,11 @@ impl DefCollector<'_> { .filter(|(_, res)| !res.is_none()) .collect::>(); - self.update(module_id, &items, vis, ImportType::Glob); + self.update(module_id, &items, vis, Some(ImportType::Glob(id))); // record the glob import in case we add further items let glob = self.glob_imports.entry(m.local_id).or_default(); - if !glob.iter().any(|(mid, _)| *mid == module_id) { - glob.push((module_id, vis)); + if !glob.iter().any(|(mid, _, _)| *mid == module_id) { + glob.push((module_id, vis, id)); } } } @@ -962,7 +971,7 @@ impl DefCollector<'_> { (Some(name), res) }) .collect::>(); - self.update(module_id, &resolutions, vis, ImportType::Glob); + self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id))); } Some(d) => { tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d); @@ -982,10 +991,10 @@ impl DefCollector<'_> { resolutions: &[(Option, PerNs)], // Visibility this import will have vis: Visibility, - import_type: ImportType, + import: Option, ) { self.db.unwind_if_cancelled(); - self.update_recursive(module_id, resolutions, vis, import_type, 0) + self.update_recursive(module_id, resolutions, vis, import, 0) } fn update_recursive( @@ -996,7 +1005,7 @@ impl DefCollector<'_> { // All resolutions are imported with this visibility; the visibilities in // the `PerNs` values are ignored and overwritten vis: Visibility, - import_type: ImportType, + import: Option, depth: usize, ) { if GLOB_RECURSION_LIMIT.check(depth).is_err() { @@ -1013,7 +1022,7 @@ impl DefCollector<'_> { &mut self.from_glob_import, (module_id, name.clone()), res.with_visibility(vis), - import_type, + import, ); } None => { @@ -1058,7 +1067,7 @@ impl DefCollector<'_> { .get(&module_id) .into_iter() .flatten() - .filter(|(glob_importing_module, _)| { + .filter(|(glob_importing_module, _, _)| { // we know all resolutions have the same visibility (`vis`), so we // just need to check that once vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module) @@ -1066,12 +1075,12 @@ impl DefCollector<'_> { .cloned() .collect::>(); - for (glob_importing_module, glob_import_vis) in glob_imports { + for (glob_importing_module, glob_import_vis, use_) in glob_imports { self.update_recursive( glob_importing_module, resolutions, glob_import_vis, - ImportType::Glob, + Some(ImportType::Glob(use_)), depth + 1, ); } @@ -1474,7 +1483,9 @@ impl DefCollector<'_> { } for directive in &self.unresolved_imports { - if let ImportSource::Use { use_tree, id, is_prelude: _ } = directive.import.source { + if let ImportSource::Use { use_tree, id, is_prelude: _, kind: _ } = + 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) @@ -1538,7 +1549,7 @@ impl ModCollector<'_, '_> { module_id, &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))], vis, - ImportType::Named, + None, ) }; let resolve_vis = |def_map: &DefMap, visibility| { @@ -1968,7 +1979,7 @@ impl ModCollector<'_, '_> { self.module_id, &[(Some(name), PerNs::from_def(def, vis, false))], vis, - ImportType::Named, + None, ); res } diff --git a/crates/hir-def/src/nameres/tests.rs b/crates/hir-def/src/nameres/tests.rs index dd7c3c36306..e7cc44b04da 100644 --- a/crates/hir-def/src/nameres/tests.rs +++ b/crates/hir-def/src/nameres/tests.rs @@ -168,7 +168,7 @@ pub struct Baz; "#, expect![[r#" crate - Foo: t v + Foo: ti vi foo: t crate::foo @@ -194,8 +194,8 @@ pub enum Quux {}; "#, expect![[r#" crate - Baz: t v - Quux: t + Baz: ti vi + Quux: ti foo: t crate::foo @@ -225,11 +225,11 @@ pub struct Baz; "#, expect![[r#" crate - Baz: t v + Baz: ti vi foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -274,7 +274,7 @@ use self::E::V; expect![[r#" crate E: t - V: t v + V: ti vi "#]], ); } @@ -307,7 +307,7 @@ pub struct FromLib; crate::foo Bar: _ - FromLib: t v + FromLib: ti vi "#]], ); } @@ -328,7 +328,7 @@ pub struct Baz; "#, expect![[r#" crate - Baz: t + Baz: ti foo: t crate::foo @@ -352,7 +352,7 @@ pub struct Baz; "#, expect![[r#" crate - Baz: t v + Baz: ti vi "#]], ); } @@ -375,13 +375,13 @@ pub struct Arc; expect![[r#" crate alloc: t - alloc_crate: t + alloc_crate: te sync: t crate::alloc crate::sync - Arc: t v + Arc: ti vi "#]], ); } @@ -404,13 +404,13 @@ pub struct Arc; expect![[r#" crate alloc: t - alloc_crate: t + alloc_crate: te sync: t crate::alloc crate::sync - Arc: t v + Arc: ti vi "#]], ); } @@ -426,7 +426,7 @@ extern crate self as bla; "#, expect![[r#" crate - bla: t + bla: te "#]], ); } @@ -447,7 +447,7 @@ pub struct Baz; "#, expect![[r#" crate - Baz: t v + Baz: ti vi "#]], ); } @@ -465,7 +465,7 @@ pub struct Bar; "#, expect![[r#" crate - Bar: t v + Bar: ti vi foo: v "#]], ); @@ -492,9 +492,9 @@ fn no_std_prelude() { } "#, expect![[r#" - crate - Rust: t v - "#]], + crate + Rust: ti vi + "#]], ); } @@ -516,9 +516,9 @@ fn edition_specific_preludes() { } "#, expect![[r#" - crate - Rust2018: t v - "#]], + crate + Rust2018: ti vi + "#]], ); check( r#" @@ -533,9 +533,9 @@ fn edition_specific_preludes() { } "#, expect![[r#" - crate - Rust2021: t v - "#]], + crate + Rust2021: ti vi + "#]], ); } @@ -563,8 +563,8 @@ pub mod prelude { "#, expect![[r#" crate - Bar: t v - Foo: t v + Bar: ti vi + Foo: ti vi "#]], ); } @@ -590,7 +590,7 @@ pub mod prelude { "#, expect![[r#" crate - Bar: t v + Bar: ti vi Baz: _ Foo: _ "#]], @@ -619,8 +619,8 @@ pub mod prelude { expect![[r#" crate Bar: _ - Baz: t v - Foo: t v + Baz: ti vi + Foo: ti vi "#]], ); } @@ -643,7 +643,7 @@ mod b { "#, expect![[r#" crate - T: t v + T: ti vi a: t b: t @@ -816,8 +816,8 @@ fn bar() {} expect![[r#" crate bar: v - baz: v - foo: t + baz: vi + foo: ti "#]], ); } @@ -836,7 +836,7 @@ use self::m::S::{self}; "#, expect![[r#" crate - S: t + S: ti m: t crate::m @@ -860,8 +860,8 @@ pub const settings: () = (); "#, expect![[r#" crate - Settings: t v - settings: v + Settings: ti vi + settings: vi "#]], ) } @@ -890,8 +890,8 @@ pub struct Struct; "#, expect![[r#" crate - Struct: t v - dep: t + Struct: ti vi + dep: te "#]], ); } @@ -917,13 +917,13 @@ use some_module::unknown_func; crate other_module: t some_module: t - unknown_func: v + unknown_func: vi crate::other_module some_submodule: t crate::other_module::some_submodule - unknown_func: v + unknown_func: vi crate::some_module unknown_func: v diff --git a/crates/hir-def/src/nameres/tests/globs.rs b/crates/hir-def/src/nameres/tests/globs.rs index 88a3c76393f..1ca74b5da6b 100644 --- a/crates/hir-def/src/nameres/tests/globs.rs +++ b/crates/hir-def/src/nameres/tests/globs.rs @@ -24,7 +24,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi Foo: t v bar: t @@ -237,9 +237,9 @@ pub mod baz { pub struct Bar; } "#, expect![[r#" crate - Bar: t v + Bar: ti vi bar: t - baz: t + baz: ti foo: t crate::bar @@ -276,9 +276,9 @@ pub mod baz { pub struct Bar; } "#, expect![[r#" crate - Bar: t v + Bar: ti vi bar: t - baz: t + baz: ti foo: t crate::bar @@ -323,7 +323,7 @@ mod d { X: t v crate::b - foo: t + foo: ti crate::c foo: t @@ -332,8 +332,8 @@ mod d { Y: t v crate::d - Y: t v - foo: t + Y: ti vi + foo: ti "#]], ); } @@ -355,7 +355,7 @@ use event::Event; "#, expect![[r#" crate - Event: t + Event: ti event: t crate::event diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs index f4cca8d68d0..e64fa0b46f1 100644 --- a/crates/hir-def/src/nameres/tests/macros.rs +++ b/crates/hir-def/src/nameres/tests/macros.rs @@ -203,8 +203,8 @@ macro_rules! bar { expect![[r#" crate Foo: t - bar: m - foo: m + bar: mi + foo: mi "#]], ); } @@ -251,7 +251,7 @@ mod priv_mod { Bar: t v Foo: t v bar: t - foo: t + foo: te crate::bar Baz: t v @@ -318,9 +318,9 @@ macro_rules! baz3 { () => { struct OkBaz3; } } OkBaz1: t v OkBaz2: t v OkBaz3: t v - all: t - empty: t - multiple: t + all: te + empty: te + multiple: te "#]], ); } @@ -551,8 +551,8 @@ fn baz() {} "#, expect![[r#" crate - bar: t m - baz: t v m + bar: ti mi + baz: ti v mi foo: t m "#]], ); @@ -583,7 +583,7 @@ mod m { crate Alias: t v Direct: t v - foo: t + foo: te "#]], ); } @@ -628,9 +628,9 @@ mod m { m: t crate::m - alias1: m - alias2: m - alias3: m + alias1: mi + alias2: mi + alias3: mi not_found: _ "#]], ); @@ -682,11 +682,11 @@ pub struct Baz; "#, expect![[r#" crate - Bar: t v - Baz: t v + Bar: ti vi + Baz: ti vi Foo: t v - FooSelf: t v - foo: t + FooSelf: ti vi + foo: te m: t crate::m @@ -725,7 +725,7 @@ pub struct bar; "#, expect![[r#" crate - bar: t v + bar: ti vi "#]], ); } @@ -1340,7 +1340,7 @@ pub mod prelude { crate Ok: t v bar: m - dep: t + dep: te foo: m ok: v "#]], @@ -1370,13 +1370,13 @@ macro_rules! mk_foo { } "#, expect![[r#" - crate - a: t - lib: t + crate + a: t + lib: te - crate::a - Ok: t v - "#]], + crate::a + Ok: t v + "#]], ); } @@ -1427,8 +1427,8 @@ pub mod prelude { expect![[r#" crate Ok: t v - bar: m - foo: m + bar: mi + foo: mi ok: v "#]], ); diff --git a/crates/hir-def/src/nameres/tests/mod_resolution.rs b/crates/hir-def/src/nameres/tests/mod_resolution.rs index 81bc0ff91e3..1327d9aa62e 100644 --- a/crates/hir-def/src/nameres/tests/mod_resolution.rs +++ b/crates/hir-def/src/nameres/tests/mod_resolution.rs @@ -80,18 +80,18 @@ pub trait Iterator; prelude: t crate::iter - Iterator: t + Iterator: ti traits: t crate::iter::traits - Iterator: t + Iterator: ti iterator: t crate::iter::traits::iterator Iterator: t crate::prelude - Iterator: t + Iterator: ti "#]], ); } @@ -109,7 +109,7 @@ pub struct Bar; "#, expect![[r#" crate - Bar: t v + Bar: ti vi foo: t crate::foo @@ -139,7 +139,7 @@ pub struct Baz; "#, expect![[r#" crate - Bar: t v + Bar: ti vi r#async: t crate::r#async @@ -176,8 +176,8 @@ pub struct Bar; "#, expect![[r#" crate - Bar: t v - Foo: t v + Bar: ti vi + Foo: ti vi r#async: t crate::r#async @@ -207,7 +207,7 @@ pub struct Bar; "#, expect![[r#" crate - Bar: t v + Bar: ti vi foo: t crate::foo @@ -236,7 +236,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -265,7 +265,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -292,7 +292,7 @@ use super::Baz; foo: t crate::foo - Baz: t v + Baz: ti vi "#]], ); } @@ -626,7 +626,7 @@ pub struct Baz; "#, expect![[r#" crate - Baz: t v + Baz: ti vi foo: t crate::foo @@ -660,7 +660,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -694,7 +694,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -728,7 +728,7 @@ pub struct Baz; foo: t crate::foo - Baz: t v + Baz: ti vi bar: t crate::foo::bar @@ -868,7 +868,7 @@ pub mod hash { pub trait Hash {} } "#, expect![[r#" crate - Hash: t + Hash: ti core: t crate::core diff --git a/crates/hir-def/src/nameres/tests/primitives.rs b/crates/hir-def/src/nameres/tests/primitives.rs index 215e8952d90..271eb1c79b1 100644 --- a/crates/hir-def/src/nameres/tests/primitives.rs +++ b/crates/hir-def/src/nameres/tests/primitives.rs @@ -14,10 +14,10 @@ pub use i32 as int; expect![[r#" crate foo: t - int: t + int: ti crate::foo - int: t + int: ti "#]], ); } From a17d73ad36baaec68078fe8b44c0b43e94a8e46a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 17 Aug 2023 10:52:13 +0200 Subject: [PATCH 3/3] Thread imports through the resolver --- crates/hir-def/src/item_scope.rs | 60 ++++++--- .../hir-def/src/macro_expansion_tests/mod.rs | 2 +- crates/hir-def/src/nameres/collector.rs | 13 +- crates/hir-def/src/nameres/path_resolution.rs | 76 +++++++----- crates/hir-def/src/per_ns.rs | 37 ++++-- crates/hir-def/src/resolver.rs | 116 +++++++++++------- crates/hir-ty/src/diagnostics/unsafe_check.rs | 2 +- crates/hir-ty/src/infer.rs | 8 +- crates/hir-ty/src/infer/closure.rs | 2 +- crates/hir-ty/src/infer/path.rs | 4 +- crates/hir-ty/src/lower.rs | 12 +- crates/hir-ty/src/mir/lower.rs | 4 +- .../hir-ty/src/mir/lower/pattern_matching.rs | 2 +- crates/hir/src/semantics.rs | 2 +- crates/hir/src/source_analyzer.rs | 9 +- 15 files changed, 218 insertions(+), 131 deletions(-) diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs index 59a1c5f49e2..0baf3fa7f44 100644 --- a/crates/hir-def/src/item_scope.rs +++ b/crates/hir-def/src/item_scope.rs @@ -34,7 +34,7 @@ pub enum ImportOrExternCrate { } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub enum ImportType { +pub(crate) enum ImportType { Import(ImportId), Glob(UseId), ExternCrate(ExternCrateId), @@ -118,7 +118,7 @@ struct DeriveMacroInvocation { pub(crate) static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { BuiltinType::ALL .iter() - .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public))) + .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public, None))) .collect() }); @@ -234,9 +234,16 @@ impl ItemScope { pub(crate) fn resolutions(&self) -> impl Iterator, PerNs)> + '_ { self.entries().map(|(name, res)| (Some(name.clone()), res)).chain( - self.unnamed_trait_imports - .iter() - .map(|(tr, (vis, _))| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))), + self.unnamed_trait_imports.iter().map(|(tr, (vis, i))| { + ( + None, + PerNs::types( + ModuleDefId::TraitId(*tr), + *vis, + i.map(ImportOrExternCrate::Import), + ), + ) + }), ) } } @@ -327,11 +334,13 @@ impl ItemScope { }) } + // FIXME: This is only used in collection, we should move the relevant parts of it out of ItemScope pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option { self.unnamed_trait_imports.get(&tr).copied().map(|(a, _)| a) } pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) { + // FIXME: import self.unnamed_trait_imports.insert(tr, (vis, None)); } @@ -344,6 +353,8 @@ impl ItemScope { ) -> bool { let mut changed = false; + // FIXME: Document and simplify this + if let Some(mut fld) = def.types { let existing = self.types.entry(lookup.1.clone()); match existing { @@ -626,28 +637,39 @@ impl ItemScope { } impl PerNs { - pub(crate) fn from_def(def: ModuleDefId, v: Visibility, has_constructor: bool) -> PerNs { + pub(crate) fn from_def( + def: ModuleDefId, + v: Visibility, + has_constructor: bool, + import: Option, + ) -> PerNs { match def { - ModuleDefId::ModuleId(_) => PerNs::types(def, v), - ModuleDefId::FunctionId(_) => PerNs::values(def, v), + ModuleDefId::ModuleId(_) => PerNs::types(def, v, import), + ModuleDefId::FunctionId(_) => { + PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import)) + } ModuleDefId::AdtId(adt) => match adt { - AdtId::UnionId(_) => PerNs::types(def, v), - AdtId::EnumId(_) => PerNs::types(def, v), + AdtId::UnionId(_) => PerNs::types(def, v, import), + AdtId::EnumId(_) => PerNs::types(def, v, import), AdtId::StructId(_) => { if has_constructor { - PerNs::both(def, def, v) + PerNs::both(def, def, v, import) } else { - PerNs::types(def, v) + PerNs::types(def, v, import) } } }, - ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v), - ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v), - ModuleDefId::TraitId(_) => PerNs::types(def, v), - ModuleDefId::TraitAliasId(_) => PerNs::types(def, v), - ModuleDefId::TypeAliasId(_) => PerNs::types(def, v), - ModuleDefId::BuiltinType(_) => PerNs::types(def, v), - ModuleDefId::MacroId(mac) => PerNs::macros(mac, v), + ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v, import), + ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => { + PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import)) + } + ModuleDefId::TraitId(_) => PerNs::types(def, v, import), + ModuleDefId::TraitAliasId(_) => PerNs::types(def, v, import), + ModuleDefId::TypeAliasId(_) => PerNs::types(def, v, import), + ModuleDefId::BuiltinType(_) => PerNs::types(def, v, import), + ModuleDefId::MacroId(mac) => { + PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::into_import)) + } } } } diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs index 7a87e61c693..8adced4e082 100644 --- a/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -131,7 +131,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream .as_call_id_with_errors(&db, krate, |path| { resolver .resolve_path_as_macro(&db, &path, Some(MacroSubNs::Bang)) - .map(|it| macro_id_to_def_id(&db, it)) + .map(|(it, _)| macro_id_to_def_id(&db, it)) }) .unwrap(); let macro_call_id = res.value.unwrap(); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 48eaec0f4e5..e9e71a8747f 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -648,7 +648,7 @@ impl DefCollector<'_> { self.def_map.modules[module_id].scope.declare(macro_.into()); self.update( module_id, - &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], + &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))], Visibility::Public, None, ); @@ -684,7 +684,7 @@ impl DefCollector<'_> { self.def_map.modules[module_id].scope.declare(macro_.into()); self.update( module_id, - &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], + &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))], vis, None, ); @@ -699,7 +699,7 @@ impl DefCollector<'_> { self.def_map.modules[module_id].scope.declare(macro_.into()); self.update( module_id, - &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], + &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))], Visibility::Public, None, ); @@ -783,6 +783,7 @@ impl DefCollector<'_> { Some(res) => PartialResolvedImport::Resolved(PerNs::types( res.into(), Visibility::Public, + None, )), None => PartialResolvedImport::Unresolved, } @@ -967,7 +968,7 @@ impl DefCollector<'_> { .map(|(local_id, variant_data)| { let name = variant_data.name.clone(); let variant = EnumVariantId { parent: e, local_id }; - let res = PerNs::both(variant.into(), variant.into(), vis); + let res = PerNs::both(variant.into(), variant.into(), vis, None); (Some(name), res) }) .collect::>(); @@ -1547,7 +1548,7 @@ impl ModCollector<'_, '_> { 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))], + &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor, None))], vis, None, ) @@ -1977,7 +1978,7 @@ impl ModCollector<'_, '_> { def_map.modules[self.module_id].scope.declare(def); self.def_collector.update( self.module_id, - &[(Some(name), PerNs::from_def(def, vis, false))], + &[(Some(name), PerNs::from_def(def, vis, false, None))], vis, None, ); diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index fc296e1e588..460a908b6db 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -15,8 +15,9 @@ use hir_expand::name::Name; use triomphe::Arc; use crate::{ + data::adt::VariantData, db::DefDatabase, - item_scope::BUILTIN_SCOPE, + item_scope::{ImportOrExternCrate, BUILTIN_SCOPE}, nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs}, path::{ModPath, PathKind}, per_ns::PerNs, @@ -196,15 +197,15 @@ impl DefMap { PathKind::DollarCrate(krate) => { if krate == self.krate { cov_mark::hit!(macro_dollar_crate_self); - PerNs::types(self.crate_root().into(), Visibility::Public) + PerNs::types(self.crate_root().into(), Visibility::Public, None) } else { let def_map = db.crate_def_map(krate); let module = def_map.module_id(Self::ROOT); cov_mark::hit!(macro_dollar_crate_other); - PerNs::types(module.into(), Visibility::Public) + PerNs::types(module.into(), Visibility::Public, None) } } - PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public), + PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public, None), // plain import or absolute path in 2015: crate-relative with // fallback to extern prelude (with the simplification in // rust-lang/rust#57745) @@ -291,7 +292,7 @@ impl DefMap { ); } - PerNs::types(module.into(), Visibility::Public) + PerNs::types(module.into(), Visibility::Public, None) } PathKind::Abs => { // 2018-style absolute path -- only extern prelude @@ -299,9 +300,13 @@ impl DefMap { Some((_, segment)) => segment, None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; - if let Some(&(def, _extern_crate)) = 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) + PerNs::types( + def.into(), + Visibility::Public, + extern_crate.map(ImportOrExternCrate::ExternCrate), + ) } else { return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude } @@ -309,7 +314,7 @@ impl DefMap { }; for (i, segment) in segments { - let (curr, vis) = match curr_per_ns.take_types_vis() { + let (curr, vis, imp) = match curr_per_ns.take_types_full() { Some(r) => r, None => { // we still have path segments left, but the path so far @@ -364,18 +369,20 @@ impl DefMap { Some(local_id) => { let variant = EnumVariantId { parent: e, local_id }; match &*enum_data.variants[local_id].variant_data { - crate::data::adt::VariantData::Record(_) => { - PerNs::types(variant.into(), Visibility::Public) - } - crate::data::adt::VariantData::Tuple(_) - | crate::data::adt::VariantData::Unit => { - PerNs::both(variant.into(), variant.into(), Visibility::Public) + VariantData::Record(_) => { + PerNs::types(variant.into(), Visibility::Public, None) } + VariantData::Tuple(_) | VariantData::Unit => PerNs::both( + variant.into(), + variant.into(), + Visibility::Public, + None, + ), } } None => { return ResolvePathResult::with( - PerNs::types(e.into(), vis), + PerNs::types(e.into(), vis, imp), ReachedFixedPoint::Yes, Some(i), Some(self.krate), @@ -393,7 +400,7 @@ impl DefMap { ); return ResolvePathResult::with( - PerNs::types(s, vis), + PerNs::types(s, vis, imp), ReachedFixedPoint::Yes, Some(i), Some(self.krate), @@ -430,7 +437,7 @@ impl DefMap { .filter(|&id| { sub_namespace_match(Some(MacroSubNs::from_id(db, id)), expected_macro_subns) }) - .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public)); + .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public, None)); let from_scope = self[module].scope.get(name).filter_macro(db, expected_macro_subns); let from_builtin = match self.block { Some(_) => { @@ -449,16 +456,26 @@ impl DefMap { let extern_prelude = || { if self.block.is_some() { - // Don't resolve extern prelude in block `DefMap`s. + // Don't resolve extern prelude in block `DefMap`s, defer it to the crate def map so + // that blocks can properly shadow them return PerNs::none(); } - self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| { - 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, + extern_crate.map(ImportOrExternCrate::ExternCrate), + ) }) }; let macro_use_prelude = || { self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| { - PerNs::macros(it.into(), Visibility::Public) + PerNs::macros( + it.into(), + Visibility::Public, + // FIXME? + None, // extern_crate.map(ImportOrExternCrate::ExternCrate), + ) }) }; let prelude = || self.resolve_in_prelude(db, name); @@ -487,13 +504,16 @@ impl DefMap { // Don't resolve extern prelude in block `DefMap`s. return PerNs::none(); } - self.data - .extern_prelude - .get(name) - .copied() - .map_or(PerNs::none(), |(it, _extern_crate)| { - PerNs::types(it.into(), Visibility::Public) - }) + self.data.extern_prelude.get(name).copied().map_or( + PerNs::none(), + |(it, extern_crate)| { + PerNs::types( + it.into(), + Visibility::Public, + extern_crate.map(ImportOrExternCrate::ExternCrate), + ) + }, + ) }; from_crate_root.or_else(from_extern_prelude) diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs index f32a97d1a3a..3f3f9f42491 100644 --- a/crates/hir-def/src/per_ns.rs +++ b/crates/hir-def/src/per_ns.rs @@ -27,20 +27,29 @@ impl PerNs { PerNs { types: None, values: None, macros: None } } - pub fn values(t: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: None, values: Some((t, v, None)), macros: None } + pub fn values(t: ModuleDefId, v: Visibility, i: Option) -> PerNs { + PerNs { types: None, values: Some((t, v, i)), macros: None } } - pub fn types(t: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: Some((t, v, None)), values: None, macros: None } + pub fn types(t: ModuleDefId, v: Visibility, i: Option) -> PerNs { + PerNs { types: Some((t, v, i)), values: None, macros: None } } - pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs { - PerNs { types: Some((types, v, None)), values: Some((values, v, None)), macros: None } + pub fn both( + types: ModuleDefId, + values: ModuleDefId, + v: Visibility, + i: Option, + ) -> PerNs { + PerNs { + types: Some((types, v, i)), + values: Some((values, v, i.and_then(ImportOrExternCrate::into_import))), + macros: None, + } } - pub fn macros(macro_: MacroId, v: Visibility) -> PerNs { - PerNs { types: None, values: None, macros: Some((macro_, v, None)) } + pub fn macros(macro_: MacroId, v: Visibility, i: Option) -> PerNs { + PerNs { types: None, values: None, macros: Some((macro_, v, i)) } } pub fn is_none(&self) -> bool { @@ -55,18 +64,26 @@ impl PerNs { self.types.map(|it| it.0) } - pub fn take_types_vis(self) -> Option<(ModuleDefId, Visibility)> { - self.types.map(|(a, b, _)| (a, b)) + pub fn take_types_full(self) -> Option<(ModuleDefId, Visibility, Option)> { + self.types } pub fn take_values(self) -> Option { self.values.map(|it| it.0) } + pub fn take_values_import(self) -> Option<(ModuleDefId, Option)> { + self.values.map(|it| (it.0, it.2)) + } + pub fn take_macros(self) -> Option { self.macros.map(|it| it.0) } + pub fn take_macros_import(self) -> Option<(MacroId, Option)> { + self.macros.map(|it| (it.0, it.2)) + } + pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { let _p = profile::span("PerNs::filter_visibility"); PerNs { diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 28ab0f8f6ee..62576100ea4 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -15,7 +15,7 @@ use crate::{ db::DefDatabase, generics::{GenericParams, TypeOrConstParamData}, hir::{BindingId, ExprId, LabelId}, - item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, + item_scope::{BuiltinShadowMode, ImportId, ImportOrExternCrate, BUILTIN_SCOPE}, lang_item::LangItemTarget, nameres::{DefMap, MacroSubNs}, path::{ModPath, Path, PathKind}, @@ -100,8 +100,8 @@ pub enum TypeNs { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ResolveValueResult { - ValueNs(ValueNs), - Partial(TypeNs, usize), + ValueNs(ValueNs, Option), + Partial(TypeNs, usize, Option), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -152,7 +152,7 @@ impl Resolver { &self, db: &dyn DefDatabase, path: &Path, - ) -> Option<(TypeNs, Option)> { + ) -> Option<(TypeNs, Option, Option)> { let path = match path { Path::Normal { mod_path, .. } => mod_path, Path::LangItem(l) => { @@ -169,6 +169,7 @@ impl Resolver { | LangItemTarget::Static(_) => return None, }, None, + None, )) } }; @@ -185,17 +186,17 @@ impl Resolver { Scope::ExprScope(_) => continue, Scope::GenericParams { params, def } => { if let Some(id) = params.find_type_by_name(first_name, *def) { - return Some((TypeNs::GenericParam(id), remaining_idx())); + return Some((TypeNs::GenericParam(id), remaining_idx(), None)); } } &Scope::ImplDefScope(impl_) => { if first_name == &name![Self] { - return Some((TypeNs::SelfType(impl_), remaining_idx())); + return Some((TypeNs::SelfType(impl_), remaining_idx(), None)); } } &Scope::AdtScope(adt) => { if first_name == &name![Self] { - return Some((TypeNs::AdtSelfType(adt), remaining_idx())); + return Some((TypeNs::AdtSelfType(adt), remaining_idx(), None)); } } Scope::BlockScope(m) => { @@ -208,12 +209,24 @@ impl Resolver { self.module_scope.resolve_path_in_type_ns(db, path) } + pub fn resolve_path_in_type_ns_fully_with_imports( + &self, + db: &dyn DefDatabase, + path: &Path, + ) -> Option<(TypeNs, Option)> { + let (res, unresolved, imp) = self.resolve_path_in_type_ns(db, path)?; + if unresolved.is_some() { + return None; + } + Some((res, imp)) + } + pub fn resolve_path_in_type_ns_fully( &self, db: &dyn DefDatabase, path: &Path, ) -> Option { - let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; + let (res, unresolved, _) = self.resolve_path_in_type_ns(db, path)?; if unresolved.is_some() { return None; } @@ -235,7 +248,6 @@ impl Resolver { RawVisibility::Public => Some(Visibility::Public), } } - pub fn resolve_path_in_value_ns( &self, db: &dyn DefDatabase, @@ -244,17 +256,20 @@ impl Resolver { let path = match path { Path::Normal { mod_path, .. } => mod_path, Path::LangItem(l) => { - return Some(ResolveValueResult::ValueNs(match *l { - LangItemTarget::Function(it) => ValueNs::FunctionId(it), - LangItemTarget::Static(it) => ValueNs::StaticId(it), - LangItemTarget::Struct(it) => ValueNs::StructId(it), - LangItemTarget::EnumVariant(it) => ValueNs::EnumVariantId(it), - LangItemTarget::Union(_) - | LangItemTarget::ImplDef(_) - | LangItemTarget::TypeAlias(_) - | LangItemTarget::Trait(_) - | LangItemTarget::EnumId(_) => return None, - })) + return Some(ResolveValueResult::ValueNs( + match *l { + LangItemTarget::Function(it) => ValueNs::FunctionId(it), + LangItemTarget::Static(it) => ValueNs::StaticId(it), + LangItemTarget::Struct(it) => ValueNs::StructId(it), + LangItemTarget::EnumVariant(it) => ValueNs::EnumVariantId(it), + LangItemTarget::Union(_) + | LangItemTarget::ImplDef(_) + | LangItemTarget::TypeAlias(_) + | LangItemTarget::Trait(_) + | LangItemTarget::EnumId(_) => return None, + }, + None, + )) } }; let n_segments = path.segments().len(); @@ -276,20 +291,24 @@ impl Resolver { .find(|entry| entry.name() == first_name); if let Some(e) = entry { - return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding( - e.binding(), - ))); + return Some(ResolveValueResult::ValueNs( + ValueNs::LocalBinding(e.binding()), + None, + )); } } Scope::GenericParams { params, def } => { if let Some(id) = params.find_const_by_name(first_name, *def) { let val = ValueNs::GenericParam(id); - return Some(ResolveValueResult::ValueNs(val)); + return Some(ResolveValueResult::ValueNs(val, None)); } } &Scope::ImplDefScope(impl_) => { if first_name == &name![Self] { - return Some(ResolveValueResult::ValueNs(ValueNs::ImplSelf(impl_))); + return Some(ResolveValueResult::ValueNs( + ValueNs::ImplSelf(impl_), + None, + )); } } // bare `Self` doesn't work in the value namespace in a struct/enum definition @@ -308,18 +327,22 @@ impl Resolver { Scope::GenericParams { params, def } => { if let Some(id) = params.find_type_by_name(first_name, *def) { let ty = TypeNs::GenericParam(id); - return Some(ResolveValueResult::Partial(ty, 1)); + return Some(ResolveValueResult::Partial(ty, 1, None)); } } &Scope::ImplDefScope(impl_) => { if first_name == &name![Self] { - return Some(ResolveValueResult::Partial(TypeNs::SelfType(impl_), 1)); + return Some(ResolveValueResult::Partial( + TypeNs::SelfType(impl_), + 1, + None, + )); } } Scope::AdtScope(adt) => { if first_name == &name![Self] { let ty = TypeNs::AdtSelfType(*adt); - return Some(ResolveValueResult::Partial(ty, 1)); + return Some(ResolveValueResult::Partial(ty, 1, None)); } } Scope::BlockScope(m) => { @@ -340,7 +363,7 @@ impl Resolver { // `use core::u16;`. if path.kind == PathKind::Plain && n_segments > 1 { if let Some(builtin) = BuiltinType::by_name(first_name) { - return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1)); + return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1, None)); } } @@ -353,7 +376,7 @@ impl Resolver { path: &Path, ) -> Option { match self.resolve_path_in_value_ns(db, path)? { - ResolveValueResult::ValueNs(it) => Some(it), + ResolveValueResult::ValueNs(it, _) => Some(it), ResolveValueResult::Partial(..) => None, } } @@ -363,12 +386,12 @@ impl Resolver { db: &dyn DefDatabase, path: &ModPath, expected_macro_kind: Option, - ) -> Option { + ) -> Option<(MacroId, Option)> { let (item_map, module) = self.item_scope(); item_map .resolve_path(db, module, path, BuiltinShadowMode::Other, expected_macro_kind) .0 - .take_macros() + .take_macros_import() } /// Returns a set of names available in the current scope. @@ -776,11 +799,12 @@ impl ModuleItemMap { self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); match idx { None => { - let value = to_value_ns(module_def)?; - Some(ResolveValueResult::ValueNs(value)) + let (value, import) = to_value_ns(module_def)?; + Some(ResolveValueResult::ValueNs(value, import)) } Some(idx) => { - let ty = match module_def.take_types()? { + let (def, _, import) = module_def.take_types_full()?; + let ty = match def { ModuleDefId::AdtId(it) => TypeNs::AdtId(it), ModuleDefId::TraitId(it) => TypeNs::TraitId(it), ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it), @@ -794,7 +818,7 @@ impl ModuleItemMap { | ModuleDefId::MacroId(_) | ModuleDefId::StaticId(_) => return None, }; - Some(ResolveValueResult::Partial(ty, idx)) + Some(ResolveValueResult::Partial(ty, idx, import)) } } } @@ -803,16 +827,17 @@ impl ModuleItemMap { &self, db: &dyn DefDatabase, path: &ModPath, - ) -> Option<(TypeNs, Option)> { + ) -> Option<(TypeNs, Option, Option)> { let (module_def, idx) = self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); - let res = to_type_ns(module_def)?; - Some((res, idx)) + let (res, import) = to_type_ns(module_def)?; + Some((res, idx, import)) } } -fn to_value_ns(per_ns: PerNs) -> Option { - let res = match per_ns.take_values()? { +fn to_value_ns(per_ns: PerNs) -> Option<(ValueNs, Option)> { + let (def, import) = per_ns.take_values_import()?; + let res = match def { ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), @@ -827,11 +852,12 @@ fn to_value_ns(per_ns: PerNs) -> Option { | ModuleDefId::MacroId(_) | ModuleDefId::ModuleId(_) => return None, }; - Some(res) + Some((res, import)) } -fn to_type_ns(per_ns: PerNs) -> Option { - let res = match per_ns.take_types()? { +fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option)> { + let (def, _, import) = per_ns.take_types_full()?; + let res = match def { ModuleDefId::AdtId(it) => TypeNs::AdtId(it), ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), @@ -847,7 +873,7 @@ fn to_type_ns(per_ns: PerNs) -> Option { | ModuleDefId::StaticId(_) | ModuleDefId::ModuleId(_) => return None, }; - Some(res) + Some((res, import)) } type FxIndexMap = IndexMap>; diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs index 9f9a56ffab0..cbca0e801d4 100644 --- a/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -75,7 +75,7 @@ fn walk_unsafe( Expr::Path(path) => { let resolver = resolver_for_expr(db.upcast(), def, current); let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path); - if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id))) = value_or_partial { + if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial { if db.static_data(id).mutable { unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block }); } diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index b4915dbf0f9..0fb4934444b 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -1017,7 +1017,7 @@ impl<'a> InferenceContext<'a> { let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into()); let (resolution, unresolved) = if value_ns { match self.resolver.resolve_path_in_value_ns(self.db.upcast(), path) { - Some(ResolveValueResult::ValueNs(value)) => match value { + Some(ResolveValueResult::ValueNs(value, _)) => match value { ValueNs::EnumVariantId(var) => { let substs = ctx.substs_from_path(path, var.into(), true); let ty = self.db.ty(var.parent.into()); @@ -1033,12 +1033,14 @@ impl<'a> InferenceContext<'a> { ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None), _ => return (self.err_ty(), None), }, - Some(ResolveValueResult::Partial(typens, unresolved)) => (typens, Some(unresolved)), + Some(ResolveValueResult::Partial(typens, unresolved, _)) => { + (typens, Some(unresolved)) + } None => return (self.err_ty(), None), } } else { match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) { - Some(it) => it, + Some((it, idx, _)) => (it, idx), None => return (self.err_ty(), None), } }; diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index 1781f6c58f1..23efe616f4f 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -322,7 +322,7 @@ impl InferenceContext<'_> { Expr::Path(p) => { let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); if let Some(r) = resolver.resolve_path_in_value_ns(self.db.upcast(), p) { - if let ResolveValueResult::ValueNs(v) = r { + if let ResolveValueResult::ValueNs(v, _) = r { if let ValueNs::LocalBinding(b) = v { return Some(HirPlace { local: b, projections: vec![] }); } diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs index 79d9e21e797..2a51c84db3a 100644 --- a/crates/hir-ty/src/infer/path.rs +++ b/crates/hir-ty/src/infer/path.rs @@ -61,8 +61,8 @@ impl InferenceContext<'_> { self.resolver.resolve_path_in_value_ns(self.db.upcast(), path)?; match value_or_partial { - ResolveValueResult::ValueNs(it) => (it, None), - ResolveValueResult::Partial(def, remaining_index) => self + ResolveValueResult::ValueNs(it, _) => (it, None), + ResolveValueResult::Partial(def, remaining_index, _) => self .resolve_assoc_item(def, path, remaining_index, id) .map(|(it, substs)| (it, Some(substs)))?, } diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 20dccfafb38..0ab04b83cf8 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -390,11 +390,9 @@ impl<'a> TyLoweringContext<'a> { let ty = { let macro_call = macro_call.to_node(self.db.upcast()); let resolver = |path| { - self.resolver.resolve_path_as_macro( - self.db.upcast(), - &path, - Some(MacroSubNs::Bang), - ) + self.resolver + .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang)) + .map(|(it, _)| it) }; match expander.enter_expand::(self.db.upcast(), macro_call, resolver) { @@ -446,7 +444,7 @@ impl<'a> TyLoweringContext<'a> { return None; } let resolution = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) { - Some((it, None)) => it, + Some((it, None, _)) => it, _ => return None, }; match resolution { @@ -626,7 +624,7 @@ impl<'a> TyLoweringContext<'a> { return self.lower_ty_relative_path(ty, res, path.segments()); } - let (resolution, remaining_index) = + let (resolution, remaining_index, _) = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) { Some(it) => it, None => return (TyKind::Error.intern(Interner), None), diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 7ab0c1f7f2f..51cf882d053 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -1352,14 +1352,14 @@ impl<'ctx> MirLowerCtx<'ctx> { .resolve_path_in_value_ns(self.db.upcast(), c) .ok_or_else(unresolved_name)?; match pr { - ResolveValueResult::ValueNs(v) => { + ResolveValueResult::ValueNs(v, _) => { if let ValueNs::ConstId(c) = v { self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty) } else { not_supported!("bad path in range pattern"); } } - ResolveValueResult::Partial(_, _) => { + ResolveValueResult::Partial(_, _, _) => { not_supported!("associated constants in range pattern") } } diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 3354cbd76a0..1cdfd919742 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -323,7 +323,7 @@ impl MirLowerCtx<'_> { break 'b (c, x.1); } } - if let ResolveValueResult::ValueNs(v) = pr { + if let ResolveValueResult::ValueNs(v, _) = pr { if let ValueNs::ConstId(c) = v { break 'b (c, Substitution::empty(Interner)); } diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index e99d2984c36..55760ba75ab 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -606,7 +606,7 @@ impl<'db> SemanticsImpl<'db> { let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { resolver .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang)) - .map(|it| macro_id_to_def_id(self.db.upcast(), it)) + .map(|(it, _)| macro_id_to_def_id(self.db.upcast(), it)) })?; hir_expand::db::expand_speculative( self.db.upcast(), diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 3499daf1140..f29fb1edf00 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -487,7 +487,7 @@ impl SourceAnalyzer { let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?; self.resolver .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang)) - .map(|it| it.into()) + .map(|(it, _)| it.into()) } pub(crate) fn resolve_bind_pat_to_const( @@ -760,7 +760,7 @@ impl SourceAnalyzer { let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { self.resolver .resolve_path_as_macro(db.upcast(), &path, Some(MacroSubNs::Bang)) - .map(|it| macro_id_to_def_id(db.upcast(), it)) + .map(|(it, _)| macro_id_to_def_id(db.upcast(), it)) })?; Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64) } @@ -966,6 +966,7 @@ pub(crate) fn resolve_hir_path_as_attr_macro( ) -> Option { resolver .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Attr)) + .map(|(it, _)| it) .map(Into::into) } @@ -983,7 +984,7 @@ fn resolve_hir_path_( res.map(|ty_ns| (ty_ns, path.segments().first())) } None => { - let (ty, remaining_idx) = resolver.resolve_path_in_type_ns(db.upcast(), path)?; + let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db.upcast(), path)?; match remaining_idx { Some(remaining_idx) => { if remaining_idx + 1 == path.segments().len() { @@ -1067,7 +1068,7 @@ fn resolve_hir_path_( let macros = || { resolver .resolve_path_as_macro(db.upcast(), path.mod_path()?, None) - .map(|def| PathResolution::Def(ModuleDef::Macro(def.into()))) + .map(|(def, _)| PathResolution::Def(ModuleDef::Macro(def.into()))) }; if prefer_value_ns { values().or_else(types) } else { types().or_else(values) }