diff options
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 161 |
1 files changed, 69 insertions, 92 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index f3150f578..0b8a641f9 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -5,112 +5,85 @@ use hir_def::{ | |||
5 | child_by_source::ChildBySource, | 5 | child_by_source::ChildBySource, |
6 | dyn_map::DynMap, | 6 | dyn_map::DynMap, |
7 | keys::{self, Key}, | 7 | keys::{self, Key}, |
8 | resolver::{HasResolver, Resolver}, | ||
9 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, | 8 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, |
10 | StaticId, StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId, | 9 | StaticId, StructFieldId, StructId, TraitId, TypeAliasId, UnionId, VariantId, |
11 | }; | 10 | }; |
12 | use hir_expand::{name::AsName, AstId, InFile, MacroDefId, MacroDefKind}; | 11 | use hir_expand::{name::AsName, AstId, InFile, MacroDefId, MacroDefKind}; |
12 | use ra_db::FileId; | ||
13 | use ra_prof::profile; | 13 | use ra_prof::profile; |
14 | use ra_syntax::{ | 14 | use ra_syntax::{ |
15 | ast::{self, NameOwner}, | 15 | ast::{self, NameOwner}, |
16 | match_ast, AstNode, SyntaxNode, TextUnit, | 16 | match_ast, AstNode, SyntaxNode, |
17 | }; | 17 | }; |
18 | use rustc_hash::FxHashMap; | 18 | use rustc_hash::FxHashMap; |
19 | 19 | ||
20 | use crate::{db::HirDatabase, Local, Module, SourceAnalyzer, TypeParam}; | 20 | use crate::{db::HirDatabase, Local, Module, TypeParam}; |
21 | use ra_db::FileId; | ||
22 | 21 | ||
23 | pub struct SourceBinder<'a, DB> { | 22 | pub struct SourceBinder { |
24 | pub db: &'a DB, | ||
25 | child_by_source_cache: FxHashMap<ChildContainer, DynMap>, | 23 | child_by_source_cache: FxHashMap<ChildContainer, DynMap>, |
26 | } | 24 | } |
27 | 25 | ||
28 | impl<DB: HirDatabase> SourceBinder<'_, DB> { | 26 | impl SourceBinder { |
29 | pub fn new(db: &DB) -> SourceBinder<DB> { | 27 | pub(crate) fn new() -> SourceBinder { |
30 | SourceBinder { db, child_by_source_cache: FxHashMap::default() } | 28 | SourceBinder { child_by_source_cache: FxHashMap::default() } |
31 | } | ||
32 | |||
33 | pub fn analyze( | ||
34 | &mut self, | ||
35 | src: InFile<&SyntaxNode>, | ||
36 | offset: Option<TextUnit>, | ||
37 | ) -> SourceAnalyzer { | ||
38 | let _p = profile("SourceBinder::analyzer"); | ||
39 | let container = match self.find_container(src) { | ||
40 | Some(it) => it, | ||
41 | None => return SourceAnalyzer::new_for_resolver(Resolver::default(), src), | ||
42 | }; | ||
43 | |||
44 | let resolver = match container { | ||
45 | ChildContainer::DefWithBodyId(def) => { | ||
46 | return SourceAnalyzer::new_for_body(self.db, def, src, offset) | ||
47 | } | ||
48 | ChildContainer::TraitId(it) => it.resolver(self.db), | ||
49 | ChildContainer::ImplId(it) => it.resolver(self.db), | ||
50 | ChildContainer::ModuleId(it) => it.resolver(self.db), | ||
51 | ChildContainer::EnumId(it) => it.resolver(self.db), | ||
52 | ChildContainer::VariantId(it) => it.resolver(self.db), | ||
53 | ChildContainer::GenericDefId(it) => it.resolver(self.db), | ||
54 | }; | ||
55 | SourceAnalyzer::new_for_resolver(resolver, src) | ||
56 | } | 29 | } |
57 | 30 | ||
58 | pub fn to_def<T: ToDef>(&mut self, src: InFile<T>) -> Option<T::Def> { | 31 | pub(crate) fn to_module_def(&mut self, db: &impl HirDatabase, file: FileId) -> Option<Module> { |
59 | T::to_def(self, src) | ||
60 | } | ||
61 | |||
62 | pub fn to_module_def(&mut self, file: FileId) -> Option<Module> { | ||
63 | let _p = profile("SourceBinder::to_module_def"); | 32 | let _p = profile("SourceBinder::to_module_def"); |
64 | let (krate, local_id) = self.db.relevant_crates(file).iter().find_map(|&crate_id| { | 33 | let (krate, local_id) = db.relevant_crates(file).iter().find_map(|&crate_id| { |
65 | let crate_def_map = self.db.crate_def_map(crate_id); | 34 | let crate_def_map = db.crate_def_map(crate_id); |
66 | let local_id = crate_def_map.modules_for_file(file).next()?; | 35 | let local_id = crate_def_map.modules_for_file(file).next()?; |
67 | Some((crate_id, local_id)) | 36 | Some((crate_id, local_id)) |
68 | })?; | 37 | })?; |
69 | Some(Module { id: ModuleId { krate, local_id } }) | 38 | Some(Module { id: ModuleId { krate, local_id } }) |
70 | } | 39 | } |
71 | 40 | ||
72 | fn to_id<T: ToId>(&mut self, src: InFile<T>) -> Option<T::ID> { | 41 | fn to_id<T: ToId>(&mut self, db: &impl HirDatabase, src: InFile<T>) -> Option<T::ID> { |
73 | T::to_id(self, src) | 42 | T::to_id(db, self, src) |
74 | } | 43 | } |
75 | 44 | ||
76 | fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { | 45 | pub(crate) fn find_container( |
77 | for container in src.cloned().ancestors_with_macros(self.db).skip(1) { | 46 | &mut self, |
47 | db: &impl HirDatabase, | ||
48 | src: InFile<&SyntaxNode>, | ||
49 | ) -> Option<ChildContainer> { | ||
50 | for container in src.cloned().ancestors_with_macros(db).skip(1) { | ||
78 | let res: ChildContainer = match_ast! { | 51 | let res: ChildContainer = match_ast! { |
79 | match (container.value) { | 52 | match (container.value) { |
80 | ast::TraitDef(it) => { | 53 | ast::TraitDef(it) => { |
81 | let def: TraitId = self.to_id(container.with_value(it))?; | 54 | let def: TraitId = self.to_id(db, container.with_value(it))?; |
82 | def.into() | 55 | def.into() |
83 | }, | 56 | }, |
84 | ast::ImplBlock(it) => { | 57 | ast::ImplBlock(it) => { |
85 | let def: ImplId = self.to_id(container.with_value(it))?; | 58 | let def: ImplId = self.to_id(db, container.with_value(it))?; |
86 | def.into() | 59 | def.into() |
87 | }, | 60 | }, |
88 | ast::FnDef(it) => { | 61 | ast::FnDef(it) => { |
89 | let def: FunctionId = self.to_id(container.with_value(it))?; | 62 | let def: FunctionId = self.to_id(db, container.with_value(it))?; |
90 | DefWithBodyId::from(def).into() | 63 | DefWithBodyId::from(def).into() |
91 | }, | 64 | }, |
92 | ast::StaticDef(it) => { | 65 | ast::StaticDef(it) => { |
93 | let def: StaticId = self.to_id(container.with_value(it))?; | 66 | let def: StaticId = self.to_id(db, container.with_value(it))?; |
94 | DefWithBodyId::from(def).into() | 67 | DefWithBodyId::from(def).into() |
95 | }, | 68 | }, |
96 | ast::ConstDef(it) => { | 69 | ast::ConstDef(it) => { |
97 | let def: ConstId = self.to_id(container.with_value(it))?; | 70 | let def: ConstId = self.to_id(db, container.with_value(it))?; |
98 | DefWithBodyId::from(def).into() | 71 | DefWithBodyId::from(def).into() |
99 | }, | 72 | }, |
100 | ast::EnumDef(it) => { | 73 | ast::EnumDef(it) => { |
101 | let def: EnumId = self.to_id(container.with_value(it))?; | 74 | let def: EnumId = self.to_id(db, container.with_value(it))?; |
102 | def.into() | 75 | def.into() |
103 | }, | 76 | }, |
104 | ast::StructDef(it) => { | 77 | ast::StructDef(it) => { |
105 | let def: StructId = self.to_id(container.with_value(it))?; | 78 | let def: StructId = self.to_id(db, container.with_value(it))?; |
106 | VariantId::from(def).into() | 79 | VariantId::from(def).into() |
107 | }, | 80 | }, |
108 | ast::UnionDef(it) => { | 81 | ast::UnionDef(it) => { |
109 | let def: UnionId = self.to_id(container.with_value(it))?; | 82 | let def: UnionId = self.to_id(db, container.with_value(it))?; |
110 | VariantId::from(def).into() | 83 | VariantId::from(def).into() |
111 | }, | 84 | }, |
112 | ast::Module(it) => { | 85 | ast::Module(it) => { |
113 | let def: ModuleId = self.to_id(container.with_value(it))?; | 86 | let def: ModuleId = self.to_id(db, container.with_value(it))?; |
114 | def.into() | 87 | def.into() |
115 | }, | 88 | }, |
116 | _ => { continue }, | 89 | _ => { continue }, |
@@ -119,12 +92,11 @@ impl<DB: HirDatabase> SourceBinder<'_, DB> { | |||
119 | return Some(res); | 92 | return Some(res); |
120 | } | 93 | } |
121 | 94 | ||
122 | let c = self.to_module_def(src.file_id.original_file(self.db))?; | 95 | let c = self.to_module_def(db, src.file_id.original_file(db))?; |
123 | Some(c.id.into()) | 96 | Some(c.id.into()) |
124 | } | 97 | } |
125 | 98 | ||
126 | fn child_by_source(&mut self, container: ChildContainer) -> &DynMap { | 99 | fn child_by_source(&mut self, db: &impl HirDatabase, container: ChildContainer) -> &DynMap { |
127 | let db = self.db; | ||
128 | self.child_by_source_cache.entry(container).or_insert_with(|| match container { | 100 | self.child_by_source_cache.entry(container).or_insert_with(|| match container { |
129 | ChildContainer::DefWithBodyId(it) => it.child_by_source(db), | 101 | ChildContainer::DefWithBodyId(it) => it.child_by_source(db), |
130 | ChildContainer::ModuleId(it) => it.child_by_source(db), | 102 | ChildContainer::ModuleId(it) => it.child_by_source(db), |
@@ -137,16 +109,20 @@ impl<DB: HirDatabase> SourceBinder<'_, DB> { | |||
137 | } | 109 | } |
138 | } | 110 | } |
139 | 111 | ||
140 | pub trait ToId: Sized { | 112 | pub(crate) trait ToId: Sized { |
141 | type ID: Sized + Copy + 'static; | 113 | type ID: Sized + Copy + 'static; |
142 | fn to_id<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>) | 114 | fn to_id<DB: HirDatabase>( |
143 | -> Option<Self::ID>; | 115 | db: &DB, |
116 | sb: &mut SourceBinder, | ||
117 | src: InFile<Self>, | ||
118 | ) -> Option<Self::ID>; | ||
144 | } | 119 | } |
145 | 120 | ||
146 | pub trait ToDef: Sized + AstNode + 'static { | 121 | pub trait ToDef: Sized + AstNode + 'static { |
147 | type Def; | 122 | type Def; |
148 | fn to_def<DB: HirDatabase>( | 123 | fn to_def<DB: HirDatabase>( |
149 | sb: &mut SourceBinder<'_, DB>, | 124 | db: &DB, |
125 | sb: &mut SourceBinder, | ||
150 | src: InFile<Self>, | 126 | src: InFile<Self>, |
151 | ) -> Option<Self::Def>; | 127 | ) -> Option<Self::Def>; |
152 | } | 128 | } |
@@ -155,9 +131,9 @@ macro_rules! to_def_impls { | |||
155 | ($(($def:path, $ast:path)),* ,) => {$( | 131 | ($(($def:path, $ast:path)),* ,) => {$( |
156 | impl ToDef for $ast { | 132 | impl ToDef for $ast { |
157 | type Def = $def; | 133 | type Def = $def; |
158 | fn to_def<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>) | 134 | fn to_def<DB: HirDatabase>(db: &DB, sb: &mut SourceBinder, src: InFile<Self>) |
159 | -> Option<Self::Def> | 135 | -> Option<Self::Def> |
160 | { sb.to_id(src).map(Into::into) } | 136 | { sb.to_id(db, src).map(Into::into) } |
161 | } | 137 | } |
162 | )*} | 138 | )*} |
163 | } | 139 | } |
@@ -179,7 +155,7 @@ to_def_impls![ | |||
179 | ]; | 155 | ]; |
180 | 156 | ||
181 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | 157 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
182 | enum ChildContainer { | 158 | pub(crate) enum ChildContainer { |
183 | DefWithBodyId(DefWithBodyId), | 159 | DefWithBodyId(DefWithBodyId), |
184 | ModuleId(ModuleId), | 160 | ModuleId(ModuleId), |
185 | TraitId(TraitId), | 161 | TraitId(TraitId), |
@@ -201,7 +177,7 @@ impl_froms! { | |||
201 | GenericDefId | 177 | GenericDefId |
202 | } | 178 | } |
203 | 179 | ||
204 | pub trait ToIdByKey: Sized + AstNode + 'static { | 180 | pub(crate) trait ToIdByKey: Sized + AstNode + 'static { |
205 | type ID: Sized + Copy + 'static; | 181 | type ID: Sized + Copy + 'static; |
206 | const KEY: Key<Self, Self::ID>; | 182 | const KEY: Key<Self, Self::ID>; |
207 | } | 183 | } |
@@ -209,11 +185,11 @@ pub trait ToIdByKey: Sized + AstNode + 'static { | |||
209 | impl<T: ToIdByKey> ToId for T { | 185 | impl<T: ToIdByKey> ToId for T { |
210 | type ID = <T as ToIdByKey>::ID; | 186 | type ID = <T as ToIdByKey>::ID; |
211 | fn to_id<DB: HirDatabase>( | 187 | fn to_id<DB: HirDatabase>( |
212 | sb: &mut SourceBinder<'_, DB>, | 188 | db: &DB, |
189 | sb: &mut SourceBinder, | ||
213 | src: InFile<Self>, | 190 | src: InFile<Self>, |
214 | ) -> Option<Self::ID> { | 191 | ) -> Option<Self::ID> { |
215 | let container = sb.find_container(src.as_ref().map(|it| it.syntax()))?; | 192 | let container = sb.find_container(db, src.as_ref().map(|it| it.syntax()))?; |
216 | let db = sb.db; | ||
217 | let dyn_map = | 193 | let dyn_map = |
218 | &*sb.child_by_source_cache.entry(container).or_insert_with(|| match container { | 194 | &*sb.child_by_source_cache.entry(container).or_insert_with(|| match container { |
219 | ChildContainer::DefWithBodyId(it) => it.child_by_source(db), | 195 | ChildContainer::DefWithBodyId(it) => it.child_by_source(db), |
@@ -255,15 +231,15 @@ to_id_key_impls![ | |||
255 | impl ToId for ast::MacroCall { | 231 | impl ToId for ast::MacroCall { |
256 | type ID = MacroDefId; | 232 | type ID = MacroDefId; |
257 | fn to_id<DB: HirDatabase>( | 233 | fn to_id<DB: HirDatabase>( |
258 | sb: &mut SourceBinder<'_, DB>, | 234 | db: &DB, |
235 | sb: &mut SourceBinder, | ||
259 | src: InFile<Self>, | 236 | src: InFile<Self>, |
260 | ) -> Option<Self::ID> { | 237 | ) -> Option<Self::ID> { |
261 | let kind = MacroDefKind::Declarative; | 238 | let kind = MacroDefKind::Declarative; |
262 | 239 | ||
263 | let krate = sb.to_module_def(src.file_id.original_file(sb.db))?.id.krate; | 240 | let krate = sb.to_module_def(db, src.file_id.original_file(db))?.id.krate; |
264 | 241 | ||
265 | let ast_id = | 242 | let ast_id = Some(AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.value))); |
266 | Some(AstId::new(src.file_id, sb.db.ast_id_map(src.file_id).ast_id(&src.value))); | ||
267 | 243 | ||
268 | Some(MacroDefId { krate: Some(krate), ast_id, kind }) | 244 | Some(MacroDefId { krate: Some(krate), ast_id, kind }) |
269 | } | 245 | } |
@@ -272,20 +248,20 @@ impl ToId for ast::MacroCall { | |||
272 | impl ToDef for ast::BindPat { | 248 | impl ToDef for ast::BindPat { |
273 | type Def = Local; | 249 | type Def = Local; |
274 | 250 | ||
275 | fn to_def<DB: HirDatabase>(sb: &mut SourceBinder<'_, DB>, src: InFile<Self>) -> Option<Local> { | 251 | fn to_def<DB: HirDatabase>(db: &DB, sb: &mut SourceBinder, src: InFile<Self>) -> Option<Local> { |
276 | let file_id = src.file_id; | 252 | let file_id = src.file_id; |
277 | let parent: DefWithBodyId = src.value.syntax().ancestors().find_map(|it| { | 253 | let parent: DefWithBodyId = src.value.syntax().ancestors().find_map(|it| { |
278 | let res = match_ast! { | 254 | let res = match_ast! { |
279 | match it { | 255 | match it { |
280 | ast::ConstDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | 256 | ast::ConstDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, |
281 | ast::StaticDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | 257 | ast::StaticDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, |
282 | ast::FnDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | 258 | ast::FnDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, |
283 | _ => return None, | 259 | _ => return None, |
284 | } | 260 | } |
285 | }; | 261 | }; |
286 | Some(res) | 262 | Some(res) |
287 | })?; | 263 | })?; |
288 | let (_body, source_map) = sb.db.body_with_source_map(parent); | 264 | let (_body, source_map) = db.body_with_source_map(parent); |
289 | let src = src.map(ast::Pat::from); | 265 | let src = src.map(ast::Pat::from); |
290 | let pat_id = source_map.node_pat(src.as_ref())?; | 266 | let pat_id = source_map.node_pat(src.as_ref())?; |
291 | Some(Local { parent: parent.into(), pat_id }) | 267 | Some(Local { parent: parent.into(), pat_id }) |
@@ -296,26 +272,26 @@ impl ToDef for ast::TypeParam { | |||
296 | type Def = TypeParam; | 272 | type Def = TypeParam; |
297 | 273 | ||
298 | fn to_def<DB: HirDatabase>( | 274 | fn to_def<DB: HirDatabase>( |
299 | sb: &mut SourceBinder<'_, DB>, | 275 | db: &DB, |
276 | sb: &mut SourceBinder, | ||
300 | src: InFile<ast::TypeParam>, | 277 | src: InFile<ast::TypeParam>, |
301 | ) -> Option<TypeParam> { | 278 | ) -> Option<TypeParam> { |
302 | let mut sb = SourceBinder::new(sb.db); | ||
303 | let file_id = src.file_id; | 279 | let file_id = src.file_id; |
304 | let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| { | 280 | let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| { |
305 | let res = match_ast! { | 281 | let res = match_ast! { |
306 | match it { | 282 | match it { |
307 | ast::FnDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | 283 | ast::FnDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, |
308 | ast::StructDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | 284 | ast::StructDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, |
309 | ast::EnumDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | 285 | ast::EnumDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, |
310 | ast::TraitDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | 286 | ast::TraitDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, |
311 | ast::TypeAliasDef(value) => { sb.to_id(InFile { value, file_id})?.into() }, | 287 | ast::TypeAliasDef(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, |
312 | ast::ImplBlock(value) => { sb.to_id(InFile { value, file_id})?.into() }, | 288 | ast::ImplBlock(value) => { sb.to_id(db, InFile { value, file_id})?.into() }, |
313 | _ => return None, | 289 | _ => return None, |
314 | } | 290 | } |
315 | }; | 291 | }; |
316 | Some(res) | 292 | Some(res) |
317 | })?; | 293 | })?; |
318 | let &id = sb.child_by_source(parent.into())[keys::TYPE_PARAM].get(&src)?; | 294 | let &id = sb.child_by_source(db, parent.into())[keys::TYPE_PARAM].get(&src)?; |
319 | Some(TypeParam { id }) | 295 | Some(TypeParam { id }) |
320 | } | 296 | } |
321 | } | 297 | } |
@@ -324,7 +300,8 @@ impl ToId for ast::Module { | |||
324 | type ID = ModuleId; | 300 | type ID = ModuleId; |
325 | 301 | ||
326 | fn to_id<DB: HirDatabase>( | 302 | fn to_id<DB: HirDatabase>( |
327 | sb: &mut SourceBinder<'_, DB>, | 303 | db: &DB, |
304 | sb: &mut SourceBinder, | ||
328 | src: InFile<ast::Module>, | 305 | src: InFile<ast::Module>, |
329 | ) -> Option<ModuleId> { | 306 | ) -> Option<ModuleId> { |
330 | { | 307 | { |
@@ -333,7 +310,7 @@ impl ToId for ast::Module { | |||
333 | .as_ref() | 310 | .as_ref() |
334 | .map(|it| it.syntax()) | 311 | .map(|it| it.syntax()) |
335 | .cloned() | 312 | .cloned() |
336 | .ancestors_with_macros(sb.db) | 313 | .ancestors_with_macros(db) |
337 | .skip(1) | 314 | .skip(1) |
338 | .find_map(|it| { | 315 | .find_map(|it| { |
339 | let m = ast::Module::cast(it.value.clone())?; | 316 | let m = ast::Module::cast(it.value.clone())?; |
@@ -341,15 +318,15 @@ impl ToId for ast::Module { | |||
341 | }); | 318 | }); |
342 | 319 | ||
343 | let parent_module = match parent_declaration { | 320 | let parent_module = match parent_declaration { |
344 | Some(parent_declaration) => sb.to_id(parent_declaration)?, | 321 | Some(parent_declaration) => sb.to_id(db, parent_declaration)?, |
345 | None => { | 322 | None => { |
346 | let file_id = src.file_id.original_file(sb.db); | 323 | let file_id = src.file_id.original_file(db); |
347 | sb.to_module_def(file_id)?.id | 324 | sb.to_module_def(db, file_id)?.id |
348 | } | 325 | } |
349 | }; | 326 | }; |
350 | 327 | ||
351 | let child_name = src.value.name()?.as_name(); | 328 | let child_name = src.value.name()?.as_name(); |
352 | let def_map = sb.db.crate_def_map(parent_module.krate); | 329 | let def_map = db.crate_def_map(parent_module.krate); |
353 | let child_id = *def_map[parent_module.local_id].children.get(&child_name)?; | 330 | let child_id = *def_map[parent_module.local_id].children.get(&child_name)?; |
354 | Some(ModuleId { krate: parent_module.krate, local_id: child_id }) | 331 | Some(ModuleId { krate: parent_module.krate, local_id: child_id }) |
355 | } | 332 | } |