diff options
Diffstat (limited to 'crates/hir_def/src/lib.rs')
-rw-r--r-- | crates/hir_def/src/lib.rs | 541 |
1 files changed, 541 insertions, 0 deletions
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs new file mode 100644 index 000000000..f24a1dd77 --- /dev/null +++ b/crates/hir_def/src/lib.rs | |||
@@ -0,0 +1,541 @@ | |||
1 | //! `hir_def` crate contains everything between macro expansion and type | ||
2 | //! inference. | ||
3 | //! | ||
4 | //! It defines various items (structs, enums, traits) which comprises Rust code, | ||
5 | //! as well as an algorithm for resolving paths to such entities. | ||
6 | //! | ||
7 | //! Note that `hir_def` is a work in progress, so not all of the above is | ||
8 | //! actually true. | ||
9 | |||
10 | #[allow(unused)] | ||
11 | macro_rules! eprintln { | ||
12 | ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; | ||
13 | } | ||
14 | |||
15 | pub mod db; | ||
16 | |||
17 | pub mod attr; | ||
18 | pub mod path; | ||
19 | pub mod type_ref; | ||
20 | pub mod builtin_type; | ||
21 | pub mod diagnostics; | ||
22 | pub mod per_ns; | ||
23 | pub mod item_scope; | ||
24 | |||
25 | pub mod dyn_map; | ||
26 | pub mod keys; | ||
27 | |||
28 | pub mod item_tree; | ||
29 | |||
30 | pub mod adt; | ||
31 | pub mod data; | ||
32 | pub mod generics; | ||
33 | pub mod lang_item; | ||
34 | pub mod docs; | ||
35 | |||
36 | pub mod expr; | ||
37 | pub mod body; | ||
38 | pub mod resolver; | ||
39 | |||
40 | mod trace; | ||
41 | pub mod nameres; | ||
42 | |||
43 | pub mod src; | ||
44 | pub mod child_by_source; | ||
45 | |||
46 | pub mod visibility; | ||
47 | pub mod find_path; | ||
48 | pub mod import_map; | ||
49 | |||
50 | #[cfg(test)] | ||
51 | mod test_db; | ||
52 | |||
53 | use std::hash::{Hash, Hasher}; | ||
54 | |||
55 | use arena::Idx; | ||
56 | use base_db::{impl_intern_key, salsa, CrateId}; | ||
57 | use hir_expand::{ | ||
58 | ast_id_map::FileAstId, eager::expand_eager_macro, hygiene::Hygiene, AstId, HirFileId, InFile, | ||
59 | MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | ||
60 | }; | ||
61 | use syntax::ast; | ||
62 | |||
63 | use crate::builtin_type::BuiltinType; | ||
64 | use item_tree::{ | ||
65 | Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, ModItem, Static, Struct, Trait, | ||
66 | TypeAlias, Union, | ||
67 | }; | ||
68 | use stdx::impl_from; | ||
69 | |||
70 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
71 | pub struct ModuleId { | ||
72 | pub krate: CrateId, | ||
73 | pub local_id: LocalModuleId, | ||
74 | } | ||
75 | |||
76 | /// An ID of a module, **local** to a specific crate | ||
77 | pub type LocalModuleId = Idx<nameres::ModuleData>; | ||
78 | |||
79 | #[derive(Debug)] | ||
80 | pub struct ItemLoc<N: ItemTreeNode> { | ||
81 | pub container: ContainerId, | ||
82 | pub id: ItemTreeId<N>, | ||
83 | } | ||
84 | |||
85 | impl<N: ItemTreeNode> Clone for ItemLoc<N> { | ||
86 | fn clone(&self) -> Self { | ||
87 | Self { container: self.container, id: self.id } | ||
88 | } | ||
89 | } | ||
90 | |||
91 | impl<N: ItemTreeNode> Copy for ItemLoc<N> {} | ||
92 | |||
93 | impl<N: ItemTreeNode> PartialEq for ItemLoc<N> { | ||
94 | fn eq(&self, other: &Self) -> bool { | ||
95 | self.container == other.container && self.id == other.id | ||
96 | } | ||
97 | } | ||
98 | |||
99 | impl<N: ItemTreeNode> Eq for ItemLoc<N> {} | ||
100 | |||
101 | impl<N: ItemTreeNode> Hash for ItemLoc<N> { | ||
102 | fn hash<H: Hasher>(&self, state: &mut H) { | ||
103 | self.container.hash(state); | ||
104 | self.id.hash(state); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | #[derive(Debug)] | ||
109 | pub struct AssocItemLoc<N: ItemTreeNode> { | ||
110 | pub container: AssocContainerId, | ||
111 | pub id: ItemTreeId<N>, | ||
112 | } | ||
113 | |||
114 | impl<N: ItemTreeNode> Clone for AssocItemLoc<N> { | ||
115 | fn clone(&self) -> Self { | ||
116 | Self { container: self.container, id: self.id } | ||
117 | } | ||
118 | } | ||
119 | |||
120 | impl<N: ItemTreeNode> Copy for AssocItemLoc<N> {} | ||
121 | |||
122 | impl<N: ItemTreeNode> PartialEq for AssocItemLoc<N> { | ||
123 | fn eq(&self, other: &Self) -> bool { | ||
124 | self.container == other.container && self.id == other.id | ||
125 | } | ||
126 | } | ||
127 | |||
128 | impl<N: ItemTreeNode> Eq for AssocItemLoc<N> {} | ||
129 | |||
130 | impl<N: ItemTreeNode> Hash for AssocItemLoc<N> { | ||
131 | fn hash<H: Hasher>(&self, state: &mut H) { | ||
132 | self.container.hash(state); | ||
133 | self.id.hash(state); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | macro_rules! impl_intern { | ||
138 | ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => { | ||
139 | impl_intern_key!($id); | ||
140 | |||
141 | impl Intern for $loc { | ||
142 | type ID = $id; | ||
143 | fn intern(self, db: &dyn db::DefDatabase) -> $id { | ||
144 | db.$intern(self) | ||
145 | } | ||
146 | } | ||
147 | |||
148 | impl Lookup for $id { | ||
149 | type Data = $loc; | ||
150 | fn lookup(&self, db: &dyn db::DefDatabase) -> $loc { | ||
151 | db.$lookup(*self) | ||
152 | } | ||
153 | } | ||
154 | }; | ||
155 | } | ||
156 | |||
157 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
158 | pub struct FunctionId(salsa::InternId); | ||
159 | type FunctionLoc = AssocItemLoc<Function>; | ||
160 | impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function); | ||
161 | |||
162 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] | ||
163 | pub struct StructId(salsa::InternId); | ||
164 | type StructLoc = ItemLoc<Struct>; | ||
165 | impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); | ||
166 | |||
167 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] | ||
168 | pub struct UnionId(salsa::InternId); | ||
169 | pub type UnionLoc = ItemLoc<Union>; | ||
170 | impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); | ||
171 | |||
172 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] | ||
173 | pub struct EnumId(salsa::InternId); | ||
174 | pub type EnumLoc = ItemLoc<Enum>; | ||
175 | impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); | ||
176 | |||
177 | // FIXME: rename to `VariantId`, only enums can ave variants | ||
178 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
179 | pub struct EnumVariantId { | ||
180 | pub parent: EnumId, | ||
181 | pub local_id: LocalEnumVariantId, | ||
182 | } | ||
183 | |||
184 | pub type LocalEnumVariantId = Idx<adt::EnumVariantData>; | ||
185 | |||
186 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
187 | pub struct FieldId { | ||
188 | pub parent: VariantId, | ||
189 | pub local_id: LocalFieldId, | ||
190 | } | ||
191 | |||
192 | pub type LocalFieldId = Idx<adt::FieldData>; | ||
193 | |||
194 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
195 | pub struct ConstId(salsa::InternId); | ||
196 | type ConstLoc = AssocItemLoc<Const>; | ||
197 | impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const); | ||
198 | |||
199 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
200 | pub struct StaticId(salsa::InternId); | ||
201 | pub type StaticLoc = ItemLoc<Static>; | ||
202 | impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static); | ||
203 | |||
204 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
205 | pub struct TraitId(salsa::InternId); | ||
206 | pub type TraitLoc = ItemLoc<Trait>; | ||
207 | impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait); | ||
208 | |||
209 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
210 | pub struct TypeAliasId(salsa::InternId); | ||
211 | type TypeAliasLoc = AssocItemLoc<TypeAlias>; | ||
212 | impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias); | ||
213 | |||
214 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] | ||
215 | pub struct ImplId(salsa::InternId); | ||
216 | type ImplLoc = ItemLoc<Impl>; | ||
217 | impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); | ||
218 | |||
219 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
220 | pub struct TypeParamId { | ||
221 | pub parent: GenericDefId, | ||
222 | pub local_id: LocalTypeParamId, | ||
223 | } | ||
224 | |||
225 | pub type LocalTypeParamId = Idx<generics::TypeParamData>; | ||
226 | |||
227 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
228 | pub enum ContainerId { | ||
229 | ModuleId(ModuleId), | ||
230 | DefWithBodyId(DefWithBodyId), | ||
231 | } | ||
232 | |||
233 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
234 | pub enum AssocContainerId { | ||
235 | ContainerId(ContainerId), | ||
236 | ImplId(ImplId), | ||
237 | TraitId(TraitId), | ||
238 | } | ||
239 | impl_from!(ContainerId for AssocContainerId); | ||
240 | |||
241 | /// A Data Type | ||
242 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | ||
243 | pub enum AdtId { | ||
244 | StructId(StructId), | ||
245 | UnionId(UnionId), | ||
246 | EnumId(EnumId), | ||
247 | } | ||
248 | impl_from!(StructId, UnionId, EnumId for AdtId); | ||
249 | |||
250 | /// The defs which can be visible in the module. | ||
251 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
252 | pub enum ModuleDefId { | ||
253 | ModuleId(ModuleId), | ||
254 | FunctionId(FunctionId), | ||
255 | AdtId(AdtId), | ||
256 | // Can't be directly declared, but can be imported. | ||
257 | EnumVariantId(EnumVariantId), | ||
258 | ConstId(ConstId), | ||
259 | StaticId(StaticId), | ||
260 | TraitId(TraitId), | ||
261 | TypeAliasId(TypeAliasId), | ||
262 | BuiltinType(BuiltinType), | ||
263 | } | ||
264 | impl_from!( | ||
265 | ModuleId, | ||
266 | FunctionId, | ||
267 | AdtId(StructId, EnumId, UnionId), | ||
268 | EnumVariantId, | ||
269 | ConstId, | ||
270 | StaticId, | ||
271 | TraitId, | ||
272 | TypeAliasId, | ||
273 | BuiltinType | ||
274 | for ModuleDefId | ||
275 | ); | ||
276 | |||
277 | /// The defs which have a body. | ||
278 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
279 | pub enum DefWithBodyId { | ||
280 | FunctionId(FunctionId), | ||
281 | StaticId(StaticId), | ||
282 | ConstId(ConstId), | ||
283 | } | ||
284 | |||
285 | impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId); | ||
286 | |||
287 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | ||
288 | pub enum AssocItemId { | ||
289 | FunctionId(FunctionId), | ||
290 | ConstId(ConstId), | ||
291 | TypeAliasId(TypeAliasId), | ||
292 | } | ||
293 | // FIXME: not every function, ... is actually an assoc item. maybe we should make | ||
294 | // sure that you can only turn actual assoc items into AssocItemIds. This would | ||
295 | // require not implementing From, and instead having some checked way of | ||
296 | // casting them, and somehow making the constructors private, which would be annoying. | ||
297 | impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId); | ||
298 | |||
299 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | ||
300 | pub enum GenericDefId { | ||
301 | FunctionId(FunctionId), | ||
302 | AdtId(AdtId), | ||
303 | TraitId(TraitId), | ||
304 | TypeAliasId(TypeAliasId), | ||
305 | ImplId(ImplId), | ||
306 | // enum variants cannot have generics themselves, but their parent enums | ||
307 | // can, and this makes some code easier to write | ||
308 | EnumVariantId(EnumVariantId), | ||
309 | // consts can have type parameters from their parents (i.e. associated consts of traits) | ||
310 | ConstId(ConstId), | ||
311 | } | ||
312 | impl_from!( | ||
313 | FunctionId, | ||
314 | AdtId(StructId, EnumId, UnionId), | ||
315 | TraitId, | ||
316 | TypeAliasId, | ||
317 | ImplId, | ||
318 | EnumVariantId, | ||
319 | ConstId | ||
320 | for GenericDefId | ||
321 | ); | ||
322 | |||
323 | impl From<AssocItemId> for GenericDefId { | ||
324 | fn from(item: AssocItemId) -> Self { | ||
325 | match item { | ||
326 | AssocItemId::FunctionId(f) => f.into(), | ||
327 | AssocItemId::ConstId(c) => c.into(), | ||
328 | AssocItemId::TypeAliasId(t) => t.into(), | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | |||
333 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
334 | pub enum AttrDefId { | ||
335 | ModuleId(ModuleId), | ||
336 | FieldId(FieldId), | ||
337 | AdtId(AdtId), | ||
338 | FunctionId(FunctionId), | ||
339 | EnumVariantId(EnumVariantId), | ||
340 | StaticId(StaticId), | ||
341 | ConstId(ConstId), | ||
342 | TraitId(TraitId), | ||
343 | TypeAliasId(TypeAliasId), | ||
344 | MacroDefId(MacroDefId), | ||
345 | ImplId(ImplId), | ||
346 | } | ||
347 | |||
348 | impl_from!( | ||
349 | ModuleId, | ||
350 | FieldId, | ||
351 | AdtId(StructId, EnumId, UnionId), | ||
352 | EnumVariantId, | ||
353 | StaticId, | ||
354 | ConstId, | ||
355 | FunctionId, | ||
356 | TraitId, | ||
357 | TypeAliasId, | ||
358 | MacroDefId, | ||
359 | ImplId | ||
360 | for AttrDefId | ||
361 | ); | ||
362 | |||
363 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
364 | pub enum VariantId { | ||
365 | EnumVariantId(EnumVariantId), | ||
366 | StructId(StructId), | ||
367 | UnionId(UnionId), | ||
368 | } | ||
369 | impl_from!(EnumVariantId, StructId, UnionId for VariantId); | ||
370 | |||
371 | trait Intern { | ||
372 | type ID; | ||
373 | fn intern(self, db: &dyn db::DefDatabase) -> Self::ID; | ||
374 | } | ||
375 | |||
376 | pub trait Lookup { | ||
377 | type Data; | ||
378 | fn lookup(&self, db: &dyn db::DefDatabase) -> Self::Data; | ||
379 | } | ||
380 | |||
381 | pub trait HasModule { | ||
382 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId; | ||
383 | } | ||
384 | |||
385 | impl HasModule for ContainerId { | ||
386 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | ||
387 | match *self { | ||
388 | ContainerId::ModuleId(it) => it, | ||
389 | ContainerId::DefWithBodyId(it) => it.module(db), | ||
390 | } | ||
391 | } | ||
392 | } | ||
393 | |||
394 | impl HasModule for AssocContainerId { | ||
395 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | ||
396 | match *self { | ||
397 | AssocContainerId::ContainerId(it) => it.module(db), | ||
398 | AssocContainerId::ImplId(it) => it.lookup(db).container.module(db), | ||
399 | AssocContainerId::TraitId(it) => it.lookup(db).container.module(db), | ||
400 | } | ||
401 | } | ||
402 | } | ||
403 | |||
404 | impl<N: ItemTreeNode> HasModule for AssocItemLoc<N> { | ||
405 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | ||
406 | self.container.module(db) | ||
407 | } | ||
408 | } | ||
409 | |||
410 | impl HasModule for AdtId { | ||
411 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | ||
412 | match self { | ||
413 | AdtId::StructId(it) => it.lookup(db).container, | ||
414 | AdtId::UnionId(it) => it.lookup(db).container, | ||
415 | AdtId::EnumId(it) => it.lookup(db).container, | ||
416 | } | ||
417 | .module(db) | ||
418 | } | ||
419 | } | ||
420 | |||
421 | impl HasModule for DefWithBodyId { | ||
422 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | ||
423 | match self { | ||
424 | DefWithBodyId::FunctionId(it) => it.lookup(db).module(db), | ||
425 | DefWithBodyId::StaticId(it) => it.lookup(db).module(db), | ||
426 | DefWithBodyId::ConstId(it) => it.lookup(db).module(db), | ||
427 | } | ||
428 | } | ||
429 | } | ||
430 | |||
431 | impl DefWithBodyId { | ||
432 | pub fn as_mod_item(self, db: &dyn db::DefDatabase) -> ModItem { | ||
433 | match self { | ||
434 | DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(), | ||
435 | DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(), | ||
436 | DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(), | ||
437 | } | ||
438 | } | ||
439 | } | ||
440 | |||
441 | impl HasModule for GenericDefId { | ||
442 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | ||
443 | match self { | ||
444 | GenericDefId::FunctionId(it) => it.lookup(db).module(db), | ||
445 | GenericDefId::AdtId(it) => it.module(db), | ||
446 | GenericDefId::TraitId(it) => it.lookup(db).container.module(db), | ||
447 | GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), | ||
448 | GenericDefId::ImplId(it) => it.lookup(db).container.module(db), | ||
449 | GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db), | ||
450 | GenericDefId::ConstId(it) => it.lookup(db).module(db), | ||
451 | } | ||
452 | } | ||
453 | } | ||
454 | |||
455 | impl HasModule for StaticLoc { | ||
456 | fn module(&self, db: &dyn db::DefDatabase) -> ModuleId { | ||
457 | self.container.module(db) | ||
458 | } | ||
459 | } | ||
460 | |||
461 | /// A helper trait for converting to MacroCallId | ||
462 | pub trait AsMacroCall { | ||
463 | fn as_call_id( | ||
464 | &self, | ||
465 | db: &dyn db::DefDatabase, | ||
466 | krate: CrateId, | ||
467 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
468 | ) -> Option<MacroCallId>; | ||
469 | } | ||
470 | |||
471 | impl AsMacroCall for InFile<&ast::MacroCall> { | ||
472 | fn as_call_id( | ||
473 | &self, | ||
474 | db: &dyn db::DefDatabase, | ||
475 | krate: CrateId, | ||
476 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
477 | ) -> Option<MacroCallId> { | ||
478 | let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); | ||
479 | let h = Hygiene::new(db.upcast(), self.file_id); | ||
480 | let path = path::ModPath::from_src(self.value.path()?, &h)?; | ||
481 | |||
482 | AstIdWithPath::new(ast_id.file_id, ast_id.value, path).as_call_id(db, krate, resolver) | ||
483 | } | ||
484 | } | ||
485 | |||
486 | /// Helper wrapper for `AstId` with `ModPath` | ||
487 | #[derive(Clone, Debug, Eq, PartialEq)] | ||
488 | struct AstIdWithPath<T: ast::AstNode> { | ||
489 | pub ast_id: AstId<T>, | ||
490 | pub path: path::ModPath, | ||
491 | } | ||
492 | |||
493 | impl<T: ast::AstNode> AstIdWithPath<T> { | ||
494 | pub fn new(file_id: HirFileId, ast_id: FileAstId<T>, path: path::ModPath) -> AstIdWithPath<T> { | ||
495 | AstIdWithPath { ast_id: AstId::new(file_id, ast_id), path } | ||
496 | } | ||
497 | } | ||
498 | |||
499 | impl AsMacroCall for AstIdWithPath<ast::MacroCall> { | ||
500 | fn as_call_id( | ||
501 | &self, | ||
502 | db: &dyn db::DefDatabase, | ||
503 | krate: CrateId, | ||
504 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
505 | ) -> Option<MacroCallId> { | ||
506 | let def: MacroDefId = resolver(self.path.clone())?; | ||
507 | |||
508 | if let MacroDefKind::BuiltInEager(_) = def.kind { | ||
509 | let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db.upcast())); | ||
510 | let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id); | ||
511 | |||
512 | Some( | ||
513 | expand_eager_macro(db.upcast(), krate, macro_call, def, &|path: ast::Path| { | ||
514 | resolver(path::ModPath::from_src(path, &hygiene)?) | ||
515 | })? | ||
516 | .into(), | ||
517 | ) | ||
518 | } else { | ||
519 | Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into()) | ||
520 | } | ||
521 | } | ||
522 | } | ||
523 | |||
524 | impl AsMacroCall for AstIdWithPath<ast::Item> { | ||
525 | fn as_call_id( | ||
526 | &self, | ||
527 | db: &dyn db::DefDatabase, | ||
528 | krate: CrateId, | ||
529 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | ||
530 | ) -> Option<MacroCallId> { | ||
531 | let def = resolver(self.path.clone())?; | ||
532 | Some( | ||
533 | def.as_lazy_macro( | ||
534 | db.upcast(), | ||
535 | krate, | ||
536 | MacroCallKind::Attr(self.ast_id, self.path.segments.last()?.to_string()), | ||
537 | ) | ||
538 | .into(), | ||
539 | ) | ||
540 | } | ||
541 | } | ||