Skip to content

Commit af80482

Browse files
committed
Prepare ItemScope for IDE import resolution
1 parent 1b67823 commit af80482

File tree

11 files changed

+174
-67
lines changed

11 files changed

+174
-67
lines changed

crates/hir-def/src/find_path.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,4 +1293,22 @@ pub mod prelude {
12931293
"None",
12941294
);
12951295
}
1296+
1297+
#[test]
1298+
fn different_crate_renamed_through_dep() {
1299+
check_found_path(
1300+
r#"
1301+
//- /main.rs crate:main deps:intermediate
1302+
$0
1303+
//- /intermediate.rs crate:intermediate deps:std
1304+
pub extern crate std as std_renamed;
1305+
//- /std.rs crate:std
1306+
pub struct S;
1307+
"#,
1308+
"intermediate::std_renamed::S",
1309+
"intermediate::std_renamed::S",
1310+
"intermediate::std_renamed::S",
1311+
"intermediate::std_renamed::S",
1312+
);
1313+
}
12961314
}

crates/hir-def/src/import_map.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,22 +114,27 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap<ItemIn
114114

115115
for (name, per_ns) in visible_items {
116116
for item in per_ns.iter_items() {
117+
// FIXME: Not yet used, but will be once we handle doc(hidden) import sources
118+
let is_doc_hidden = false;
119+
117120
let import_info = ImportInfo {
118121
name: name.clone(),
119122
container: module,
120123
is_trait_assoc_item: false,
121124
};
122125

123126
match depth_map.entry(item) {
124-
Entry::Vacant(entry) => {
125-
entry.insert(depth);
126-
}
127+
Entry::Vacant(entry) => _ = entry.insert((depth, is_doc_hidden)),
127128
Entry::Occupied(mut entry) => {
128-
if depth < *entry.get() {
129-
entry.insert(depth);
130-
} else {
129+
let &(occ_depth, occ_is_doc_hidden) = entry.get();
130+
// Prefer the one that is not doc(hidden),
131+
// Otherwise, if both have the same doc(hidden)-ness and the new path is shorter, prefer that one.
132+
let overwrite_entry = occ_is_doc_hidden && !is_doc_hidden
133+
|| occ_is_doc_hidden == is_doc_hidden && depth < occ_depth;
134+
if !overwrite_entry {
131135
continue;
132136
}
137+
entry.insert((depth, is_doc_hidden));
133138
}
134139
}
135140

crates/hir-def/src/item_scope.rs

Lines changed: 93 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::collections::hash_map::Entry;
66
use base_db::CrateId;
77
use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId};
88
use itertools::Itertools;
9+
use la_arena::Idx;
910
use once_cell::sync::Lazy;
1011
use profile::Count;
1112
use rustc_hash::{FxHashMap, FxHashSet};
@@ -32,15 +33,50 @@ pub struct PerNsGlobImports {
3233
macros: FxHashSet<(LocalModuleId, Name)>,
3334
}
3435

36+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
37+
pub enum ImportOrExternCrate {
38+
Import(ImportId),
39+
Glob(UseId),
40+
ExternCrate(ExternCrateId),
41+
}
42+
43+
impl ImportOrExternCrate {
44+
pub fn into_import(self) -> Option<ImportId> {
45+
match self {
46+
ImportOrExternCrate::Import(it) => Some(it),
47+
_ => None,
48+
}
49+
}
50+
51+
pub fn into_glob(self) -> Option<UseId> {
52+
match self {
53+
ImportOrExternCrate::Glob(it) => Some(it),
54+
_ => None,
55+
}
56+
}
57+
}
58+
59+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
60+
pub enum ImportOrDef {
61+
Import(ImportId),
62+
ExternCrate(ExternCrateId),
63+
Def(ModuleDefId),
64+
}
65+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
66+
pub struct ImportId {
67+
pub import: UseId,
68+
pub idx: Idx<ast::UseTree>,
69+
}
70+
3571
#[derive(Debug, Default, PartialEq, Eq)]
3672
pub struct ItemScope {
3773
_c: Count<Self>,
3874

3975
/// Defs visible in this scope. This includes `declarations`, but also
4076
/// imports.
41-
types: FxHashMap<Name, (ModuleDefId, Visibility)>,
42-
values: FxHashMap<Name, (ModuleDefId, Visibility)>,
43-
macros: FxHashMap<Name, (MacroId, Visibility)>,
77+
types: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
78+
values: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportId>)>,
79+
macros: FxHashMap<Name, (MacroId, Visibility, Option<ImportId>)>,
4480
unresolved: FxHashSet<Name>,
4581

4682
/// The defs declared in this scope. Each def has a single scope where it is
@@ -50,7 +86,14 @@ pub struct ItemScope {
5086
impls: Vec<ImplId>,
5187
unnamed_consts: Vec<ConstId>,
5288
/// Traits imported via `use Trait as _;`.
53-
unnamed_trait_imports: FxHashMap<TraitId, Visibility>,
89+
unnamed_trait_imports: FxHashMap<TraitId, (Visibility, Option<ImportId>)>,
90+
91+
// the resolutions of the imports of this scope
92+
use_imports_types: FxHashMap<UseId, ImportOrDef>,
93+
use_imports_values: FxHashMap<UseId, ImportOrDef>,
94+
use_imports_macros: FxHashMap<UseId, ImportOrDef>,
95+
96+
use_decls: Vec<UseId>,
5497
extern_crate_decls: Vec<ExternCrateId>,
5598
/// Macros visible in current module in legacy textual scope
5699
///
@@ -121,8 +164,7 @@ impl ItemScope {
121164
}
122165

123166
pub fn use_decls(&self) -> impl Iterator<Item = UseId> + ExactSizeIterator + '_ {
124-
// FIXME: to be implemented
125-
std::iter::empty()
167+
self.use_decls.iter().copied()
126168
}
127169

128170
pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
@@ -132,13 +174,13 @@ impl ItemScope {
132174
pub fn values(
133175
&self,
134176
) -> impl Iterator<Item = (ModuleDefId, Visibility)> + ExactSizeIterator + '_ {
135-
self.values.values().copied()
177+
self.values.values().copied().map(|(a, b, _)| (a, b))
136178
}
137179

138-
pub fn types(
180+
pub(crate) fn types(
139181
&self,
140182
) -> impl Iterator<Item = (ModuleDefId, Visibility)> + ExactSizeIterator + '_ {
141-
self.types.values().copied()
183+
self.types.values().copied().map(|(def, vis, _)| (def, vis))
142184
}
143185

144186
pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ {
@@ -165,33 +207,48 @@ impl ItemScope {
165207
}
166208

167209
pub(crate) fn type_(&self, name: &Name) -> Option<(ModuleDefId, Visibility)> {
168-
self.types.get(name).copied()
210+
self.types.get(name).copied().map(|(a, b, _)| (a, b))
169211
}
170212

171213
/// XXX: this is O(N) rather than O(1), try to not introduce new usages.
172214
pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> {
173-
let (def, mut iter) = match item {
174-
ItemInNs::Macros(def) => {
175-
return self.macros.iter().find_map(|(name, &(other_def, vis))| {
176-
(other_def == def).then_some((name, vis))
177-
});
178-
}
179-
ItemInNs::Types(def) => (def, self.types.iter()),
180-
ItemInNs::Values(def) => (def, self.values.iter()),
181-
};
182-
iter.find_map(|(name, &(other_def, vis))| (other_def == def).then_some((name, vis)))
215+
match item {
216+
ItemInNs::Macros(def) => self
217+
.macros
218+
.iter()
219+
.find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
220+
ItemInNs::Types(def) => self
221+
.types
222+
.iter()
223+
.find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
224+
225+
ItemInNs::Values(def) => self
226+
.values
227+
.iter()
228+
.find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
229+
}
183230
}
184231

185232
pub(crate) fn traits(&self) -> impl Iterator<Item = TraitId> + '_ {
186233
self.types
187234
.values()
188-
.filter_map(|&(def, _)| match def {
235+
.filter_map(|&(def, _, _)| match def {
189236
ModuleDefId::TraitId(t) => Some(t),
190237
_ => None,
191238
})
192239
.chain(self.unnamed_trait_imports.keys().copied())
193240
}
194241

242+
pub(crate) fn resolutions(&self) -> impl Iterator<Item = (Option<Name>, PerNs)> + '_ {
243+
self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
244+
self.unnamed_trait_imports
245+
.iter()
246+
.map(|(tr, (vis, _))| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))),
247+
)
248+
}
249+
}
250+
251+
impl ItemScope {
195252
pub(crate) fn declare(&mut self, def: ModuleDefId) {
196253
self.declarations.push(def)
197254
}
@@ -278,11 +335,11 @@ impl ItemScope {
278335
}
279336

280337
pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {
281-
self.unnamed_trait_imports.get(&tr).copied()
338+
self.unnamed_trait_imports.get(&tr).copied().map(|(a, _)| a)
282339
}
283340

284341
pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) {
285-
self.unnamed_trait_imports.insert(tr, vis);
342+
self.unnamed_trait_imports.insert(tr, (vis, None));
286343
}
287344

