aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/attr.rs1
-rw-r--r--crates/hir_def/src/body.rs6
-rw-r--r--crates/hir_def/src/body/tests.rs41
-rw-r--r--crates/hir_def/src/db.rs17
-rw-r--r--crates/hir_def/src/find_path.rs22
-rw-r--r--crates/hir_def/src/import_map.rs68
-rw-r--r--crates/hir_def/src/item_tree.rs41
-rw-r--r--crates/hir_def/src/item_tree/lower.rs45
-rw-r--r--crates/hir_def/src/lang_item.rs2
-rw-r--r--crates/hir_def/src/nameres.rs150
-rw-r--r--crates/hir_def/src/nameres/collector.rs68
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs41
-rw-r--r--crates/hir_def/src/nameres/tests.rs22
-rw-r--r--crates/hir_def/src/nameres/tests/block.rs97
-rw-r--r--crates/hir_def/src/path.rs2
-rw-r--r--crates/hir_def/src/resolver.rs60
-rw-r--r--crates/hir_def/src/test_db.rs6
-rw-r--r--crates/hir_def/src/type_ref.rs2
-rw-r--r--crates/hir_def/src/visibility.rs6
19 files changed, 550 insertions, 147 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 1b09ff816..c72649c41 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -207,6 +207,7 @@ impl Attrs {
207 mod_data.definition_source(db).as_ref().map(|src| match src { 207 mod_data.definition_source(db).as_ref().map(|src| match src {
208 ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, 208 ModuleSource::SourceFile(file) => file as &dyn AttrsOwner,
209 ModuleSource::Module(module) => module as &dyn AttrsOwner, 209 ModuleSource::Module(module) => module as &dyn AttrsOwner,
210 ModuleSource::BlockExpr(block) => block as &dyn AttrsOwner,
210 }), 211 }),
211 ), 212 ),
212 } 213 }
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index 344f0b6c0..2c2c999dd 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -29,7 +29,7 @@ use crate::{
29 expr::{Expr, ExprId, Label, LabelId, Pat, PatId}, 29 expr::{Expr, ExprId, Label, LabelId, Pat, PatId},
30 item_scope::BuiltinShadowMode, 30 item_scope::BuiltinShadowMode,
31 item_scope::ItemScope, 31 item_scope::ItemScope,
32 nameres::CrateDefMap, 32 nameres::DefMap,
33 path::{ModPath, Path}, 33 path::{ModPath, Path},
34 src::HasSource, 34 src::HasSource,
35 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, 35 AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
@@ -45,7 +45,7 @@ pub(crate) struct CfgExpander {
45 45
46pub(crate) struct Expander { 46pub(crate) struct Expander {
47 cfg_expander: CfgExpander, 47 cfg_expander: CfgExpander,
48 crate_def_map: Arc<CrateDefMap>, 48 crate_def_map: Arc<DefMap>,
49 current_file_id: HirFileId, 49 current_file_id: HirFileId,
50 ast_id_map: Arc<AstIdMap>, 50 ast_id_map: Arc<AstIdMap>,
51 module: ModuleId, 51 module: ModuleId,
@@ -122,7 +122,7 @@ impl Expander {
122 122
123 let mut err = None; 123 let mut err = None;
124 let call_id = 124 let call_id =
125 macro_call.as_call_id_with_errors(db, self.crate_def_map.krate, resolver, &mut |e| { 125 macro_call.as_call_id_with_errors(db, self.crate_def_map.krate(), resolver, &mut |e| {
126 err.get_or_insert(e); 126 err.get_or_insert(e);
127 }); 127 });
128 let call_id = match call_id { 128 let call_id = match call_id {
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs
index de77d5fc9..2e5d0a01e 100644
--- a/crates/hir_def/src/body/tests.rs
+++ b/crates/hir_def/src/body/tests.rs
@@ -6,18 +6,24 @@ use crate::{test_db::TestDB, ModuleDefId};
6use super::*; 6use super::*;
7 7
8fn lower(ra_fixture: &str) -> Arc<Body> { 8fn lower(ra_fixture: &str) -> Arc<Body> {
9 let (db, file_id) = crate::test_db::TestDB::with_single_file(ra_fixture); 9 let db = crate::test_db::TestDB::with_files(ra_fixture);
10 10
11 let krate = db.crate_graph().iter().next().unwrap(); 11 let krate = db.crate_graph().iter().next().unwrap();
12 let def_map = db.crate_def_map(krate); 12 let def_map = db.crate_def_map(krate);
13 let module = def_map.modules_for_file(file_id).next().unwrap(); 13 let mut fn_def = None;
14 let module = &def_map[module]; 14 'outer: for (_, module) in def_map.modules() {
15 let fn_def = match module.scope.declarations().next().unwrap() { 15 for decl in module.scope.declarations() {
16 ModuleDefId::FunctionId(it) => it, 16 match decl {
17 _ => panic!(), 17 ModuleDefId::FunctionId(it) => {
18 }; 18 fn_def = Some(it);
19 break 'outer;
20 }
21 _ => {}
22 }
23 }
24 }
19 25
20 db.body(fn_def.into()) 26 db.body(fn_def.unwrap().into())
21} 27}
22 28
23fn check_diagnostics(ra_fixture: &str) { 29fn check_diagnostics(ra_fixture: &str) {
@@ -42,6 +48,25 @@ fn main() { n_nuple!(1,2,3); }
42} 48}
43 49
44#[test] 50#[test]
51fn macro_resolve() {
52 // Regression test for a path resolution bug introduced with inner item handling.
53 lower(
54 r"
55macro_rules! vec {
56 () => { () };
57 ($elem:expr; $n:expr) => { () };
58 ($($x:expr),+ $(,)?) => { () };
59}
60mod m {
61 fn outer() {
62 let _ = vec![FileSet::default(); self.len()];
63 }
64}
65 ",
66 );
67}
68
69#[test]
45fn cfg_diagnostics() { 70fn cfg_diagnostics() {
46 check_diagnostics( 71 check_diagnostics(
47 r" 72 r"
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs
index 6ef9fe790..a87c80b8a 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -2,9 +2,9 @@
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use base_db::{salsa, CrateId, SourceDatabase, Upcast}; 4use base_db::{salsa, CrateId, SourceDatabase, Upcast};
5use hir_expand::{db::AstDatabase, HirFileId}; 5use hir_expand::{db::AstDatabase, AstId, HirFileId};
6use la_arena::ArenaMap; 6use la_arena::ArenaMap;
7use syntax::SmolStr; 7use syntax::{ast, SmolStr};
8 8
9use crate::{ 9use crate::{
10 adt::{EnumData, StructData}, 10 adt::{EnumData, StructData},
@@ -15,7 +15,7 @@ use crate::{
15 import_map::ImportMap, 15 import_map::ImportMap,
16 item_tree::ItemTree, 16 item_tree::ItemTree,
17 lang_item::{LangItemTarget, LangItems}, 17 lang_item::{LangItemTarget, LangItems},
18 nameres::CrateDefMap, 18 nameres::DefMap,
19 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, 19 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc,
20 GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, StaticLoc, StructId, 20 GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, StaticLoc, StructId,
21 StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId, 21 StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId,
@@ -50,10 +50,13 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
50 50
51 #[salsa::invoke(crate_def_map_wait)] 51 #[salsa::invoke(crate_def_map_wait)]
52 #[salsa::transparent] 52 #[salsa::transparent]
53 fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>; 53 fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;
54 54
55 #[salsa::invoke(CrateDefMap::crate_def_map_query)] 55 #[salsa::invoke(DefMap::crate_def_map_query)]
56 fn crate_def_map_query(&self, krate: CrateId) -> Arc<CrateDefMap>; 56 fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>;
57
58 #[salsa::invoke(DefMap::block_def_map_query)]
59 fn block_def_map(&self, krate: CrateId, block: AstId<ast::BlockExpr>) -> Arc<DefMap>;
57 60
58 #[salsa::invoke(StructData::struct_data_query)] 61 #[salsa::invoke(StructData::struct_data_query)]
59 fn struct_data(&self, id: StructId) -> Arc<StructData>; 62 fn struct_data(&self, id: StructId) -> Arc<StructData>;
@@ -112,7 +115,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
112 fn import_map(&self, krate: CrateId) -> Arc<ImportMap>; 115 fn import_map(&self, krate: CrateId) -> Arc<ImportMap>;
113} 116}
114 117
115fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { 118fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<DefMap> {
116 let _p = profile::span("crate_def_map:wait"); 119 let _p = profile::span("crate_def_map:wait");
117 db.crate_def_map_query(krate) 120 db.crate_def_map_query(krate)
118} 121}
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index 4a212d291..db2d125ae 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -4,7 +4,7 @@ use hir_expand::name::{known, AsName, Name};
4use rustc_hash::FxHashSet; 4use rustc_hash::FxHashSet;
5use test_utils::mark; 5use test_utils::mark;
6 6
7use crate::nameres::CrateDefMap; 7use crate::nameres::DefMap;
8use crate::{ 8use crate::{
9 db::DefDatabase, 9 db::DefDatabase,
10 item_scope::ItemInNs, 10 item_scope::ItemInNs,
@@ -47,11 +47,11 @@ impl ModPath {
47 } 47 }
48} 48}
49 49
50fn check_self_super(def_map: &CrateDefMap, item: ItemInNs, from: ModuleId) -> Option<ModPath> { 50fn check_self_super(def_map: &DefMap, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
51 if item == ItemInNs::Types(from.into()) { 51 if item == ItemInNs::Types(from.into()) {
52 // - if the item is the module we're in, use `self` 52 // - if the item is the module we're in, use `self`
53 Some(ModPath::from_segments(PathKind::Super(0), Vec::new())) 53 Some(ModPath::from_segments(PathKind::Super(0), Vec::new()))
54 } else if let Some(parent_id) = def_map.modules[from.local_id].parent { 54 } else if let Some(parent_id) = def_map[from.local_id].parent {
55 // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly) 55 // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly)
56 if item 56 if item
57 == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { 57 == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId {
@@ -111,7 +111,7 @@ fn find_path_inner(
111 111
112 // - if the item is already in scope, return the name under which it is 112 // - if the item is already in scope, return the name under which it is
113 let def_map = db.crate_def_map(from.krate); 113 let def_map = db.crate_def_map(from.krate);
114 let from_scope: &crate::item_scope::ItemScope = &def_map.modules[from.local_id].scope; 114 let from_scope: &crate::item_scope::ItemScope = &def_map[from.local_id].scope;
115 let scope_name = 115 let scope_name =
116 if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None }; 116 if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None };
117 if prefixed.is_none() && scope_name.is_some() { 117 if prefixed.is_none() && scope_name.is_some() {
@@ -123,7 +123,7 @@ fn find_path_inner(
123 if item 123 if item
124 == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { 124 == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId {
125 krate: from.krate, 125 krate: from.krate,
126 local_id: def_map.root, 126 local_id: def_map.root(),
127 })) 127 }))
128 { 128 {
129 return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); 129 return Some(ModPath::from_segments(PathKind::Crate, Vec::new()));
@@ -136,7 +136,7 @@ fn find_path_inner(
136 } 136 }
137 137
138 // - if the item is the crate root of a dependency crate, return the name from the extern prelude 138 // - if the item is the crate root of a dependency crate, return the name from the extern prelude
139 for (name, def_id) in &def_map.extern_prelude { 139 for (name, def_id) in def_map.extern_prelude() {
140 if item == ItemInNs::Types(*def_id) { 140 if item == ItemInNs::Types(*def_id) {
141 let name = scope_name.unwrap_or_else(|| name.clone()); 141 let name = scope_name.unwrap_or_else(|| name.clone());
142 return Some(ModPath::from_segments(PathKind::Plain, vec![name])); 142 return Some(ModPath::from_segments(PathKind::Plain, vec![name]));
@@ -144,10 +144,10 @@ fn find_path_inner(
144 } 144 }
145 145
146 // - if the item is in the prelude, return the name from there 146 // - if the item is in the prelude, return the name from there
147 if let Some(prelude_module) = def_map.prelude { 147 if let Some(prelude_module) = def_map.prelude() {
148 let prelude_def_map = db.crate_def_map(prelude_module.krate); 148 let prelude_def_map = db.crate_def_map(prelude_module.krate);
149 let prelude_scope: &crate::item_scope::ItemScope = 149 let prelude_scope: &crate::item_scope::ItemScope =
150 &prelude_def_map.modules[prelude_module.local_id].scope; 150 &prelude_def_map[prelude_module.local_id].scope;
151 if let Some((name, vis)) = prelude_scope.name_of(item) { 151 if let Some((name, vis)) = prelude_scope.name_of(item) {
152 if vis.is_visible_from(db, from) { 152 if vis.is_visible_from(db, from) {
153 return Some(ModPath::from_segments(PathKind::Plain, vec![name.clone()])); 153 return Some(ModPath::from_segments(PathKind::Plain, vec![name.clone()]));
@@ -175,7 +175,7 @@ fn find_path_inner(
175 175
176 // - otherwise, look for modules containing (reexporting) it and import it from one of those 176 // - otherwise, look for modules containing (reexporting) it and import it from one of those
177 177
178 let crate_root = ModuleId { local_id: def_map.root, krate: from.krate }; 178 let crate_root = ModuleId { local_id: def_map.root(), krate: from.krate };
179 let crate_attrs = db.attrs(crate_root.into()); 179 let crate_attrs = db.attrs(crate_root.into());
180 let prefer_no_std = crate_attrs.by_key("no_std").exists(); 180 let prefer_no_std = crate_attrs.by_key("no_std").exists();
181 let mut best_path = None; 181 let mut best_path = None;
@@ -287,7 +287,7 @@ fn find_local_import_locations(
287 287
288 // Compute the initial worklist. We start with all direct child modules of `from` as well as all 288 // Compute the initial worklist. We start with all direct child modules of `from` as well as all
289 // of its (recursive) parent modules. 289 // of its (recursive) parent modules.
290 let data = &def_map.modules[from.local_id]; 290 let data = &def_map[from.local_id];
291 let mut worklist = data 291 let mut worklist = data
292 .children 292 .children
293 .values() 293 .values()
@@ -296,7 +296,7 @@ fn find_local_import_locations(
296 let mut parent = data.parent; 296 let mut parent = data.parent;
297 while let Some(p) = parent { 297 while let Some(p) = parent {
298 worklist.push(ModuleId { krate: from.krate, local_id: p }); 298 worklist.push(ModuleId { krate: from.krate, local_id: p });
299 parent = def_map.modules[p].parent; 299 parent = def_map[p].parent;
300 } 300 }
301 301
302 let mut seen: FxHashSet<_> = FxHashSet::default(); 302 let mut seen: FxHashSet<_> = FxHashSet::default();
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs
index e5368b293..0251d016b 100644
--- a/crates/hir_def/src/import_map.rs
+++ b/crates/hir_def/src/import_map.rs
@@ -75,7 +75,7 @@ impl ImportMap {
75 75
76 // We look only into modules that are public(ly reexported), starting with the crate root. 76 // We look only into modules that are public(ly reexported), starting with the crate root.
77 let empty = ImportPath { segments: vec![] }; 77 let empty = ImportPath { segments: vec![] };
78 let root = ModuleId { krate, local_id: def_map.root }; 78 let root = ModuleId { krate, local_id: def_map.root() };
79 let mut worklist = vec![(root, empty)]; 79 let mut worklist = vec![(root, empty)];
80 while let Some((module, mod_path)) = worklist.pop() { 80 while let Some((module, mod_path)) = worklist.pop() {
81 let ext_def_map; 81 let ext_def_map;
@@ -263,6 +263,7 @@ pub enum ImportKind {
263 Trait, 263 Trait,
264 TypeAlias, 264 TypeAlias,
265 BuiltinType, 265 BuiltinType,
266 AssociatedItem,
266} 267}
267 268
268/// A way to match import map contents against the search query. 269/// A way to match import map contents against the search query.
@@ -282,6 +283,7 @@ pub struct Query {
282 query: String, 283 query: String,
283 lowercased: String, 284 lowercased: String,
284 name_only: bool, 285 name_only: bool,
286 assoc_items_only: bool,
285 search_mode: SearchMode, 287 search_mode: SearchMode,
286 case_sensitive: bool, 288 case_sensitive: bool,
287 limit: usize, 289 limit: usize,
@@ -295,6 +297,7 @@ impl Query {
295 query, 297 query,
296 lowercased, 298 lowercased,
297 name_only: false, 299 name_only: false,
300 assoc_items_only: false,
298 search_mode: SearchMode::Contains, 301 search_mode: SearchMode::Contains,
299 case_sensitive: false, 302 case_sensitive: false,
300 limit: usize::max_value(), 303 limit: usize::max_value(),
@@ -309,6 +312,11 @@ impl Query {
309 Self { name_only: true, ..self } 312 Self { name_only: true, ..self }
310 } 313 }
311 314
315 /// Matches only the entries that are associated items, ignoring the rest.
316 pub fn assoc_items_only(self) -> Self {
317 Self { assoc_items_only: true, ..self }
318 }
319
312 /// Specifies the way to search for the entries using the query. 320 /// Specifies the way to search for the entries using the query.
313 pub fn search_mode(self, search_mode: SearchMode) -> Self { 321 pub fn search_mode(self, search_mode: SearchMode) -> Self {
314 Self { search_mode, ..self } 322 Self { search_mode, ..self }
@@ -331,6 +339,14 @@ impl Query {
331 } 339 }
332 340
333 fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { 341 fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool {
342 if import.is_trait_assoc_item {
343 if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) {
344 return false;
345 }
346 } else if self.assoc_items_only {
347 return false;
348 }
349
334 let mut input = if import.is_trait_assoc_item || self.name_only { 350 let mut input = if import.is_trait_assoc_item || self.name_only {
335 import.path.segments.last().unwrap().to_string() 351 import.path.segments.last().unwrap().to_string()
336 } else { 352 } else {
@@ -814,6 +830,56 @@ mod tests {
814 } 830 }
815 831
816 #[test] 832 #[test]
833 fn assoc_items_filtering() {
834 let ra_fixture = r#"
835 //- /main.rs crate:main deps:dep
836 //- /dep.rs crate:dep
837 pub mod fmt {
838 pub trait Display {
839 type FmtTypeAlias;
840 const FMT_CONST: bool;
841
842 fn format_function();
843 fn format_method(&self);
844 }
845 }
846 "#;
847
848 check_search(
849 ra_fixture,
850 "main",
851 Query::new("fmt".to_string()).search_mode(SearchMode::Fuzzy).assoc_items_only(),
852 expect![[r#"
853 dep::fmt::Display::FMT_CONST (a)
854 dep::fmt::Display::format_function (a)
855 dep::fmt::Display::format_method (a)
856 "#]],
857 );
858
859 check_search(
860 ra_fixture,
861 "main",
862 Query::new("fmt".to_string())
863 .search_mode(SearchMode::Fuzzy)
864 .exclude_import_kind(ImportKind::AssociatedItem),
865 expect![[r#"
866 dep::fmt (t)
867 dep::fmt::Display (t)
868 "#]],
869 );
870
871 check_search(
872 ra_fixture,
873 "main",
874 Query::new("fmt".to_string())
875 .search_mode(SearchMode::Fuzzy)
876 .assoc_items_only()
877 .exclude_import_kind(ImportKind::AssociatedItem),
878 expect![[r#""#]],
879 );
880 }
881
882 #[test]
817 fn search_mode() { 883 fn search_mode() {
818 let ra_fixture = r#" 884 let ra_fixture = r#"
819 //- /main.rs crate:main deps:dep 885 //- /main.rs crate:main deps:dep
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 9a433b61c..b8d7608e7 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -21,6 +21,7 @@ use hir_expand::{
21 HirFileId, InFile, 21 HirFileId, InFile,
22}; 22};
23use la_arena::{Arena, Idx, RawIdx}; 23use la_arena::{Arena, Idx, RawIdx};
24use profile::Count;
24use rustc_hash::FxHashMap; 25use rustc_hash::FxHashMap;
25use smallvec::SmallVec; 26use smallvec::SmallVec;
26use syntax::{ast, match_ast}; 27use syntax::{ast, match_ast};
@@ -67,15 +68,16 @@ impl GenericParamsId {
67/// The item tree of a source file. 68/// The item tree of a source file.
68#[derive(Debug, Eq, PartialEq)] 69#[derive(Debug, Eq, PartialEq)]
69pub struct ItemTree { 70pub struct ItemTree {
71 _c: Count<Self>,
72
70 top_level: SmallVec<[ModItem; 1]>, 73 top_level: SmallVec<[ModItem; 1]>,
71 attrs: FxHashMap<AttrOwner, RawAttrs>, 74 attrs: FxHashMap<AttrOwner, RawAttrs>,
72 inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>,
73 75
74 data: Option<Box<ItemTreeData>>, 76 data: Option<Box<ItemTreeData>>,
75} 77}
76 78
77impl ItemTree { 79impl ItemTree {
78 pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> { 80 pub(crate) fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
79 let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id)); 81 let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id));
80 let syntax = if let Some(node) = db.parse_or_expand(file_id) { 82 let syntax = if let Some(node) = db.parse_or_expand(file_id) {
81 node 83 node
@@ -118,9 +120,9 @@ impl ItemTree {
118 120
119 fn empty() -> Self { 121 fn empty() -> Self {
120 Self { 122 Self {
123 _c: Count::new(),
121 top_level: Default::default(), 124 top_level: Default::default(),
122 attrs: Default::default(), 125 attrs: Default::default(),
123 inner_items: Default::default(),
124 data: Default::default(), 126 data: Default::default(),
125 } 127 }
126 } 128 }
@@ -145,9 +147,9 @@ impl ItemTree {
145 macro_calls, 147 macro_calls,
146 macro_rules, 148 macro_rules,
147 macro_defs, 149 macro_defs,
148 exprs,
149 vis, 150 vis,
150 generics, 151 generics,
152 inner_items,
151 } = &mut **data; 153 } = &mut **data;
152 154
153 imports.shrink_to_fit(); 155 imports.shrink_to_fit();
@@ -167,10 +169,11 @@ impl ItemTree {
167 macro_calls.shrink_to_fit(); 169 macro_calls.shrink_to_fit();
168 macro_rules.shrink_to_fit(); 170 macro_rules.shrink_to_fit();
169 macro_defs.shrink_to_fit(); 171 macro_defs.shrink_to_fit();
170 exprs.shrink_to_fit();
171 172
172 vis.arena.shrink_to_fit(); 173 vis.arena.shrink_to_fit();
173 generics.arena.shrink_to_fit(); 174 generics.arena.shrink_to_fit();
175
176 inner_items.shrink_to_fit();
174 } 177 }
175 } 178 }
176 179
@@ -193,16 +196,18 @@ impl ItemTree {
193 self.raw_attrs(of).clone().filter(db, krate) 196 self.raw_attrs(of).clone().filter(db, krate)
194 } 197 }
195 198
196 /// Returns the lowered inner items that `ast` corresponds to. 199 pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ {
197 /// 200 match &self.data {
198 /// Most AST items are lowered to a single `ModItem`, but some (eg. `use` items) may be lowered 201 Some(data) => Some(data.inner_items.values().flatten().copied()).into_iter().flatten(),
199 /// to multiple items in the `ItemTree`. 202 None => None.into_iter().flatten(),
200 pub fn inner_items(&self, ast: FileAstId<ast::Item>) -> &[ModItem] { 203 }
201 &self.inner_items[&ast]
202 } 204 }
203 205
204 pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ { 206 pub fn inner_items_of_block(&self, block: FileAstId<ast::BlockExpr>) -> &[ModItem] {
205 self.inner_items.values().flatten().copied() 207 match &self.data {
208 Some(data) => data.inner_items.get(&block).map(|it| &**it).unwrap_or(&[]),
209 None => &[],
210 }
206 } 211 }
207 212
208 pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { 213 pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source {
@@ -296,10 +301,11 @@ struct ItemTreeData {
296 macro_calls: Arena<MacroCall>, 301 macro_calls: Arena<MacroCall>,
297 macro_rules: Arena<MacroRules>, 302 macro_rules: Arena<MacroRules>,
298 macro_defs: Arena<MacroDef>, 303 macro_defs: Arena<MacroDef>,
299 exprs: Arena<Expr>,
300 304
301 vis: ItemVisibilities, 305 vis: ItemVisibilities,
302 generics: GenericParamsStorage, 306 generics: GenericParamsStorage,
307
308 inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
303} 309}
304 310
305#[derive(Debug, Eq, PartialEq, Hash)] 311#[derive(Debug, Eq, PartialEq, Hash)]
@@ -461,7 +467,7 @@ macro_rules! impl_index {
461 }; 467 };
462} 468}
463 469
464impl_index!(fields: Field, variants: Variant, exprs: Expr); 470impl_index!(fields: Field, variants: Variant);
465 471
466impl Index<RawVisibilityId> for ItemTree { 472impl Index<RawVisibilityId> for ItemTree {
467 type Output = RawVisibility; 473 type Output = RawVisibility;
@@ -664,11 +670,6 @@ pub struct MacroDef {
664 pub ast_id: FileAstId<ast::MacroDef>, 670 pub ast_id: FileAstId<ast::MacroDef>,
665} 671}
666 672
667// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
668// lengths, but we don't do much with them yet.
669#[derive(Debug, Clone, Eq, PartialEq)]
670pub struct Expr;
671
672macro_rules! impl_froms { 673macro_rules! impl_froms {
673 ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => { 674 ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => {
674 $( 675 $(
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 5e71ca42c..ce470fc3b 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -6,7 +6,7 @@ use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId}
6use smallvec::SmallVec; 6use smallvec::SmallVec;
7use syntax::{ 7use syntax::{
8 ast::{self, ModuleItemOwner}, 8 ast::{self, ModuleItemOwner},
9 SyntaxNode, 9 SyntaxNode, WalkEvent,
10}; 10};
11 11
12use crate::{ 12use crate::{
@@ -37,7 +37,6 @@ pub(super) struct Ctx {
37 file: HirFileId, 37 file: HirFileId,
38 source_ast_id_map: Arc<AstIdMap>, 38 source_ast_id_map: Arc<AstIdMap>,
39 body_ctx: crate::body::LowerCtx, 39 body_ctx: crate::body::LowerCtx,
40 inner_items: Vec<ModItem>,
41 forced_visibility: Option<RawVisibilityId>, 40 forced_visibility: Option<RawVisibilityId>,
42} 41}
43 42
@@ -49,7 +48,6 @@ impl Ctx {
49 file, 48 file,
50 source_ast_id_map: db.ast_id_map(file), 49 source_ast_id_map: db.ast_id_map(file),
51 body_ctx: crate::body::LowerCtx::new(db, file), 50 body_ctx: crate::body::LowerCtx::new(db, file),
52 inner_items: Vec::new(),
53 forced_visibility: None, 51 forced_visibility: None,
54 } 52 }
55 } 53 }
@@ -73,8 +71,6 @@ impl Ctx {
73 } 71 }
74 72
75 fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> { 73 fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> {
76 assert!(inner || self.inner_items.is_empty());
77
78 // Collect inner items for 1-to-1-lowered items. 74 // Collect inner items for 1-to-1-lowered items.
79 match item { 75 match item {
80 ast::Item::Struct(_) 76 ast::Item::Struct(_)
@@ -150,14 +146,37 @@ impl Ctx {
150 146
151 fn collect_inner_items(&mut self, container: &SyntaxNode) { 147 fn collect_inner_items(&mut self, container: &SyntaxNode) {
152 let forced_vis = self.forced_visibility.take(); 148 let forced_vis = self.forced_visibility.take();
153 let mut inner_items = mem::take(&mut self.tree.inner_items); 149
154 inner_items.extend(container.descendants().skip(1).filter_map(ast::Item::cast).filter_map( 150 let mut block_stack = Vec::new();
155 |item| { 151 for event in container.preorder().skip(1) {
156 let ast_id = self.source_ast_id_map.ast_id(&item); 152 match event {
157 Some((ast_id, self.lower_mod_item(&item, true)?.0)) 153 WalkEvent::Enter(node) => {
158 }, 154 match_ast! {
159 )); 155 match node {
160 self.tree.inner_items = inner_items; 156 ast::BlockExpr(block) => {
157 block_stack.push(self.source_ast_id_map.ast_id(&block));
158 },
159 ast::Item(item) => {
160 let mod_items = self.lower_mod_item(&item, true);
161 let current_block = block_stack.last();
162 if let (Some(mod_items), Some(block)) = (mod_items, current_block) {
163 if !mod_items.0.is_empty() {
164 self.data().inner_items.entry(*block).or_default().extend(mod_items.0.iter().copied());
165 }
166 }
167 },
168 _ => {}
169 }
170 }
171 }
172 WalkEvent::Leave(node) => {
173 if ast::BlockExpr::cast(node).is_some() {
174 block_stack.pop();
175 }
176 }
177 }
178 }
179
161 self.forced_visibility = forced_vis; 180 self.forced_visibility = forced_vis;
162 } 181 }
163 182
diff --git a/crates/hir_def/src/lang_item.rs b/crates/hir_def/src/lang_item.rs
index 30188b740..9e90f745c 100644
--- a/crates/hir_def/src/lang_item.rs
+++ b/crates/hir_def/src/lang_item.rs
@@ -84,7 +84,7 @@ impl LangItems {
84 84
85 let crate_def_map = db.crate_def_map(krate); 85 let crate_def_map = db.crate_def_map(krate);
86 86
87 for (_, module_data) in crate_def_map.modules.iter() { 87 for (_, module_data) in crate_def_map.modules() {
88 for impl_def in module_data.scope.impls() { 88 for impl_def in module_data.scope.impls() {
89 lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId) 89 lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDefId)
90 } 90 }
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 50acc3f54..bd3ea9b8b 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -59,9 +59,10 @@ use std::sync::Arc;
59use base_db::{CrateId, Edition, FileId}; 59use base_db::{CrateId, Edition, FileId};
60use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; 60use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile};
61use la_arena::Arena; 61use la_arena::Arena;
62use profile::Count;
62use rustc_hash::FxHashMap; 63use rustc_hash::FxHashMap;
63use stdx::format_to; 64use stdx::format_to;
64use syntax::ast; 65use syntax::{ast, AstNode};
65 66
66use crate::{ 67use crate::{
67 db::DefDatabase, 68 db::DefDatabase,
@@ -74,21 +75,23 @@ use crate::{
74 75
75/// Contains all top-level defs from a macro-expanded crate 76/// Contains all top-level defs from a macro-expanded crate
76#[derive(Debug, PartialEq, Eq)] 77#[derive(Debug, PartialEq, Eq)]
77pub struct CrateDefMap { 78pub struct DefMap {
78 pub root: LocalModuleId, 79 _c: Count<Self>,
79 pub modules: Arena<ModuleData>, 80 parent: Option<Arc<DefMap>>,
80 pub(crate) krate: CrateId, 81 root: LocalModuleId,
82 modules: Arena<ModuleData>,
83 krate: CrateId,
81 /// The prelude module for this crate. This either comes from an import 84 /// The prelude module for this crate. This either comes from an import
82 /// marked with the `prelude_import` attribute, or (in the normal case) from 85 /// marked with the `prelude_import` attribute, or (in the normal case) from
83 /// a dependency (`std` or `core`). 86 /// a dependency (`std` or `core`).
84 pub(crate) prelude: Option<ModuleId>, 87 prelude: Option<ModuleId>,
85 pub(crate) extern_prelude: FxHashMap<Name, ModuleDefId>, 88 extern_prelude: FxHashMap<Name, ModuleDefId>,
86 89
87 edition: Edition, 90 edition: Edition,
88 diagnostics: Vec<DefDiagnostic>, 91 diagnostics: Vec<DefDiagnostic>,
89} 92}
90 93
91impl std::ops::Index<LocalModuleId> for CrateDefMap { 94impl std::ops::Index<LocalModuleId> for DefMap {
92 type Output = ModuleData; 95 type Output = ModuleData;
93 fn index(&self, id: LocalModuleId) -> &ModuleData { 96 fn index(&self, id: LocalModuleId) -> &ModuleData {
94 &self.modules[id] 97 &self.modules[id]
@@ -109,6 +112,10 @@ pub enum ModuleOrigin {
109 Inline { 112 Inline {
110 definition: AstId<ast::Module>, 113 definition: AstId<ast::Module>,
111 }, 114 },
115 /// Pseudo-module introduced by a block scope (contains only inner items).
116 BlockExpr {
117 block: AstId<ast::BlockExpr>,
118 },
112} 119}
113 120
114impl Default for ModuleOrigin { 121impl Default for ModuleOrigin {
@@ -122,7 +129,7 @@ impl ModuleOrigin {
122 match self { 129 match self {
123 ModuleOrigin::File { declaration: module, .. } 130 ModuleOrigin::File { declaration: module, .. }
124 | ModuleOrigin::Inline { definition: module, .. } => Some(*module), 131 | ModuleOrigin::Inline { definition: module, .. } => Some(*module),
125 ModuleOrigin::CrateRoot { .. } => None, 132 ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None,
126 } 133 }
127 } 134 }
128 135
@@ -137,7 +144,7 @@ impl ModuleOrigin {
137 144
138 pub fn is_inline(&self) -> bool { 145 pub fn is_inline(&self) -> bool {
139 match self { 146 match self {
140 ModuleOrigin::Inline { .. } => true, 147 ModuleOrigin::Inline { .. } | ModuleOrigin::BlockExpr { .. } => true,
141 ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false, 148 ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false,
142 } 149 }
143 } 150 }
@@ -155,6 +162,9 @@ impl ModuleOrigin {
155 definition.file_id, 162 definition.file_id,
156 ModuleSource::Module(definition.to_node(db.upcast())), 163 ModuleSource::Module(definition.to_node(db.upcast())),
157 ), 164 ),
165 ModuleOrigin::BlockExpr { block } => {
166 InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db.upcast())))
167 }
158 } 168 }
159 } 169 }
160} 170}
@@ -169,29 +179,56 @@ pub struct ModuleData {
169 pub origin: ModuleOrigin, 179 pub origin: ModuleOrigin,
170} 180}
171 181
172impl CrateDefMap { 182impl DefMap {
173 pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { 183 pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
174 let _p = profile::span("crate_def_map_query").detail(|| { 184 let _p = profile::span("crate_def_map_query").detail(|| {
175 db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string() 185 db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string()
176 }); 186 });
177 let def_map = { 187 let edition = db.crate_graph()[krate].edition;
178 let edition = db.crate_graph()[krate].edition; 188 let def_map = DefMap::empty(krate, edition);
179 let mut modules: Arena<ModuleData> = Arena::default(); 189 let def_map = collector::collect_defs(db, def_map, None);
180 let root = modules.alloc(ModuleData::default());
181 CrateDefMap {
182 krate,
183 edition,
184 extern_prelude: FxHashMap::default(),
185 prelude: None,
186 root,
187 modules,
188 diagnostics: Vec::new(),
189 }
190 };
191 let def_map = collector::collect_defs(db, def_map);
192 Arc::new(def_map) 190 Arc::new(def_map)
193 } 191 }
194 192
193 pub(crate) fn block_def_map_query(
194 db: &dyn DefDatabase,
195 krate: CrateId,
196 block: AstId<ast::BlockExpr>,
197 ) -> Arc<DefMap> {
198 let item_tree = db.item_tree(block.file_id);
199 let block_items = item_tree.inner_items_of_block(block.value);
200
201 let parent = parent_def_map(db, krate, block);
202
203 if block_items.is_empty() {
204 // If there are no inner items, nothing new is brought into scope, so we can just return
205 // the parent DefMap. This keeps DefMap parent chains short.
206 return parent;
207 }
208
209 let mut def_map = DefMap::empty(krate, parent.edition);
210 def_map.parent = Some(parent);
211
212 let def_map = collector::collect_defs(db, def_map, Some(block.value));
213 Arc::new(def_map)
214 }
215
216 fn empty(krate: CrateId, edition: Edition) -> DefMap {
217 let mut modules: Arena<ModuleData> = Arena::default();
218 let root = modules.alloc(ModuleData::default());
219 DefMap {
220 _c: Count::new(),
221 parent: None,
222 krate,
223 edition,
224 extern_prelude: FxHashMap::default(),
225 prelude: None,
226 root,
227 modules,
228 diagnostics: Vec::new(),
229 }
230 }
231
195 pub fn add_diagnostics( 232 pub fn add_diagnostics(
196 &self, 233 &self,
197 db: &dyn DefDatabase, 234 db: &dyn DefDatabase,
@@ -208,6 +245,26 @@ impl CrateDefMap {
208 .map(|(id, _data)| id) 245 .map(|(id, _data)| id)
209 } 246 }
210 247
248 pub fn modules(&self) -> impl Iterator<Item = (LocalModuleId, &ModuleData)> + '_ {
249 self.modules.iter()
250 }
251
252 pub fn root(&self) -> LocalModuleId {
253 self.root
254 }
255
256 pub(crate) fn krate(&self) -> CrateId {
257 self.krate
258 }
259
260 pub(crate) fn prelude(&self) -> Option<ModuleId> {
261 self.prelude
262 }
263
264 pub(crate) fn extern_prelude(&self) -> impl Iterator<Item = (&Name, &ModuleDefId)> + '_ {
265 self.extern_prelude.iter()
266 }
267
211 pub(crate) fn resolve_path( 268 pub(crate) fn resolve_path(
212 &self, 269 &self,
213 db: &dyn DefDatabase, 270 db: &dyn DefDatabase,
@@ -224,10 +281,15 @@ impl CrateDefMap {
224 // even), as this should be a great debugging aid. 281 // even), as this should be a great debugging aid.
225 pub fn dump(&self) -> String { 282 pub fn dump(&self) -> String {
226 let mut buf = String::new(); 283 let mut buf = String::new();
227 go(&mut buf, self, "crate", self.root); 284 let mut current_map = self;
285 while let Some(parent) = &current_map.parent {
286 go(&mut buf, current_map, "block scope", current_map.root);
287 current_map = &**parent;
288 }
289 go(&mut buf, current_map, "crate", current_map.root);
228 return buf; 290 return buf;
229 291
230 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) { 292 fn go(buf: &mut String, map: &DefMap, path: &str, module: LocalModuleId) {
231 format_to!(buf, "{}\n", path); 293 format_to!(buf, "{}\n", path);
232 294
233 let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect(); 295 let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect();
@@ -276,10 +338,40 @@ impl ModuleData {
276 } 338 }
277} 339}
278 340
341fn parent_def_map(
342 db: &dyn DefDatabase,
343 krate: CrateId,
344 block: AstId<ast::BlockExpr>,
345) -> Arc<DefMap> {
346 // FIXME: store this info in the item tree instead of reparsing here
347 let ast_id_map = db.ast_id_map(block.file_id);
348 let block_ptr = ast_id_map.get(block.value);
349 let root = match db.parse_or_expand(block.file_id) {
350 Some(it) => it,
351 None => {
352 return Arc::new(DefMap::empty(krate, Edition::Edition2018));
353 }
354 };
355 let ast = block_ptr.to_node(&root);
356
357 for ancestor in ast.syntax().ancestors().skip(1) {
358 if let Some(block_expr) = ast::BlockExpr::cast(ancestor) {
359 let ancestor_id = ast_id_map.ast_id(&block_expr);
360 let ast_id = InFile::new(block.file_id, ancestor_id);
361 let parent_map = db.block_def_map(krate, ast_id);
362 return parent_map;
363 }
364 }
365
366 // No enclosing block scope, so the parent is the crate-level DefMap.
367 db.crate_def_map(krate)
368}
369
279#[derive(Debug, Clone, PartialEq, Eq)] 370#[derive(Debug, Clone, PartialEq, Eq)]
280pub enum ModuleSource { 371pub enum ModuleSource {
281 SourceFile(ast::SourceFile), 372 SourceFile(ast::SourceFile),
282 Module(ast::Module), 373 Module(ast::Module),
374 BlockExpr(ast::BlockExpr),
283} 375}
284 376
285mod diagnostics { 377mod diagnostics {
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 0cd61698c..cd68efbe6 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -31,7 +31,7 @@ use crate::{
31 }, 31 },
32 nameres::{ 32 nameres::{
33 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, 33 diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
34 BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, 34 BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode,
35 }, 35 },
36 path::{ImportAlias, ModPath, PathKind}, 36 path::{ImportAlias, ModPath, PathKind},
37 per_ns::PerNs, 37 per_ns::PerNs,
@@ -45,7 +45,11 @@ const GLOB_RECURSION_LIMIT: usize = 100;
45const EXPANSION_DEPTH_LIMIT: usize = 128; 45const EXPANSION_DEPTH_LIMIT: usize = 128;
46const FIXED_POINT_LIMIT: usize = 8192; 46const FIXED_POINT_LIMIT: usize = 8192;
47 47
48pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { 48pub(super) fn collect_defs(
49 db: &dyn DefDatabase,
50 mut def_map: DefMap,
51 block: Option<FileAstId<ast::BlockExpr>>,
52) -> DefMap {
49 let crate_graph = db.crate_graph(); 53 let crate_graph = db.crate_graph();
50 54
51 // populate external prelude 55 // populate external prelude
@@ -93,6 +97,14 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
93 exports_proc_macros: false, 97 exports_proc_macros: false,
94 from_glob_import: Default::default(), 98 from_glob_import: Default::default(),
95 }; 99 };
100 match block {
101 Some(block) => {
102 collector.seed_with_inner(block);
103 }
104 None => {
105 collector.seed_with_top_level();
106 }
107 }
96 collector.collect(); 108 collector.collect();
97 collector.finish() 109 collector.finish()
98} 110}
@@ -210,7 +222,7 @@ struct DefData<'a> {
210/// Walks the tree of module recursively 222/// Walks the tree of module recursively
211struct DefCollector<'a> { 223struct DefCollector<'a> {
212 db: &'a dyn DefDatabase, 224 db: &'a dyn DefDatabase,
213 def_map: CrateDefMap, 225 def_map: DefMap,
214 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>, 226 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
215 unresolved_imports: Vec<ImportDirective>, 227 unresolved_imports: Vec<ImportDirective>,
216 resolved_imports: Vec<ImportDirective>, 228 resolved_imports: Vec<ImportDirective>,
@@ -228,7 +240,7 @@ struct DefCollector<'a> {
228} 240}
229 241
230impl DefCollector<'_> { 242impl DefCollector<'_> {
231 fn collect(&mut self) { 243 fn seed_with_top_level(&mut self) {
232 let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; 244 let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id;
233 let item_tree = self.db.item_tree(file_id.into()); 245 let item_tree = self.db.item_tree(file_id.into());
234 let module_id = self.def_map.root; 246 let module_id = self.def_map.root;
@@ -248,7 +260,31 @@ impl DefCollector<'_> {
248 } 260 }
249 .collect(item_tree.top_level_items()); 261 .collect(item_tree.top_level_items());
250 } 262 }
263 }
264
265 fn seed_with_inner(&mut self, block: FileAstId<ast::BlockExpr>) {
266 let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id;
267 let item_tree = self.db.item_tree(file_id.into());
268 let module_id = self.def_map.root;
269 self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
270 if item_tree
271 .top_level_attrs(self.db, self.def_map.krate)
272 .cfg()
273 .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false))
274 {
275 ModCollector {
276 def_collector: &mut *self,
277 macro_depth: 0,
278 module_id,
279 file_id: file_id.into(),
280 item_tree: &item_tree,
281 mod_dir: ModDir::root(),
282 }
283 .collect(item_tree.inner_items_of_block(block));
284 }
285 }
251 286
287 fn collect(&mut self) {
252 // main name resolution fixed-point loop. 288 // main name resolution fixed-point loop.
253 let mut i = 0; 289 let mut i = 0;
254 loop { 290 loop {
@@ -859,7 +895,7 @@ impl DefCollector<'_> {
859 .collect(item_tree.top_level_items()); 895 .collect(item_tree.top_level_items());
860 } 896 }
861 897
862 fn finish(mut self) -> CrateDefMap { 898 fn finish(mut self) -> DefMap {
863 // Emit diagnostics for all remaining unexpanded macros. 899 // Emit diagnostics for all remaining unexpanded macros.
864 900
865 for directive in &self.unexpanded_macros { 901 for directive in &self.unexpanded_macros {
@@ -1470,11 +1506,10 @@ impl ModCollector<'_, '_> {
1470mod tests { 1506mod tests {
1471 use crate::{db::DefDatabase, test_db::TestDB}; 1507 use crate::{db::DefDatabase, test_db::TestDB};
1472 use base_db::{fixture::WithFixture, SourceDatabase}; 1508 use base_db::{fixture::WithFixture, SourceDatabase};
1473 use la_arena::Arena;
1474 1509
1475 use super::*; 1510 use super::*;
1476 1511
1477 fn do_collect_defs(db: &dyn DefDatabase, def_map: CrateDefMap) -> CrateDefMap { 1512 fn do_collect_defs(db: &dyn DefDatabase, def_map: DefMap) -> DefMap {
1478 let mut collector = DefCollector { 1513 let mut collector = DefCollector {
1479 db, 1514 db,
1480 def_map, 1515 def_map,
@@ -1489,28 +1524,17 @@ mod tests {
1489 exports_proc_macros: false, 1524 exports_proc_macros: false,
1490 from_glob_import: Default::default(), 1525 from_glob_import: Default::default(),
1491 }; 1526 };
1527 collector.seed_with_top_level();
1492 collector.collect(); 1528 collector.collect();
1493 collector.def_map 1529 collector.def_map
1494 } 1530 }
1495 1531
1496 fn do_resolve(code: &str) -> CrateDefMap { 1532 fn do_resolve(code: &str) -> DefMap {
1497 let (db, _file_id) = TestDB::with_single_file(&code); 1533 let (db, _file_id) = TestDB::with_single_file(&code);
1498 let krate = db.test_crate(); 1534 let krate = db.test_crate();
1499 1535
1500 let def_map = { 1536 let edition = db.crate_graph()[krate].edition;
1501 let edition = db.crate_graph()[krate].edition; 1537 let def_map = DefMap::empty(krate, edition);
1502 let mut modules: Arena<ModuleData> = Arena::default();
1503 let root = modules.alloc(ModuleData::default());
1504 CrateDefMap {
1505 krate,
1506 edition,
1507 extern_prelude: FxHashMap::default(),
1508 prelude: None,
1509 root,
1510 modules,
1511 diagnostics: Vec::new(),
1512 }
1513 };
1514 do_collect_defs(&db, def_map) 1538 do_collect_defs(&db, def_map)
1515 } 1539 }
1516 1540
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index 88e10574e..ec90f4e65 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -19,7 +19,7 @@ use test_utils::mark;
19use crate::{ 19use crate::{
20 db::DefDatabase, 20 db::DefDatabase,
21 item_scope::BUILTIN_SCOPE, 21 item_scope::BUILTIN_SCOPE,
22 nameres::{BuiltinShadowMode, CrateDefMap}, 22 nameres::{BuiltinShadowMode, DefMap},
23 path::{ModPath, PathKind}, 23 path::{ModPath, PathKind},
24 per_ns::PerNs, 24 per_ns::PerNs,
25 visibility::{RawVisibility, Visibility}, 25 visibility::{RawVisibility, Visibility},
@@ -61,7 +61,7 @@ impl ResolvePathResult {
61 } 61 }
62} 62}
63 63
64impl CrateDefMap { 64impl DefMap {
65 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { 65 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
66 self.extern_prelude 66 self.extern_prelude
67 .get(name) 67 .get(name)
@@ -104,6 +104,43 @@ impl CrateDefMap {
104 path: &ModPath, 104 path: &ModPath,
105 shadow: BuiltinShadowMode, 105 shadow: BuiltinShadowMode,
106 ) -> ResolvePathResult { 106 ) -> ResolvePathResult {
107 let mut result = ResolvePathResult::empty(ReachedFixedPoint::No);
108 result.segment_index = Some(usize::max_value());
109
110 let mut current_map = self;
111 loop {
112 let new = current_map.resolve_path_fp_with_macro_single(
113 db,
114 mode,
115 original_module,
116 path,
117 shadow,
118 );
119
120 // Merge `new` into `result`.
121 result.resolved_def = result.resolved_def.or(new.resolved_def);
122 if result.reached_fixedpoint == ReachedFixedPoint::No {
123 result.reached_fixedpoint = new.reached_fixedpoint;
124 }
125 // FIXME: this doesn't seem right; what if the different namespace resolutions come from different crates?
126 result.krate = result.krate.or(new.krate);
127 result.segment_index = result.segment_index.min(new.segment_index);
128
129 match &current_map.parent {
130 Some(map) => current_map = map,
131 None => return result,
132 }
133 }
134 }
135
136 pub(super) fn resolve_path_fp_with_macro_single(
137 &self,
138 db: &dyn DefDatabase,
139 mode: ResolveMode,
140 original_module: LocalModuleId,
141 path: &ModPath,
142 shadow: BuiltinShadowMode,
143 ) -> ResolvePathResult {
107 let mut segments = path.segments.iter().enumerate(); 144 let mut segments = path.segments.iter().enumerate();
108 let mut curr_per_ns: PerNs = match path.kind { 145 let mut curr_per_ns: PerNs = match path.kind {
109 PathKind::DollarCrate(krate) => { 146 PathKind::DollarCrate(krate) => {
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs
index c459fa66d..73e3a4702 100644
--- a/crates/hir_def/src/nameres/tests.rs
+++ b/crates/hir_def/src/nameres/tests.rs
@@ -4,27 +4,47 @@ mod macros;
4mod mod_resolution; 4mod mod_resolution;
5mod diagnostics; 5mod diagnostics;
6mod primitives; 6mod primitives;
7mod block;
7 8
8use std::sync::Arc; 9use std::sync::Arc;
9 10
10use base_db::{fixture::WithFixture, SourceDatabase}; 11use base_db::{fixture::WithFixture, SourceDatabase};
11use expect_test::{expect, Expect}; 12use expect_test::{expect, Expect};
13use hir_expand::db::AstDatabase;
12use test_utils::mark; 14use test_utils::mark;
13 15
14use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; 16use crate::{db::DefDatabase, nameres::*, test_db::TestDB};
15 17
16fn compute_crate_def_map(ra_fixture: &str) -> Arc<CrateDefMap> { 18fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> {
17 let db = TestDB::with_files(ra_fixture); 19 let db = TestDB::with_files(ra_fixture);
18 let krate = db.crate_graph().iter().next().unwrap(); 20 let krate = db.crate_graph().iter().next().unwrap();
19 db.crate_def_map(krate) 21 db.crate_def_map(krate)
20} 22}
21 23
24fn compute_block_def_map(ra_fixture: &str) -> Arc<DefMap> {
25 let (db, position) = TestDB::with_position(ra_fixture);
26 let module = db.module_for_file(position.file_id);
27 let ast_map = db.ast_id_map(position.file_id.into());
28 let ast = db.parse(position.file_id);
29 let block: ast::BlockExpr =
30 syntax::algo::find_node_at_offset(&ast.syntax_node(), position.offset).unwrap();
31 let block_id = ast_map.ast_id(&block);
32
33 db.block_def_map(module.krate, InFile::new(position.file_id.into(), block_id))
34}
35
22fn check(ra_fixture: &str, expect: Expect) { 36fn check(ra_fixture: &str, expect: Expect) {
23 let def_map = compute_crate_def_map(ra_fixture); 37 let def_map = compute_crate_def_map(ra_fixture);
24 let actual = def_map.dump(); 38 let actual = def_map.dump();
25 expect.assert_eq(&actual); 39 expect.assert_eq(&actual);
26} 40}
27 41
42fn check_at(ra_fixture: &str, expect: Expect) {
43 let def_map = compute_block_def_map(ra_fixture);
44 let actual = def_map.dump();
45 expect.assert_eq(&actual);
46}
47
28#[test] 48#[test]
29fn crate_def_map_smoke_test() { 49fn crate_def_map_smoke_test() {
30 check( 50 check(
diff --git a/crates/hir_def/src/nameres/tests/block.rs b/crates/hir_def/src/nameres/tests/block.rs
new file mode 100644
index 000000000..01d6326a7
--- /dev/null
+++ b/crates/hir_def/src/nameres/tests/block.rs
@@ -0,0 +1,97 @@
1use super::*;
2
3#[test]
4fn inner_item_smoke() {
5 check_at(
6 r#"
7struct inner {}
8fn outer() {
9 $0
10 fn inner() {}
11}
12"#,
13 expect![[r#"
14 block scope
15 inner: v
16 crate
17 inner: t
18 outer: v
19 "#]],
20 );
21}
22
23#[test]
24fn use_from_crate() {
25 check_at(
26 r#"
27struct Struct;
28fn outer() {
29 use Struct;
30 use crate::Struct as CrateStruct;
31 use self::Struct as SelfStruct;
32 $0
33}
34"#,
35 expect![[r#"
36 block scope
37 CrateStruct: t v
38 SelfStruct: t v
39 Struct: t v
40 crate
41 Struct: t v
42 outer: v
43 "#]],
44 );
45}
46
47#[test]
48fn merge_namespaces() {
49 check_at(
50 r#"
51struct name {}
52fn outer() {
53 fn name() {}
54
55 use name as imported; // should import both `name`s
56
57 $0
58}
59"#,
60 expect![[r#"
61 block scope
62 imported: t v
63 name: v
64 crate
65 name: t
66 outer: v
67 "#]],
68 );
69}
70
71#[test]
72fn nested_blocks() {
73 check_at(
74 r#"
75fn outer() {
76 struct inner1 {}
77 fn inner() {
78 use inner1;
79 use outer;
80 fn inner2() {}
81 $0
82 }
83}
84"#,
85 expect![[r#"
86 block scope
87 inner1: t
88 inner2: v
89 outer: v
90 block scope
91 inner: v
92 inner1: t
93 crate
94 outer: v
95 "#]],
96 );
97}
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index 3dd7c3cbb..e34cd7f2f 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -87,7 +87,7 @@ impl ModPath {
87 87
88 /// If this path is a single identifier, like `foo`, return its name. 88 /// If this path is a single identifier, like `foo`, return its name.
89 pub fn as_ident(&self) -> Option<&Name> { 89 pub fn as_ident(&self) -> Option<&Name> {
90 if self.kind != PathKind::Plain || self.segments.len() > 1 { 90 if !self.is_ident() {
91 return None; 91 return None;
92 } 92 }
93 self.segments.first() 93 self.segments.first()
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index 85ddc2c47..b2f577649 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -16,13 +16,14 @@ use crate::{
16 expr::{ExprId, PatId}, 16 expr::{ExprId, PatId},
17 generics::GenericParams, 17 generics::GenericParams,
18 item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, 18 item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
19 nameres::CrateDefMap, 19 nameres::DefMap,
20 path::{ModPath, PathKind}, 20 path::{ModPath, PathKind},
21 per_ns::PerNs, 21 per_ns::PerNs,
22 visibility::{RawVisibility, Visibility}, 22 visibility::{RawVisibility, Visibility},
23 AdtId, AssocContainerId, ConstId, ConstParamId, ContainerId, DefWithBodyId, EnumId, 23 AdtId, AssocContainerId, ConstId, ConstParamId, ContainerId, DefWithBodyId, EnumId,
24 EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, 24 EnumVariantId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, LifetimeParamId,
25 ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, 25 LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
26 TypeParamId, VariantId,
26}; 27};
27 28
28#[derive(Debug, Clone, Default)] 29#[derive(Debug, Clone, Default)]
@@ -34,7 +35,7 @@ pub struct Resolver {
34// FIXME how to store these best 35// FIXME how to store these best
35#[derive(Debug, Clone)] 36#[derive(Debug, Clone)]
36struct ModuleItemMap { 37struct ModuleItemMap {
37 crate_def_map: Arc<CrateDefMap>, 38 crate_def_map: Arc<DefMap>,
38 module_id: LocalModuleId, 39 module_id: LocalModuleId,
39} 40}
40 41
@@ -145,6 +146,19 @@ impl Resolver {
145 self.resolve_module_path(db, path, BuiltinShadowMode::Module) 146 self.resolve_module_path(db, path, BuiltinShadowMode::Module)
146 } 147 }
147 148
149 pub fn resolve_module_path_in_trait_items(
150 &self,
151 db: &dyn DefDatabase,
152 path: &ModPath,
153 ) -> Option<TraitId> {
154 let (item_map, module) = self.module_scope()?;
155 let (module_res, ..) = item_map.resolve_path(db, module, &path, BuiltinShadowMode::Module);
156 match module_res.take_types()? {
157 ModuleDefId::TraitId(it) => Some(it),
158 _ => None,
159 }
160 }
161
148 pub fn resolve_path_in_type_ns( 162 pub fn resolve_path_in_type_ns(
149 &self, 163 &self,
150 db: &dyn DefDatabase, 164 db: &dyn DefDatabase,
@@ -415,7 +429,7 @@ impl Resolver {
415 let mut traits = FxHashSet::default(); 429 let mut traits = FxHashSet::default();
416 for scope in &self.scopes { 430 for scope in &self.scopes {
417 if let Scope::ModuleScope(m) = scope { 431 if let Scope::ModuleScope(m) = scope {
418 if let Some(prelude) = m.crate_def_map.prelude { 432 if let Some(prelude) = m.crate_def_map.prelude() {
419 let prelude_def_map = db.crate_def_map(prelude.krate); 433 let prelude_def_map = db.crate_def_map(prelude.krate);
420 traits.extend(prelude_def_map[prelude.local_id].scope.traits()); 434 traits.extend(prelude_def_map[prelude.local_id].scope.traits());
421 } 435 }
@@ -425,7 +439,7 @@ impl Resolver {
425 traits 439 traits
426 } 440 }
427 441
428 fn module_scope(&self) -> Option<(&CrateDefMap, LocalModuleId)> { 442 fn module_scope(&self) -> Option<(&DefMap, LocalModuleId)> {
429 self.scopes.iter().rev().find_map(|scope| match scope { 443 self.scopes.iter().rev().find_map(|scope| match scope {
430 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), 444 Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)),
431 445
@@ -445,11 +459,11 @@ impl Resolver {
445 459
446 pub fn module(&self) -> Option<ModuleId> { 460 pub fn module(&self) -> Option<ModuleId> {
447 let (def_map, local_id) = self.module_scope()?; 461 let (def_map, local_id) = self.module_scope()?;
448 Some(ModuleId { krate: def_map.krate, local_id }) 462 Some(ModuleId { krate: def_map.krate(), local_id })
449 } 463 }
450 464
451 pub fn krate(&self) -> Option<CrateId> { 465 pub fn krate(&self) -> Option<CrateId> {
452 self.module_scope().map(|t| t.0.krate) 466 self.module_scope().map(|t| t.0.krate())
453 } 467 }
454 468
455 pub fn where_predicates_in_scope<'a>( 469 pub fn where_predicates_in_scope<'a>(
@@ -484,7 +498,7 @@ pub enum ScopeDef {
484 PerNs(PerNs), 498 PerNs(PerNs),
485 ImplSelfType(ImplId), 499 ImplSelfType(ImplId),
486 AdtSelfType(AdtId), 500 AdtSelfType(AdtId),
487 GenericParam(TypeParamId), 501 GenericParam(GenericParamId),
488 Local(PatId), 502 Local(PatId),
489} 503}
490 504
@@ -508,13 +522,13 @@ impl Scope {
508 seen.insert((name.clone(), scope)); 522 seen.insert((name.clone(), scope));
509 f(name.clone(), ScopeDef::PerNs(scope)); 523 f(name.clone(), ScopeDef::PerNs(scope));
510 }); 524 });
511 m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| { 525 m.crate_def_map.extern_prelude().for_each(|(name, &def)| {
512 f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public))); 526 f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public)));
513 }); 527 });
514 BUILTIN_SCOPE.iter().for_each(|(name, &def)| { 528 BUILTIN_SCOPE.iter().for_each(|(name, &def)| {
515 f(name.clone(), ScopeDef::PerNs(def)); 529 f(name.clone(), ScopeDef::PerNs(def));
516 }); 530 });
517 if let Some(prelude) = m.crate_def_map.prelude { 531 if let Some(prelude) = m.crate_def_map.prelude() {
518 let prelude_def_map = db.crate_def_map(prelude.krate); 532 let prelude_def_map = db.crate_def_map(prelude.krate);
519 prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { 533 prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| {
520 let seen_tuple = (name.clone(), def); 534 let seen_tuple = (name.clone(), def);
@@ -527,15 +541,21 @@ impl Scope {
527 Scope::LocalItemsScope(body) => body.item_scope.entries().for_each(|(name, def)| { 541 Scope::LocalItemsScope(body) => body.item_scope.entries().for_each(|(name, def)| {
528 f(name.clone(), ScopeDef::PerNs(def)); 542 f(name.clone(), ScopeDef::PerNs(def));
529 }), 543 }),
530 Scope::GenericParams { params, def } => { 544 &Scope::GenericParams { ref params, def: parent } => {
531 for (local_id, param) in params.types.iter() { 545 for (local_id, param) in params.types.iter() {
532 if let Some(name) = &param.name { 546 if let Some(ref name) = param.name {
533 f( 547 let id = TypeParamId { local_id, parent };
534 name.clone(), 548 f(name.clone(), ScopeDef::GenericParam(id.into()))
535 ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }),
536 )
537 } 549 }
538 } 550 }
551 for (local_id, param) in params.consts.iter() {
552 let id = ConstParamId { local_id, parent };
553 f(param.name.clone(), ScopeDef::GenericParam(id.into()))
554 }
555 for (local_id, param) in params.lifetimes.iter() {
556 let id = LifetimeParamId { local_id, parent };
557 f(param.name.clone(), ScopeDef::GenericParam(id.into()))
558 }
539 } 559 }
540 Scope::ImplDefScope(i) => { 560 Scope::ImplDefScope(i) => {
541 f(name![Self], ScopeDef::ImplSelfType(*i)); 561 f(name![Self], ScopeDef::ImplSelfType(*i));
@@ -588,11 +608,7 @@ impl Resolver {
588 self.push_scope(Scope::ImplDefScope(impl_def)) 608 self.push_scope(Scope::ImplDefScope(impl_def))
589 } 609 }
590 610
591 fn push_module_scope( 611 fn push_module_scope(self, crate_def_map: Arc<DefMap>, module_id: LocalModuleId) -> Resolver {
592 self,
593 crate_def_map: Arc<CrateDefMap>,
594 module_id: LocalModuleId,
595 ) -> Resolver {
596 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) 612 self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id }))
597 } 613 }
598 614
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs
index 574c0201a..4ff219fb7 100644
--- a/crates/hir_def/src/test_db.rs
+++ b/crates/hir_def/src/test_db.rs
@@ -75,7 +75,7 @@ impl TestDB {
75 pub(crate) fn module_for_file(&self, file_id: FileId) -> crate::ModuleId { 75 pub(crate) fn module_for_file(&self, file_id: FileId) -> crate::ModuleId {
76 for &krate in self.relevant_crates(file_id).iter() { 76 for &krate in self.relevant_crates(file_id).iter() {
77 let crate_def_map = self.crate_def_map(krate); 77 let crate_def_map = self.crate_def_map(krate);
78 for (local_id, data) in crate_def_map.modules.iter() { 78 for (local_id, data) in crate_def_map.modules() {
79 if data.origin.file_id() == Some(file_id) { 79 if data.origin.file_id() == Some(file_id) {
80 return crate::ModuleId { krate, local_id }; 80 return crate::ModuleId { krate, local_id };
81 } 81 }
@@ -110,7 +110,7 @@ impl TestDB {
110 let crate_graph = self.crate_graph(); 110 let crate_graph = self.crate_graph();
111 for krate in crate_graph.iter() { 111 for krate in crate_graph.iter() {
112 let crate_def_map = self.crate_def_map(krate); 112 let crate_def_map = self.crate_def_map(krate);
113 for (module_id, _) in crate_def_map.modules.iter() { 113 for (module_id, _) in crate_def_map.modules() {
114 let file_id = crate_def_map[module_id].origin.file_id(); 114 let file_id = crate_def_map[module_id].origin.file_id();
115 files.extend(file_id) 115 files.extend(file_id)
116 } 116 }
@@ -135,7 +135,7 @@ impl TestDB {
135 let crate_def_map = self.crate_def_map(krate); 135 let crate_def_map = self.crate_def_map(krate);
136 136
137 let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); 137 let mut sink = DiagnosticSinkBuilder::new().build(&mut cb);
138 for (module_id, module) in crate_def_map.modules.iter() { 138 for (module_id, module) in crate_def_map.modules() {
139 crate_def_map.add_diagnostics(self, module_id, &mut sink); 139 crate_def_map.add_diagnostics(self, module_id, &mut sink);
140 140
141 for decl in module.scope.declarations() { 141 for decl in module.scope.declarations() {
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs
index ae93d0d10..049b2e462 100644
--- a/crates/hir_def/src/type_ref.rs
+++ b/crates/hir_def/src/type_ref.rs
@@ -159,6 +159,8 @@ impl TypeRef {
159 ast::Type::DynTraitType(inner) => { 159 ast::Type::DynTraitType(inner) => {
160 TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list())) 160 TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
161 } 161 }
162 // FIXME: Macros in type position are not yet supported.
163 ast::Type::MacroType(_) => TypeRef::Error,
162 } 164 }
163 } 165 }
164 166
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs
index f3bc9d680..3134fa43d 100644
--- a/crates/hir_def/src/visibility.rs
+++ b/crates/hir_def/src/visibility.rs
@@ -5,7 +5,7 @@ use syntax::ast;
5 5
6use crate::{ 6use crate::{
7 db::DefDatabase, 7 db::DefDatabase,
8 nameres::CrateDefMap, 8 nameres::DefMap,
9 path::{ModPath, PathKind}, 9 path::{ModPath, PathKind},
10 ModuleId, 10 ModuleId,
11}; 11};
@@ -116,7 +116,7 @@ impl Visibility {
116 116
117 pub(crate) fn is_visible_from_def_map( 117 pub(crate) fn is_visible_from_def_map(
118 self, 118 self,
119 def_map: &CrateDefMap, 119 def_map: &DefMap,
120 from_module: crate::LocalModuleId, 120 from_module: crate::LocalModuleId,
121 ) -> bool { 121 ) -> bool {
122 let to_module = match self { 122 let to_module = match self {
@@ -135,7 +135,7 @@ impl Visibility {
135 /// 135 ///
136 /// If there is no subset relation between `self` and `other`, returns `None` (ie. they're only 136 /// If there is no subset relation between `self` and `other`, returns `None` (ie. they're only
137 /// visible in unrelated modules). 137 /// visible in unrelated modules).
138 pub(crate) fn max(self, other: Visibility, def_map: &CrateDefMap) -> Option<Visibility> { 138 pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> {
139 match (self, other) { 139 match (self, other) {
140 (Visibility::Module(_), Visibility::Public) 140 (Visibility::Module(_), Visibility::Public)
141 | (Visibility::Public, Visibility::Module(_)) 141 | (Visibility::Public, Visibility::Module(_))