diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-01-25 18:24:04 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-01-25 18:24:04 +0000 |
commit | a37091d2d0175b0999d6383d48f538cdbf0267a0 (patch) | |
tree | 06981374f0c397b45e31b74c97ed337853fe59d2 /crates | |
parent | 2c735ed734be9b9041921478e0049fffd7160f78 (diff) | |
parent | 08253d5473348e2f3061e0c8d84c62de537a5821 (diff) |
Merge #7431
7431: Handle `super` paths inside blocks correctly r=jonas-schievink a=jonas-schievink
We now intern `BlockLoc` and use `BlockId` to refer to block expressions. This is needed to keep `ModuleId` simple, since it would otherwise have to store an arbitrarily long chain of blocks and couldn't be `Copy`.
The `DefMap` hierarchy is now created as the caller descends into an item body. This is necessary to link the correct module as the block's parent, which is important for correct name resolution.
As a result, we can now resolve `super` paths inside block expressions by climbing the `DefMap` chain.
bors r+
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_def/src/db.rs | 15 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 15 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 73 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/path_resolution.rs | 41 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests.rs | 62 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/block.rs | 26 |
6 files changed, 158 insertions, 74 deletions
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index a87c80b8a..aef7e1f6c 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, AstId, HirFileId}; | 5 | use hir_expand::{db::AstDatabase, HirFileId}; |
6 | use la_arena::ArenaMap; | 6 | use la_arena::ArenaMap; |
7 | use syntax::{ast, SmolStr}; | 7 | use syntax::SmolStr; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | adt::{EnumData, StructData}, | 10 | adt::{EnumData, StructData}, |
@@ -16,9 +16,10 @@ use crate::{ | |||
16 | item_tree::ItemTree, | 16 | item_tree::ItemTree, |
17 | lang_item::{LangItemTarget, LangItems}, | 17 | lang_item::{LangItemTarget, LangItems}, |
18 | nameres::DefMap, | 18 | nameres::DefMap, |
19 | AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, | 19 | AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, |
20 | GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, StaticLoc, StructId, | 20 | FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, LocalFieldId, StaticId, |
21 | StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, VariantId, | 21 | StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, |
22 | UnionLoc, VariantId, | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | #[salsa::query_group(InternDatabaseStorage)] | 25 | #[salsa::query_group(InternDatabaseStorage)] |
@@ -41,6 +42,8 @@ pub trait InternDatabase: SourceDatabase { | |||
41 | fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; | 42 | fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; |
42 | #[salsa::interned] | 43 | #[salsa::interned] |
43 | fn intern_impl(&self, loc: ImplLoc) -> ImplId; | 44 | fn intern_impl(&self, loc: ImplLoc) -> ImplId; |
45 | #[salsa::interned] | ||
46 | fn intern_block(&self, loc: BlockLoc) -> BlockId; | ||
44 | } | 47 | } |
45 | 48 | ||
46 | #[salsa::query_group(DefDatabaseStorage)] | 49 | #[salsa::query_group(DefDatabaseStorage)] |
@@ -56,7 +59,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
56 | fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; | 59 | fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; |
57 | 60 | ||
58 | #[salsa::invoke(DefMap::block_def_map_query)] | 61 | #[salsa::invoke(DefMap::block_def_map_query)] |
59 | fn block_def_map(&self, krate: CrateId, block: AstId<ast::BlockExpr>) -> Arc<DefMap>; | 62 | fn block_def_map(&self, block: BlockId) -> Arc<DefMap>; |
60 | 63 | ||
61 | #[salsa::invoke(StructData::struct_data_query)] | 64 | #[salsa::invoke(StructData::struct_data_query)] |
62 | fn struct_data(&self, id: StructId) -> Arc<StructData>; | 65 | fn struct_data(&self, id: StructId) -> Arc<StructData>; |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index cf09ebd3f..42b50b5b7 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -74,12 +74,16 @@ use stdx::impl_from; | |||
74 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 74 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
75 | pub struct ModuleId { | 75 | pub struct ModuleId { |
76 | krate: CrateId, | 76 | krate: CrateId, |
77 | block: Option<BlockId>, | ||
77 | pub local_id: LocalModuleId, | 78 | pub local_id: LocalModuleId, |
78 | } | 79 | } |
79 | 80 | ||
80 | impl ModuleId { | 81 | impl ModuleId { |
81 | pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> { | 82 | pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> { |
82 | db.crate_def_map(self.krate) | 83 | match self.block { |
84 | Some(block) => db.block_def_map(block), | ||
85 | None => db.crate_def_map(self.krate), | ||
86 | } | ||
83 | } | 87 | } |
84 | 88 | ||
85 | pub fn krate(&self) -> CrateId { | 89 | pub fn krate(&self) -> CrateId { |
@@ -230,6 +234,15 @@ pub struct ImplId(salsa::InternId); | |||
230 | type ImplLoc = ItemLoc<Impl>; | 234 | type ImplLoc = ItemLoc<Impl>; |
231 | impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); | 235 | impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); |
232 | 236 | ||
237 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] | ||
238 | pub struct BlockId(salsa::InternId); | ||
239 | #[derive(Debug, Hash, PartialEq, Eq, Clone)] | ||
240 | pub struct BlockLoc { | ||
241 | ast_id: AstId<ast::BlockExpr>, | ||
242 | module: ModuleId, | ||
243 | } | ||
244 | impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block); | ||
245 | |||
233 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 246 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
234 | pub struct TypeParamId { | 247 | pub struct TypeParamId { |
235 | pub parent: GenericDefId, | 248 | pub parent: GenericDefId, |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 4fbbecb38..199771e9a 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -62,7 +62,7 @@ use la_arena::Arena; | |||
62 | use profile::Count; | 62 | use profile::Count; |
63 | use rustc_hash::FxHashMap; | 63 | use rustc_hash::FxHashMap; |
64 | use stdx::format_to; | 64 | use stdx::format_to; |
65 | use syntax::{ast, AstNode}; | 65 | use syntax::ast; |
66 | 66 | ||
67 | use crate::{ | 67 | use crate::{ |
68 | db::DefDatabase, | 68 | db::DefDatabase, |
@@ -70,14 +70,14 @@ use crate::{ | |||
70 | nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, | 70 | nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, |
71 | path::ModPath, | 71 | path::ModPath, |
72 | per_ns::PerNs, | 72 | per_ns::PerNs, |
73 | AstId, LocalModuleId, ModuleDefId, ModuleId, | 73 | AstId, BlockId, BlockLoc, LocalModuleId, ModuleDefId, ModuleId, |
74 | }; | 74 | }; |
75 | 75 | ||
76 | /// Contains all top-level defs from a macro-expanded crate | 76 | /// Contains all top-level defs from a macro-expanded crate |
77 | #[derive(Debug, PartialEq, Eq)] | 77 | #[derive(Debug, PartialEq, Eq)] |
78 | pub struct DefMap { | 78 | pub struct DefMap { |
79 | _c: Count<Self>, | 79 | _c: Count<Self>, |
80 | parent: Option<Arc<DefMap>>, | 80 | block: Option<BlockInfo>, |
81 | root: LocalModuleId, | 81 | root: LocalModuleId, |
82 | modules: Arena<ModuleData>, | 82 | modules: Arena<ModuleData>, |
83 | krate: CrateId, | 83 | krate: CrateId, |
@@ -91,6 +91,13 @@ pub struct DefMap { | |||
91 | diagnostics: Vec<DefDiagnostic>, | 91 | diagnostics: Vec<DefDiagnostic>, |
92 | } | 92 | } |
93 | 93 | ||
94 | #[derive(Debug, PartialEq, Eq)] | ||
95 | struct BlockInfo { | ||
96 | block: BlockId, | ||
97 | parent: Arc<DefMap>, | ||
98 | parent_module: LocalModuleId, | ||
99 | } | ||
100 | |||
94 | impl std::ops::Index<LocalModuleId> for DefMap { | 101 | impl std::ops::Index<LocalModuleId> for DefMap { |
95 | type Output = ModuleData; | 102 | type Output = ModuleData; |
96 | fn index(&self, id: LocalModuleId) -> &ModuleData { | 103 | fn index(&self, id: LocalModuleId) -> &ModuleData { |
@@ -190,15 +197,12 @@ impl DefMap { | |||
190 | Arc::new(def_map) | 197 | Arc::new(def_map) |
191 | } | 198 | } |
192 | 199 | ||
193 | pub(crate) fn block_def_map_query( | 200 | pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> { |
194 | db: &dyn DefDatabase, | 201 | let block: BlockLoc = db.lookup_intern_block(block_id); |
195 | krate: CrateId, | 202 | let item_tree = db.item_tree(block.ast_id.file_id); |
196 | block: AstId<ast::BlockExpr>, | 203 | let block_items = item_tree.inner_items_of_block(block.ast_id.value); |
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 | 204 | ||
201 | let parent = parent_def_map(db, krate, block); | 205 | let parent = block.module.def_map(db); |
202 | 206 | ||
203 | if block_items.is_empty() { | 207 | if block_items.is_empty() { |
204 | // If there are no inner items, nothing new is brought into scope, so we can just return | 208 | // If there are no inner items, nothing new is brought into scope, so we can just return |
@@ -206,10 +210,13 @@ impl DefMap { | |||
206 | return parent; | 210 | return parent; |
207 | } | 211 | } |
208 | 212 | ||
209 | let mut def_map = DefMap::empty(krate, parent.edition); | 213 | let block_info = |
210 | def_map.parent = Some(parent); | 214 | BlockInfo { block: block_id, parent, parent_module: block.module.local_id }; |
215 | |||
216 | let mut def_map = DefMap::empty(block.module.krate, block_info.parent.edition); | ||
217 | def_map.block = Some(block_info); | ||
211 | 218 | ||
212 | let def_map = collector::collect_defs(db, def_map, Some(block.value)); | 219 | let def_map = collector::collect_defs(db, def_map, Some(block.ast_id.value)); |
213 | Arc::new(def_map) | 220 | Arc::new(def_map) |
214 | } | 221 | } |
215 | 222 | ||
@@ -218,7 +225,7 @@ impl DefMap { | |||
218 | let root = modules.alloc(ModuleData::default()); | 225 | let root = modules.alloc(ModuleData::default()); |
219 | DefMap { | 226 | DefMap { |
220 | _c: Count::new(), | 227 | _c: Count::new(), |
221 | parent: None, | 228 | block: None, |
222 | krate, | 229 | krate, |
223 | edition, | 230 | edition, |
224 | extern_prelude: FxHashMap::default(), | 231 | extern_prelude: FxHashMap::default(), |
@@ -266,7 +273,8 @@ impl DefMap { | |||
266 | } | 273 | } |
267 | 274 | ||
268 | pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId { | 275 | pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId { |
269 | ModuleId { krate: self.krate, local_id } | 276 | let block = self.block.as_ref().map(|b| b.block); |
277 | ModuleId { krate: self.krate, local_id, block } | ||
270 | } | 278 | } |
271 | 279 | ||
272 | pub(crate) fn resolve_path( | 280 | pub(crate) fn resolve_path( |
@@ -286,9 +294,9 @@ impl DefMap { | |||
286 | pub fn dump(&self) -> String { | 294 | pub fn dump(&self) -> String { |
287 | let mut buf = String::new(); | 295 | let mut buf = String::new(); |
288 | let mut current_map = self; | 296 | let mut current_map = self; |
289 | while let Some(parent) = ¤t_map.parent { | 297 | while let Some(block) = ¤t_map.block { |
290 | go(&mut buf, current_map, "block scope", current_map.root); | 298 | go(&mut buf, current_map, "block scope", current_map.root); |
291 | current_map = &**parent; | 299 | current_map = &*block.parent; |
292 | } | 300 | } |
293 | go(&mut buf, current_map, "crate", current_map.root); | 301 | go(&mut buf, current_map, "crate", current_map.root); |
294 | return buf; | 302 | return buf; |
@@ -342,35 +350,6 @@ impl ModuleData { | |||
342 | } | 350 | } |
343 | } | 351 | } |
344 | 352 | ||
345 | fn parent_def_map( | ||
346 | db: &dyn DefDatabase, | ||
347 | krate: CrateId, | ||
348 | block: AstId<ast::BlockExpr>, | ||
349 | ) -> Arc<DefMap> { | ||
350 | // FIXME: store this info in the item tree instead of reparsing here | ||
351 | let ast_id_map = db.ast_id_map(block.file_id); | ||
352 | let block_ptr = ast_id_map.get(block.value); | ||
353 | let root = match db.parse_or_expand(block.file_id) { | ||
354 | Some(it) => it, | ||
355 | None => { | ||
356 | return Arc::new(DefMap::empty(krate, Edition::Edition2018)); | ||
357 | } | ||
358 | }; | ||
359 | let ast = block_ptr.to_node(&root); | ||
360 | |||
361 | for ancestor in ast.syntax().ancestors().skip(1) { | ||
362 | if let Some(block_expr) = ast::BlockExpr::cast(ancestor) { | ||
363 | let ancestor_id = ast_id_map.ast_id(&block_expr); | ||
364 | let ast_id = InFile::new(block.file_id, ancestor_id); | ||
365 | let parent_map = db.block_def_map(krate, ast_id); | ||
366 | return parent_map; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | // No enclosing block scope, so the parent is the crate-level DefMap. | ||
371 | db.crate_def_map(krate) | ||
372 | } | ||
373 | |||
374 | #[derive(Debug, Clone, PartialEq, Eq)] | 353 | #[derive(Debug, Clone, PartialEq, Eq)] |
375 | pub enum ModuleSource { | 354 | pub enum ModuleSource { |
376 | SourceFile(ast::SourceFile), | 355 | SourceFile(ast::SourceFile), |
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index c1eded5f2..419e465ed 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -10,8 +10,6 @@ | |||
10 | //! | 10 | //! |
11 | //! `ReachedFixedPoint` signals about this. | 11 | //! `ReachedFixedPoint` signals about this. |
12 | 12 | ||
13 | use std::iter::successors; | ||
14 | |||
15 | use base_db::Edition; | 13 | use base_db::Edition; |
16 | use hir_expand::name; | 14 | use hir_expand::name; |
17 | use hir_expand::name::Name; | 15 | use hir_expand::name::Name; |
@@ -131,8 +129,8 @@ impl DefMap { | |||
131 | result.krate = result.krate.or(new.krate); | 129 | result.krate = result.krate.or(new.krate); |
132 | result.segment_index = result.segment_index.min(new.segment_index); | 130 | result.segment_index = result.segment_index.min(new.segment_index); |
133 | 131 | ||
134 | match ¤t_map.parent { | 132 | match ¤t_map.block { |
135 | Some(map) => current_map = map, | 133 | Some(block) => current_map = &block.parent, |
136 | None => return result, | 134 | None => return result, |
137 | } | 135 | } |
138 | } | 136 | } |
@@ -193,14 +191,35 @@ impl DefMap { | |||
193 | self.resolve_name_in_module(db, original_module, &segment, prefer_module) | 191 | self.resolve_name_in_module(db, original_module, &segment, prefer_module) |
194 | } | 192 | } |
195 | PathKind::Super(lvl) => { | 193 | PathKind::Super(lvl) => { |
196 | let m = successors(Some(original_module), |m| self.modules[*m].parent) | 194 | let mut module = original_module; |
197 | .nth(lvl as usize); | 195 | for i in 0..lvl { |
198 | if let Some(local_id) = m { | 196 | match self.modules[module].parent { |
199 | PerNs::types(self.module_id(local_id).into(), Visibility::Public) | 197 | Some(it) => module = it, |
200 | } else { | 198 | None => match &self.block { |
201 | log::debug!("super path in root module"); | 199 | Some(block) => { |
202 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); | 200 | // Look up remaining path in parent `DefMap` |
201 | let new_path = ModPath { | ||
202 | kind: PathKind::Super(lvl - i), | ||
203 | segments: path.segments.clone(), | ||
204 | }; | ||
205 | log::debug!("`super` path: {} -> {} in parent map", path, new_path); | ||
206 | return block.parent.resolve_path_fp_with_macro( | ||
207 | db, | ||
208 | mode, | ||
209 | block.parent_module, | ||
210 | &new_path, | ||
211 | shadow, | ||
212 | ); | ||
213 | } | ||
214 | None => { | ||
215 | log::debug!("super path in root module"); | ||
216 | return ResolvePathResult::empty(ReachedFixedPoint::Yes); | ||
217 | } | ||
218 | }, | ||
219 | } | ||
203 | } | 220 | } |
221 | |||
222 | PerNs::types(self.module_id(module).into(), Visibility::Public) | ||
204 | } | 223 | } |
205 | PathKind::Abs => { | 224 | PathKind::Abs => { |
206 | // 2018-style absolute path -- only extern prelude | 225 | // 2018-style absolute path -- only extern prelude |
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs index 73e3a4702..b36d0b59b 100644 --- a/crates/hir_def/src/nameres/tests.rs +++ b/crates/hir_def/src/nameres/tests.rs | |||
@@ -8,12 +8,12 @@ mod block; | |||
8 | 8 | ||
9 | use std::sync::Arc; | 9 | use std::sync::Arc; |
10 | 10 | ||
11 | use base_db::{fixture::WithFixture, SourceDatabase}; | 11 | use base_db::{fixture::WithFixture, FilePosition, SourceDatabase}; |
12 | use expect_test::{expect, Expect}; | 12 | use expect_test::{expect, Expect}; |
13 | use hir_expand::db::AstDatabase; | 13 | use syntax::AstNode; |
14 | use test_utils::mark; | 14 | use test_utils::mark; |
15 | 15 | ||
16 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; | 16 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB, Lookup}; |
17 | 17 | ||
18 | fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { | 18 | fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { |
19 | let db = TestDB::with_files(ra_fixture); | 19 | let db = TestDB::with_files(ra_fixture); |
@@ -23,14 +23,58 @@ fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { | |||
23 | 23 | ||
24 | fn compute_block_def_map(ra_fixture: &str) -> Arc<DefMap> { | 24 | fn compute_block_def_map(ra_fixture: &str) -> Arc<DefMap> { |
25 | let (db, position) = TestDB::with_position(ra_fixture); | 25 | let (db, position) = TestDB::with_position(ra_fixture); |
26 | |||
27 | // FIXME: perhaps we should make this use body lowering tests instead? | ||
28 | |||
26 | let module = db.module_for_file(position.file_id); | 29 | let module = db.module_for_file(position.file_id); |
27 | let ast_map = db.ast_id_map(position.file_id.into()); | 30 | let mut def_map = db.crate_def_map(module.krate); |
28 | let ast = db.parse(position.file_id); | 31 | while let Some(new_def_map) = descend_def_map_at_position(&db, position, def_map.clone()) { |
29 | let block: ast::BlockExpr = | 32 | def_map = new_def_map; |
30 | syntax::algo::find_node_at_offset(&ast.syntax_node(), position.offset).unwrap(); | 33 | } |
31 | let block_id = ast_map.ast_id(&block); | 34 | |
35 | // FIXME: select the right module, not the root | ||
36 | |||
37 | def_map | ||
38 | } | ||
39 | |||
40 | fn descend_def_map_at_position( | ||
41 | db: &dyn DefDatabase, | ||
42 | position: FilePosition, | ||
43 | def_map: Arc<DefMap>, | ||
44 | ) -> Option<Arc<DefMap>> { | ||
45 | for (local_id, module_data) in def_map.modules() { | ||
46 | let mod_def = module_data.origin.definition_source(db); | ||
47 | let ast_map = db.ast_id_map(mod_def.file_id); | ||
48 | let item_tree = db.item_tree(mod_def.file_id); | ||
49 | let root = db.parse_or_expand(mod_def.file_id).unwrap(); | ||
50 | for item in module_data.scope.declarations() { | ||
51 | match item { | ||
52 | ModuleDefId::FunctionId(it) => { | ||
53 | // Technically blocks can be inside any type (due to arrays and const generics), | ||
54 | // and also in const/static initializers. For tests we only really care about | ||
55 | // functions though. | ||
56 | |||
57 | let ast = ast_map.get(item_tree[it.lookup(db).id.value].ast_id).to_node(&root); | ||
58 | |||
59 | if ast.syntax().text_range().contains(position.offset) { | ||
60 | // Cursor inside function, descend into its body's DefMap. | ||
61 | // Note that we don't handle block *expressions* inside function bodies. | ||
62 | let ast_map = db.ast_id_map(position.file_id.into()); | ||
63 | let ast_id = ast_map.ast_id(&ast.body().unwrap()); | ||
64 | let block = BlockLoc { | ||
65 | ast_id: InFile::new(position.file_id.into(), ast_id), | ||
66 | module: def_map.module_id(local_id), | ||
67 | }; | ||
68 | let block_id = db.intern_block(block); | ||
69 | return Some(db.block_def_map(block_id)); | ||
70 | } | ||
71 | } | ||
72 | _ => continue, | ||
73 | } | ||
74 | } | ||
75 | } | ||
32 | 76 | ||
33 | db.block_def_map(module.krate, InFile::new(position.file_id.into(), block_id)) | 77 | None |
34 | } | 78 | } |
35 | 79 | ||
36 | fn check(ra_fixture: &str, expect: Expect) { | 80 | fn check(ra_fixture: &str, expect: Expect) { |
diff --git a/crates/hir_def/src/nameres/tests/block.rs b/crates/hir_def/src/nameres/tests/block.rs index 01d6326a7..470ca593e 100644 --- a/crates/hir_def/src/nameres/tests/block.rs +++ b/crates/hir_def/src/nameres/tests/block.rs | |||
@@ -95,3 +95,29 @@ fn outer() { | |||
95 | "#]], | 95 | "#]], |
96 | ); | 96 | ); |
97 | } | 97 | } |
98 | |||
99 | #[test] | ||
100 | fn super_imports() { | ||
101 | check_at( | ||
102 | r#" | ||
103 | mod module { | ||
104 | fn f() { | ||
105 | use super::Struct; | ||
106 | $0 | ||
107 | } | ||
108 | } | ||
109 | |||
110 | struct Struct {} | ||
111 | "#, | ||
112 | expect![[r#" | ||
113 | block scope | ||
114 | Struct: t | ||
115 | crate | ||
116 | Struct: t | ||
117 | module: t | ||
118 | |||
119 | crate::module | ||
120 | f: v | ||
121 | "#]], | ||
122 | ); | ||
123 | } | ||