diff options
Diffstat (limited to 'crates/hir_def/src')
-rw-r--r-- | crates/hir_def/src/attr.rs | 1 | ||||
-rw-r--r-- | crates/hir_def/src/body.rs | 6 | ||||
-rw-r--r-- | crates/hir_def/src/body/tests.rs | 41 | ||||
-rw-r--r-- | crates/hir_def/src/db.rs | 17 | ||||
-rw-r--r-- | crates/hir_def/src/find_path.rs | 22 | ||||
-rw-r--r-- | crates/hir_def/src/import_map.rs | 68 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 41 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 45 | ||||
-rw-r--r-- | crates/hir_def/src/lang_item.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 150 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 68 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/path_resolution.rs | 41 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests.rs | 22 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/block.rs | 97 | ||||
-rw-r--r-- | crates/hir_def/src/path.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/resolver.rs | 60 | ||||
-rw-r--r-- | crates/hir_def/src/test_db.rs | 6 | ||||
-rw-r--r-- | crates/hir_def/src/type_ref.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/visibility.rs | 6 |
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 | ||
46 | pub(crate) struct Expander { | 46 | pub(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}; | |||
6 | use super::*; | 6 | use super::*; |
7 | 7 | ||
8 | fn lower(ra_fixture: &str) -> Arc<Body> { | 8 | fn 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 | ||
23 | fn check_diagnostics(ra_fixture: &str) { | 29 | fn check_diagnostics(ra_fixture: &str) { |
@@ -42,6 +48,25 @@ fn main() { n_nuple!(1,2,3); } | |||
42 | } | 48 | } |
43 | 49 | ||
44 | #[test] | 50 | #[test] |
51 | fn macro_resolve() { | ||
52 | // Regression test for a path resolution bug introduced with inner item handling. | ||
53 | lower( | ||
54 | r" | ||
55 | macro_rules! vec { | ||
56 | () => { () }; | ||
57 | ($elem:expr; $n:expr) => { () }; | ||
58 | ($($x:expr),+ $(,)?) => { () }; | ||
59 | } | ||
60 | mod m { | ||
61 | fn outer() { | ||
62 | let _ = vec![FileSet::default(); self.len()]; | ||
63 | } | ||
64 | } | ||
65 | ", | ||
66 | ); | ||
67 | } | ||
68 | |||
69 | #[test] | ||
45 | fn cfg_diagnostics() { | 70 | fn 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 @@ | |||
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; | 4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; |
5 | use hir_expand::{db::AstDatabase, HirFileId}; | 5 | use hir_expand::{db::AstDatabase, AstId, HirFileId}; |
6 | use la_arena::ArenaMap; | 6 | use la_arena::ArenaMap; |
7 | use syntax::SmolStr; | 7 | use syntax::{ast, SmolStr}; |
8 | 8 | ||
9 | use crate::{ | 9 | use 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 | ||
115 | fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { | 118 | fn 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}; | |||
4 | use rustc_hash::FxHashSet; | 4 | use rustc_hash::FxHashSet; |
5 | use test_utils::mark; | 5 | use test_utils::mark; |
6 | 6 | ||
7 | use crate::nameres::CrateDefMap; | 7 | use crate::nameres::DefMap; |
8 | use crate::{ | 8 | use 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 | ||
50 | fn check_self_super(def_map: &CrateDefMap, item: ItemInNs, from: ModuleId) -> Option<ModPath> { | 50 | fn 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 | }; |
23 | use la_arena::{Arena, Idx, RawIdx}; | 23 | use la_arena::{Arena, Idx, RawIdx}; |
24 | use profile::Count; | ||
24 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
25 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
26 | use syntax::{ast, match_ast}; | 27 | use 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)] |
69 | pub struct ItemTree { | 70 | pub 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 | ||
77 | impl ItemTree { | 79 | impl 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 | ||
464 | impl_index!(fields: Field, variants: Variant, exprs: Expr); | 470 | impl_index!(fields: Field, variants: Variant); |
465 | 471 | ||
466 | impl Index<RawVisibilityId> for ItemTree { | 472 | impl 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)] | ||
670 | pub struct Expr; | ||
671 | |||
672 | macro_rules! impl_froms { | 673 | macro_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} | |||
6 | use smallvec::SmallVec; | 6 | use smallvec::SmallVec; |
7 | use syntax::{ | 7 | use syntax::{ |
8 | ast::{self, ModuleItemOwner}, | 8 | ast::{self, ModuleItemOwner}, |
9 | SyntaxNode, | 9 | SyntaxNode, WalkEvent, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use 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; | |||
59 | use base_db::{CrateId, Edition, FileId}; | 59 | use base_db::{CrateId, Edition, FileId}; |
60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; | 60 | use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; |
61 | use la_arena::Arena; | 61 | use la_arena::Arena; |
62 | use profile::Count; | ||
62 | use rustc_hash::FxHashMap; | 63 | use rustc_hash::FxHashMap; |
63 | use stdx::format_to; | 64 | use stdx::format_to; |
64 | use syntax::ast; | 65 | use syntax::{ast, AstNode}; |
65 | 66 | ||
66 | use crate::{ | 67 | use 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)] |
77 | pub struct CrateDefMap { | 78 | pub 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 | ||
91 | impl std::ops::Index<LocalModuleId> for CrateDefMap { | 94 | impl 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 | ||
114 | impl Default for ModuleOrigin { | 121 | impl 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 | ||
172 | impl CrateDefMap { | 182 | impl 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) = ¤t_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 | ||
341 | fn 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)] |
280 | pub enum ModuleSource { | 371 | pub 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 | ||
285 | mod diagnostics { | 377 | mod 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; | |||
45 | const EXPANSION_DEPTH_LIMIT: usize = 128; | 45 | const EXPANSION_DEPTH_LIMIT: usize = 128; |
46 | const FIXED_POINT_LIMIT: usize = 8192; | 46 | const FIXED_POINT_LIMIT: usize = 8192; |
47 | 47 | ||
48 | pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { | 48 | pub(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 |
211 | struct DefCollector<'a> { | 223 | struct 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 | ||
230 | impl DefCollector<'_> { | 242 | impl 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<'_, '_> { | |||
1470 | mod tests { | 1506 | mod 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; | |||
19 | use crate::{ | 19 | use 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 | ||
64 | impl CrateDefMap { | 64 | impl 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 ¤t_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; | |||
4 | mod mod_resolution; | 4 | mod mod_resolution; |
5 | mod diagnostics; | 5 | mod diagnostics; |
6 | mod primitives; | 6 | mod primitives; |
7 | mod block; | ||
7 | 8 | ||
8 | use std::sync::Arc; | 9 | use std::sync::Arc; |
9 | 10 | ||
10 | use base_db::{fixture::WithFixture, SourceDatabase}; | 11 | use base_db::{fixture::WithFixture, SourceDatabase}; |
11 | use expect_test::{expect, Expect}; | 12 | use expect_test::{expect, Expect}; |
13 | use hir_expand::db::AstDatabase; | ||
12 | use test_utils::mark; | 14 | use test_utils::mark; |
13 | 15 | ||
14 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; | 16 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; |
15 | 17 | ||
16 | fn compute_crate_def_map(ra_fixture: &str) -> Arc<CrateDefMap> { | 18 | fn 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 | ||
24 | fn 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 | |||
22 | fn check(ra_fixture: &str, expect: Expect) { | 36 | fn 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 | ||
42 | fn 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] |
29 | fn crate_def_map_smoke_test() { | 49 | fn 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 @@ | |||
1 | use super::*; | ||
2 | |||
3 | #[test] | ||
4 | fn inner_item_smoke() { | ||
5 | check_at( | ||
6 | r#" | ||
7 | struct inner {} | ||
8 | fn 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] | ||
24 | fn use_from_crate() { | ||
25 | check_at( | ||
26 | r#" | ||
27 | struct Struct; | ||
28 | fn 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] | ||
48 | fn merge_namespaces() { | ||
49 | check_at( | ||
50 | r#" | ||
51 | struct name {} | ||
52 | fn 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] | ||
72 | fn nested_blocks() { | ||
73 | check_at( | ||
74 | r#" | ||
75 | fn 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)] |
36 | struct ModuleItemMap { | 37 | struct 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) = ¶m.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 | ||
6 | use crate::{ | 6 | use 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(_)) |