288345
pub(crate) fn push_res_with_import(
@@ -343,27 +400,18 @@ impl ItemScope {
343400
changed
344401
}
345402

346-
pub(crate) fn resolutions(&self) -> impl Iterator<Item = (Option<Name>, PerNs)> + '_ {
347-
self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
348-
self.unnamed_trait_imports
349-
.iter()
350-
.map(|(tr, vis)| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))),
351-
)
352-
}
353-
354403
/// Marks everything that is not a procedural macro as private to `this_module`.
355404
pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) {
356405
self.types
357406
.values_mut()
358-
.chain(self.values.values_mut())
407+
.map(|(def, vis, _)| (def, vis))
408+
.chain(self.values.values_mut().map(|(def, vis, _)| (def, vis)))
359409
.map(|(_, v)| v)
360-
.chain(self.unnamed_trait_imports.values_mut())
410+
.chain(self.unnamed_trait_imports.values_mut().map(|(vis, _)| vis))
361411
.for_each(|vis| *vis = Visibility::Module(this_module));
362412

363-
for (mac, vis) in self.macros.values_mut() {
364-
if let MacroId::ProcMacroId(_) = mac {
365-
// FIXME: Technically this is insufficient since reexports of proc macros are also
366-
// forbidden. Practically nobody does that.
413+
for (mac, vis, import) in self.macros.values_mut() {
414+
if matches!(mac, MacroId::ProcMacroId(_) if import.is_none()) {
367415
continue;
368416
}
369417

@@ -415,10 +463,17 @@ impl ItemScope {
415463
attr_macros,
416464
derive_macros,
417465
extern_crate_decls,
466+
use_decls,
467+
use_imports_values,
468+
use_imports_types,
469+
use_imports_macros,
418470
} = self;
419471
types.shrink_to_fit();
420472
values.shrink_to_fit();
421473
macros.shrink_to_fit();
474+
use_imports_types.shrink_to_fit();
475+
use_imports_values.shrink_to_fit();
476+
use_imports_macros.shrink_to_fit();
422477
unresolved.shrink_to_fit();
423478
declarations.shrink_to_fit();
424479
impls.shrink_to_fit();
@@ -428,6 +483,7 @@ impl ItemScope {
428483
attr_macros.shrink_to_fit();
429484
derive_macros.shrink_to_fit();
430485
extern_crate_decls.shrink_to_fit();
486+
use_decls.shrink_to_fit();
431487
}
432488
}
433489

crates/hir-def/src/lib.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,7 @@ impl_from!(
865865
ConstId,
866866
FunctionId,
867867
TraitId,
868+
TraitAliasId,
868869
TypeAliasId,
869870
MacroId(Macro2Id, MacroRulesId, ProcMacroId),
870871
ImplId,
@@ -873,6 +874,26 @@ impl_from!(
873874
for AttrDefId
874875
);
875876

877+
impl TryFrom<ModuleDefId> for AttrDefId {
878+
type Error = ();
879+
880+
fn try_from(value: ModuleDefId) -> Result<Self, Self::Error> {
881+
match value {
882+
ModuleDefId::ModuleId(it) => Ok(it.into()),
883+
ModuleDefId::FunctionId(it) => Ok(it.into()),
884+
ModuleDefId::AdtId(it) => Ok(it.into()),
885+
ModuleDefId::EnumVariantId(it) => Ok(it.into()),
886+
ModuleDefId::ConstId(it) => Ok(it.into()),
887+
ModuleDefId::StaticId(it) => Ok(it.into()),
888+
ModuleDefId::TraitId(it) => Ok(it.into()),
889+
ModuleDefId::TypeAliasId(it) => Ok(it.into()),
890+
ModuleDefId::TraitAliasId(id) => Ok(id.into()),
891+
ModuleDefId::MacroId(id) => Ok(id.into()),
892+
ModuleDefId::BuiltinType(_) => Err(()),
893+
}
894+
}
895+
}
896+
876897
impl From<ItemContainerId> for AttrDefId {
877898
fn from(acid: ItemContainerId) -> Self {
878899
match acid {

crates/hir-def/src/nameres.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ pub struct DefMap {
108108
prelude: Option<(ModuleId, Option<UseId>)>,
109109
/// `macro_use` prelude that contains macros from `#[macro_use]`'d external crates. Note that
110110
/// this contains all kinds of macro, not just `macro_rules!` macro.
111+
/// ExternCrateId being None implies it being imported from the general prelude import.
111112
macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>,
112113

113114
/// Tracks which custom derives are in scope for an item, to allow resolution of derive helper

crates/hir-def/src/nameres/collector.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use crate::{
3333
attr_macro_as_call_id,
3434
db::DefDatabase,
3535
derive_macro_as_call_id,
36-
item_scope::{ImportType, PerNsGlobImports},
36+
item_scope::{ImportOrExternCrate, ImportType, PerNsGlobImports},
3737
item_tree::{
3838
self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
3939
MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
@@ -546,8 +546,8 @@ impl DefCollector<'_> {
546546
self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None);
547547

548548
match per_ns.types {
549-
Some((ModuleDefId::ModuleId(m), _)) => {
550-
self.def_map.prelude = Some((m, None));
549+
Some((ModuleDefId::ModuleId(m), _, import)) => {
550+
self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::into_glob)));
551551
}
552552
types => {
553553
tracing::debug!(
@@ -714,7 +714,6 @@ impl DefCollector<'_> {
714714
&mut self,
715715
krate: CrateId,
716716
names: Option<Vec<Name>>,
717-
718717
extern_crate: Option<ExternCrateId>,
719718
) {
720719
let def_map = self.db.crate_def_map(krate);

crates/hir-def/src/nameres/path_resolution.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl PerNs {
6565
db: &dyn DefDatabase,
6666
expected: Option<MacroSubNs>,
6767
) -> Self {
68-
self.macros = self.macros.filter(|&(id, _)| {
68+
self.macros = self.macros.filter(|&(id, _, _)| {
6969
let this = MacroSubNs::from_id(db, id);
7070
sub_namespace_match(Some(this), expected)
7171
});

crates/hir-def/src/nameres/tests/incremental.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ pub type Ty = ();
212212
}
213213

214214
for (_, res) in module_data.scope.resolutions() {
215-
match res.values.or(res.types).unwrap().0 {
215+
match res.values.map(|(a, _, _)| a).or(res.types.map(|(a, _, _)| a)).unwrap() {
216216
ModuleDefId::FunctionId(f) => _ = db.function_data(f),
217217
ModuleDefId::AdtId(adt) => match adt {
218218
AdtId::StructId(it) => _ = db.struct_data(it),

0 commit comments

Comments
 (0)