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 #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
11
12 #[allow(unused)]
13 macro_rules! eprintln {
14 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
15 }
16
17 pub mod db;
18
19 pub mod attr;
20 pub mod path;
21 pub mod builtin_type;
22 pub mod per_ns;
23 pub mod item_scope;
24
25 pub mod lower;
26 pub mod expander;
27
28 pub mod dyn_map;
29
30 pub mod item_tree;
31
32 pub mod data;
33 pub mod generics;
34 pub mod lang_item;
35
36 pub mod hir;
37 pub use self::hir::type_ref;
38 pub mod body;
39 pub mod resolver;
40
41 mod trace;
42 pub mod nameres;
43
44 pub mod src;
45 pub mod child_by_source;
46
47 pub mod visibility;
48 pub mod find_path;
49 pub mod import_map;
50
51 pub use rustc_abi as layout;
52 use triomphe::Arc;
53
54 #[cfg(test)]
55 mod test_db;
56 #[cfg(test)]
57 mod macro_expansion_tests;
58 mod pretty;
59
60 use std::{
61 hash::{Hash, Hasher},
62 panic::{RefUnwindSafe, UnwindSafe},
63 };
64
65 use base_db::{impl_intern_key, salsa, CrateId, ProcMacroKind};
66 use hir_expand::{
67 ast_id_map::FileAstId,
68 attrs::{Attr, AttrId, AttrInput},
69 builtin_attr_macro::BuiltinAttrExpander,
70 builtin_derive_macro::BuiltinDeriveExpander,
71 builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
72 db::ExpandDatabase,
73 eager::expand_eager_macro_input,
74 hygiene::Hygiene,
75 proc_macro::ProcMacroExpander,
76 AstId, ExpandError, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind,
77 MacroDefId, MacroDefKind, UnresolvedMacro,
78 };
79 use item_tree::ExternBlock;
80 use la_arena::Idx;
81 use nameres::DefMap;
82 use stdx::impl_from;
83 use syntax::ast;
84
85 use ::tt::token_id as tt;
86
87 use crate::{
88 builtin_type::BuiltinType,
89 data::adt::VariantData,
90 item_tree::{
91 Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, Static,
92 Struct, Trait, TraitAlias, TypeAlias, Union,
93 },
94 };
95
96 /// A `ModuleId` that is always a crate's root module.
97 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
98 pub struct CrateRootModuleId {
99 krate: CrateId,
100 }
101
102 impl CrateRootModuleId {
def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap>103 pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> {
104 db.crate_def_map(self.krate)
105 }
106
krate(self) -> CrateId107 pub fn krate(self) -> CrateId {
108 self.krate
109 }
110 }
111
112 impl From<CrateRootModuleId> for ModuleId {
113 fn from(CrateRootModuleId { krate }: CrateRootModuleId) -> Self {
114 ModuleId { krate, block: None, local_id: DefMap::ROOT }
115 }
116 }
117
118 impl From<CrateRootModuleId> for ModuleDefId {
from(value: CrateRootModuleId) -> Self119 fn from(value: CrateRootModuleId) -> Self {
120 ModuleDefId::ModuleId(value.into())
121 }
122 }
123
124 impl TryFrom<ModuleId> for CrateRootModuleId {
125 type Error = ();
126
127 fn try_from(ModuleId { krate, block, local_id }: ModuleId) -> Result<Self, Self::Error> {
128 if block.is_none() && local_id == DefMap::ROOT {
129 Ok(CrateRootModuleId { krate })
130 } else {
131 Err(())
132 }
133 }
134 }
135
136 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
137 pub struct ModuleId {
138 krate: CrateId,
139 /// If this `ModuleId` was derived from a `DefMap` for a block expression, this stores the
140 /// `BlockId` of that block expression. If `None`, this module is part of the crate-level
141 /// `DefMap` of `krate`.
142 block: Option<BlockId>,
143 /// The module's ID in its originating `DefMap`.
144 pub local_id: LocalModuleId,
145 }
146
147 impl ModuleId {
def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap>148 pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> {
149 match self.block {
150 Some(block) => db.block_def_map(block),
151 None => db.crate_def_map(self.krate),
152 }
153 }
154
krate(&self) -> CrateId155 pub fn krate(&self) -> CrateId {
156 self.krate
157 }
158
containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId>159 pub fn containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
160 self.def_map(db).containing_module(self.local_id)
161 }
162
containing_block(&self) -> Option<BlockId>163 pub fn containing_block(&self) -> Option<BlockId> {
164 self.block
165 }
166 }
167
168 /// An ID of a module, **local** to a `DefMap`.
169 pub type LocalModuleId = Idx<nameres::ModuleData>;
170
171 #[derive(Debug)]
172 pub struct ItemLoc<N: ItemTreeNode> {
173 pub container: ModuleId,
174 pub id: ItemTreeId<N>,
175 }
176
177 impl<N: ItemTreeNode> Clone for ItemLoc<N> {
clone(&self) -> Self178 fn clone(&self) -> Self {
179 Self { container: self.container, id: self.id }
180 }
181 }
182
183 impl<N: ItemTreeNode> Copy for ItemLoc<N> {}
184
185 impl<N: ItemTreeNode> PartialEq for ItemLoc<N> {
eq(&self, other: &Self) -> bool186 fn eq(&self, other: &Self) -> bool {
187 self.container == other.container && self.id == other.id
188 }
189 }
190
191 impl<N: ItemTreeNode> Eq for ItemLoc<N> {}
192
193 impl<N: ItemTreeNode> Hash for ItemLoc<N> {
hash<H: Hasher>(&self, state: &mut H)194 fn hash<H: Hasher>(&self, state: &mut H) {
195 self.container.hash(state);
196 self.id.hash(state);
197 }
198 }
199
200 #[derive(Debug)]
201 pub struct AssocItemLoc<N: ItemTreeNode> {
202 pub container: ItemContainerId,
203 pub id: ItemTreeId<N>,
204 }
205
206 impl<N: ItemTreeNode> Clone for AssocItemLoc<N> {
clone(&self) -> Self207 fn clone(&self) -> Self {
208 Self { container: self.container, id: self.id }
209 }
210 }
211
212 impl<N: ItemTreeNode> Copy for AssocItemLoc<N> {}
213
214 impl<N: ItemTreeNode> PartialEq for AssocItemLoc<N> {
eq(&self, other: &Self) -> bool215 fn eq(&self, other: &Self) -> bool {
216 self.container == other.container && self.id == other.id
217 }
218 }
219
220 impl<N: ItemTreeNode> Eq for AssocItemLoc<N> {}
221
222 impl<N: ItemTreeNode> Hash for AssocItemLoc<N> {
hash<H: Hasher>(&self, state: &mut H)223 fn hash<H: Hasher>(&self, state: &mut H) {
224 self.container.hash(state);
225 self.id.hash(state);
226 }
227 }
228
229 macro_rules! impl_intern {
230 ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
231 impl_intern_key!($id);
232
233 impl Intern for $loc {
234 type ID = $id;
235 fn intern(self, db: &dyn db::DefDatabase) -> $id {
236 db.$intern(self)
237 }
238 }
239
240 impl Lookup for $id {
241 type Data = $loc;
242 fn lookup(&self, db: &dyn db::DefDatabase) -> $loc {
243 db.$lookup(*self)
244 }
245 }
246 };
247 }
248
249 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
250 pub struct FunctionId(salsa::InternId);
251 type FunctionLoc = AssocItemLoc<Function>;
252 impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
253
254 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
255 pub struct StructId(salsa::InternId);
256 type StructLoc = ItemLoc<Struct>;
257 impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
258
259 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
260 pub struct UnionId(salsa::InternId);
261 pub type UnionLoc = ItemLoc<Union>;
262 impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
263
264 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
265 pub struct EnumId(salsa::InternId);
266 pub type EnumLoc = ItemLoc<Enum>;
267 impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
268
269 // FIXME: rename to `VariantId`, only enums can ave variants
270 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
271 pub struct EnumVariantId {
272 pub parent: EnumId,
273 pub local_id: LocalEnumVariantId,
274 }
275
276 pub type LocalEnumVariantId = Idx<data::adt::EnumVariantData>;
277
278 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
279 pub struct FieldId {
280 pub parent: VariantId,
281 pub local_id: LocalFieldId,
282 }
283
284 pub type LocalFieldId = Idx<data::adt::FieldData>;
285
286 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
287 pub struct ConstId(salsa::InternId);
288 type ConstLoc = AssocItemLoc<Const>;
289 impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const);
290
291 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
292 pub struct StaticId(salsa::InternId);
293 pub type StaticLoc = AssocItemLoc<Static>;
294 impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
295
296 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
297 pub struct TraitId(salsa::InternId);
298 pub type TraitLoc = ItemLoc<Trait>;
299 impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
300
301 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
302 pub struct TraitAliasId(salsa::InternId);
303 pub type TraitAliasLoc = ItemLoc<TraitAlias>;
304 impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias);
305
306 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
307 pub struct TypeAliasId(salsa::InternId);
308 type TypeAliasLoc = AssocItemLoc<TypeAlias>;
309 impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
310
311 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
312 pub struct ImplId(salsa::InternId);
313 type ImplLoc = ItemLoc<Impl>;
314 impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
315
316 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
317 pub struct ExternBlockId(salsa::InternId);
318 type ExternBlockLoc = ItemLoc<ExternBlock>;
319 impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block);
320
321 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
322 pub enum MacroExpander {
323 Declarative,
324 BuiltIn(BuiltinFnLikeExpander),
325 BuiltInAttr(BuiltinAttrExpander),
326 BuiltInDerive(BuiltinDeriveExpander),
327 BuiltInEager(EagerExpander),
328 }
329
330 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
331 pub struct Macro2Id(salsa::InternId);
332 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
333 pub struct Macro2Loc {
334 pub container: ModuleId,
335 pub id: ItemTreeId<MacroDef>,
336 pub expander: MacroExpander,
337 pub allow_internal_unsafe: bool,
338 }
339 impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2);
340
341 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
342 pub struct MacroRulesId(salsa::InternId);
343 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
344 pub struct MacroRulesLoc {
345 pub container: ModuleId,
346 pub id: ItemTreeId<MacroRules>,
347 pub expander: MacroExpander,
348 pub allow_internal_unsafe: bool,
349 pub local_inner: bool,
350 }
351 impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macro_rules);
352
353 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
354 pub struct ProcMacroId(salsa::InternId);
355 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
356 pub struct ProcMacroLoc {
357 pub container: CrateRootModuleId,
358 pub id: ItemTreeId<Function>,
359 pub expander: ProcMacroExpander,
360 pub kind: ProcMacroKind,
361 }
362 impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro);
363
364 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
365 pub struct BlockId(salsa::InternId);
366 #[derive(Debug, Hash, PartialEq, Eq, Clone)]
367 pub struct BlockLoc {
368 ast_id: AstId<ast::BlockExpr>,
369 /// The containing module.
370 module: ModuleId,
371 }
372 impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
373
374 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
375 pub struct TypeOrConstParamId {
376 pub parent: GenericDefId,
377 pub local_id: LocalTypeOrConstParamId,
378 }
379
380 /// A TypeOrConstParamId with an invariant that it actually belongs to a type
381 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
382 pub struct TypeParamId(TypeOrConstParamId);
383
384 impl TypeParamId {
parent(&self) -> GenericDefId385 pub fn parent(&self) -> GenericDefId {
386 self.0.parent
387 }
local_id(&self) -> LocalTypeOrConstParamId388 pub fn local_id(&self) -> LocalTypeOrConstParamId {
389 self.0.local_id
390 }
391 }
392
393 impl TypeParamId {
394 /// Caller should check if this toc id really belongs to a type
from_unchecked(x: TypeOrConstParamId) -> Self395 pub fn from_unchecked(x: TypeOrConstParamId) -> Self {
396 Self(x)
397 }
398 }
399
400 impl From<TypeParamId> for TypeOrConstParamId {
from(x: TypeParamId) -> Self401 fn from(x: TypeParamId) -> Self {
402 x.0
403 }
404 }
405
406 /// A TypeOrConstParamId with an invariant that it actually belongs to a const
407 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
408 pub struct ConstParamId(TypeOrConstParamId);
409
410 impl ConstParamId {
parent(&self) -> GenericDefId411 pub fn parent(&self) -> GenericDefId {
412 self.0.parent
413 }
local_id(&self) -> LocalTypeOrConstParamId414 pub fn local_id(&self) -> LocalTypeOrConstParamId {
415 self.0.local_id
416 }
417 }
418
419 impl ConstParamId {
420 /// Caller should check if this toc id really belongs to a const
from_unchecked(x: TypeOrConstParamId) -> Self421 pub fn from_unchecked(x: TypeOrConstParamId) -> Self {
422 Self(x)
423 }
424 }
425
426 impl From<ConstParamId> for TypeOrConstParamId {
from(x: ConstParamId) -> Self427 fn from(x: ConstParamId) -> Self {
428 x.0
429 }
430 }
431
432 pub type LocalTypeOrConstParamId = Idx<generics::TypeOrConstParamData>;
433
434 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
435 pub struct LifetimeParamId {
436 pub parent: GenericDefId,
437 pub local_id: LocalLifetimeParamId,
438 }
439 pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>;
440
441 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
442 pub enum ItemContainerId {
443 ExternBlockId(ExternBlockId),
444 ModuleId(ModuleId),
445 ImplId(ImplId),
446 TraitId(TraitId),
447 }
448 impl_from!(ModuleId for ItemContainerId);
449
450 /// A Data Type
451 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
452 pub enum AdtId {
453 StructId(StructId),
454 UnionId(UnionId),
455 EnumId(EnumId),
456 }
457 impl_from!(StructId, UnionId, EnumId for AdtId);
458
459 /// A macro
460 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
461 pub enum MacroId {
462 Macro2Id(Macro2Id),
463 MacroRulesId(MacroRulesId),
464 ProcMacroId(ProcMacroId),
465 }
466 impl_from!(Macro2Id, MacroRulesId, ProcMacroId for MacroId);
467
468 impl MacroId {
is_attribute(self, db: &dyn db::DefDatabase) -> bool469 pub fn is_attribute(self, db: &dyn db::DefDatabase) -> bool {
470 match self {
471 MacroId::ProcMacroId(it) => it.lookup(db).kind == ProcMacroKind::Attr,
472 _ => false,
473 }
474 }
475 }
476
477 /// A generic param
478 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
479 pub enum GenericParamId {
480 TypeParamId(TypeParamId),
481 ConstParamId(ConstParamId),
482 LifetimeParamId(LifetimeParamId),
483 }
484 impl_from!(TypeParamId, LifetimeParamId, ConstParamId for GenericParamId);
485
486 /// The defs which can be visible in the module.
487 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
488 pub enum ModuleDefId {
489 ModuleId(ModuleId),
490 FunctionId(FunctionId),
491 AdtId(AdtId),
492 // Can't be directly declared, but can be imported.
493 EnumVariantId(EnumVariantId),
494 ConstId(ConstId),
495 StaticId(StaticId),
496 TraitId(TraitId),
497 TraitAliasId(TraitAliasId),
498 TypeAliasId(TypeAliasId),
499 BuiltinType(BuiltinType),
500 MacroId(MacroId),
501 }
502 impl_from!(
503 MacroId(Macro2Id, MacroRulesId, ProcMacroId),
504 ModuleId,
505 FunctionId,
506 AdtId(StructId, EnumId, UnionId),
507 EnumVariantId,
508 ConstId,
509 StaticId,
510 TraitId,
511 TraitAliasId,
512 TypeAliasId,
513 BuiltinType
514 for ModuleDefId
515 );
516
517 /// Id of the anonymous const block expression and patterns. This is very similar to `ClosureId` and
518 /// shouldn't be a `DefWithBodyId` since its type inference is dependent on its parent.
519 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
520 pub struct ConstBlockId(salsa::InternId);
521 impl_intern!(ConstBlockId, ConstBlockLoc, intern_anonymous_const, lookup_intern_anonymous_const);
522
523 #[derive(Debug, Hash, PartialEq, Eq, Clone)]
524 pub struct ConstBlockLoc {
525 /// The parent of the anonymous const block.
526 pub parent: DefWithBodyId,
527 /// The root expression of this const block in the parent body.
528 pub root: hir::ExprId,
529 }
530
531 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
532 pub enum TypeOwnerId {
533 FunctionId(FunctionId),
534 StaticId(StaticId),
535 ConstId(ConstId),
536 InTypeConstId(InTypeConstId),
537 AdtId(AdtId),
538 TraitId(TraitId),
539 TraitAliasId(TraitAliasId),
540 TypeAliasId(TypeAliasId),
541 ImplId(ImplId),
542 EnumVariantId(EnumVariantId),
543 // FIXME(const-generic-body): ModuleId should not be a type owner. This needs to be fixed to make `TypeOwnerId` actually
544 // useful for assigning ids to in type consts.
545 ModuleId(ModuleId),
546 }
547
548 impl TypeOwnerId {
as_generic_def_id(self) -> Option<GenericDefId>549 fn as_generic_def_id(self) -> Option<GenericDefId> {
550 Some(match self {
551 TypeOwnerId::FunctionId(x) => GenericDefId::FunctionId(x),
552 TypeOwnerId::ConstId(x) => GenericDefId::ConstId(x),
553 TypeOwnerId::AdtId(x) => GenericDefId::AdtId(x),
554 TypeOwnerId::TraitId(x) => GenericDefId::TraitId(x),
555 TypeOwnerId::TraitAliasId(x) => GenericDefId::TraitAliasId(x),
556 TypeOwnerId::TypeAliasId(x) => GenericDefId::TypeAliasId(x),
557 TypeOwnerId::ImplId(x) => GenericDefId::ImplId(x),
558 TypeOwnerId::EnumVariantId(x) => GenericDefId::EnumVariantId(x),
559 TypeOwnerId::InTypeConstId(_) | TypeOwnerId::ModuleId(_) | TypeOwnerId::StaticId(_) => {
560 return None
561 }
562 })
563 }
564 }
565
566 impl_from!(
567 FunctionId,
568 StaticId,
569 ConstId,
570 InTypeConstId,
571 AdtId,
572 TraitId,
573 TraitAliasId,
574 TypeAliasId,
575 ImplId,
576 EnumVariantId,
577 ModuleId
578 for TypeOwnerId
579 );
580
581 // Every `DefWithBodyId` is a type owner, since bodies can contain type (e.g. `{ let x: Type = _; }`)
582 impl From<DefWithBodyId> for TypeOwnerId {
from(value: DefWithBodyId) -> Self583 fn from(value: DefWithBodyId) -> Self {
584 match value {
585 DefWithBodyId::FunctionId(x) => x.into(),
586 DefWithBodyId::StaticId(x) => x.into(),
587 DefWithBodyId::ConstId(x) => x.into(),
588 DefWithBodyId::InTypeConstId(x) => x.into(),
589 DefWithBodyId::VariantId(x) => x.into(),
590 }
591 }
592 }
593
594 impl From<GenericDefId> for TypeOwnerId {
from(value: GenericDefId) -> Self595 fn from(value: GenericDefId) -> Self {
596 match value {
597 GenericDefId::FunctionId(x) => x.into(),
598 GenericDefId::AdtId(x) => x.into(),
599 GenericDefId::TraitId(x) => x.into(),
600 GenericDefId::TraitAliasId(x) => x.into(),
601 GenericDefId::TypeAliasId(x) => x.into(),
602 GenericDefId::ImplId(x) => x.into(),
603 GenericDefId::EnumVariantId(x) => x.into(),
604 GenericDefId::ConstId(x) => x.into(),
605 }
606 }
607 }
608
609 // FIXME: This should not be a thing
610 /// A thing that we want to store in interned ids, but we don't know its type in `hir-def`. This is
611 /// currently only used in `InTypeConstId` for storing the type (which has type `Ty` defined in
612 /// the `hir-ty` crate) of the constant in its id, which is a temporary hack so we may want
613 /// to remove this after removing that.
614 pub trait OpaqueInternableThing:
615 std::any::Any + std::fmt::Debug + Sync + Send + UnwindSafe + RefUnwindSafe
616 {
as_any(&self) -> &dyn std::any::Any617 fn as_any(&self) -> &dyn std::any::Any;
box_any(&self) -> Box<dyn std::any::Any>618 fn box_any(&self) -> Box<dyn std::any::Any>;
dyn_hash(&self, state: &mut dyn Hasher)619 fn dyn_hash(&self, state: &mut dyn Hasher);
dyn_eq(&self, other: &dyn OpaqueInternableThing) -> bool620 fn dyn_eq(&self, other: &dyn OpaqueInternableThing) -> bool;
dyn_clone(&self) -> Box<dyn OpaqueInternableThing>621 fn dyn_clone(&self) -> Box<dyn OpaqueInternableThing>;
622 }
623
624 impl Hash for dyn OpaqueInternableThing {
hash<H: Hasher>(&self, state: &mut H)625 fn hash<H: Hasher>(&self, state: &mut H) {
626 self.dyn_hash(state);
627 }
628 }
629
630 impl PartialEq for dyn OpaqueInternableThing {
eq(&self, other: &Self) -> bool631 fn eq(&self, other: &Self) -> bool {
632 self.dyn_eq(other)
633 }
634 }
635
636 impl Eq for dyn OpaqueInternableThing {}
637
638 impl Clone for Box<dyn OpaqueInternableThing> {
clone(&self) -> Self639 fn clone(&self) -> Self {
640 self.dyn_clone()
641 }
642 }
643
644 // FIXME(const-generic-body): Use an stable id for in type consts.
645 //
646 // The current id uses `AstId<ast::ConstArg>` which will be changed by every change in the code. Ideally
647 // we should use an id which is relative to the type owner, so that every change will only invalidate the
648 // id if it happens inside of the type owner.
649 //
650 // The solution probably is to have some query on `TypeOwnerId` to traverse its constant children and store
651 // their `AstId` in a list (vector or arena), and use the index of that list in the id here. That query probably
652 // needs name resolution, and might go far and handles the whole path lowering or type lowering for a `TypeOwnerId`.
653 //
654 // Whatever path the solution takes, it should answer 3 questions at the same time:
655 // * Is the id stable enough?
656 // * How to find a constant id using an ast node / position in the source code? This is needed when we want to
657 // provide ide functionalities inside an in type const (which we currently don't support) e.g. go to definition
658 // for a local defined there. A complex id might have some trouble in this reverse mapping.
659 // * How to find the return type of a constant using its id? We have this data when we are doing type lowering
660 // and the name of the struct that contains this constant is resolved, so a query that only traverses the
661 // type owner by its syntax tree might have a hard time here.
662
663 /// A constant in a type as a substitution for const generics (like `Foo<{ 2 + 2 }>`) or as an array
664 /// length (like `[u8; 2 + 2]`). These constants are body owner and are a variant of `DefWithBodyId`. These
665 /// are not called `AnonymousConstId` to prevent confusion with [`ConstBlockId`].
666 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
667 pub struct InTypeConstId(salsa::InternId);
668 impl_intern!(InTypeConstId, InTypeConstLoc, intern_in_type_const, lookup_intern_in_type_const);
669
670 #[derive(Debug, Hash, Eq, Clone)]
671 pub struct InTypeConstLoc {
672 pub id: AstId<ast::ConstArg>,
673 /// The thing this const arg appears in
674 pub owner: TypeOwnerId,
675 pub thing: Box<dyn OpaqueInternableThing>,
676 }
677
678 impl PartialEq for InTypeConstLoc {
eq(&self, other: &Self) -> bool679 fn eq(&self, other: &Self) -> bool {
680 self.id == other.id && self.owner == other.owner && &*self.thing == &*other.thing
681 }
682 }
683
684 impl InTypeConstId {
source(&self, db: &dyn db::DefDatabase) -> ast::ConstArg685 pub fn source(&self, db: &dyn db::DefDatabase) -> ast::ConstArg {
686 let src = self.lookup(db).id;
687 let file_id = src.file_id;
688 let root = &db.parse_or_expand(file_id);
689 db.ast_id_map(file_id).get(src.value).to_node(root)
690 }
691 }
692
693 /// A constant, which might appears as a const item, an annonymous const block in expressions
694 /// or patterns, or as a constant in types with const generics.
695 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
696 pub enum GeneralConstId {
697 ConstId(ConstId),
698 ConstBlockId(ConstBlockId),
699 InTypeConstId(InTypeConstId),
700 }
701
702 impl_from!(ConstId, ConstBlockId, InTypeConstId for GeneralConstId);
703
704 impl GeneralConstId {
generic_def(self, db: &dyn db::DefDatabase) -> Option<GenericDefId>705 pub fn generic_def(self, db: &dyn db::DefDatabase) -> Option<GenericDefId> {
706 match self {
707 GeneralConstId::ConstId(it) => Some(it.into()),
708 GeneralConstId::ConstBlockId(it) => it.lookup(db).parent.as_generic_def_id(),
709 GeneralConstId::InTypeConstId(it) => it.lookup(db).owner.as_generic_def_id(),
710 }
711 }
712
name(self, db: &dyn db::DefDatabase) -> String713 pub fn name(self, db: &dyn db::DefDatabase) -> String {
714 match self {
715 GeneralConstId::ConstId(const_id) => db
716 .const_data(const_id)
717 .name
718 .as_ref()
719 .and_then(|x| x.as_str())
720 .unwrap_or("_")
721 .to_owned(),
722 GeneralConstId::ConstBlockId(id) => format!("{{anonymous const {id:?}}}"),
723 GeneralConstId::InTypeConstId(id) => format!("{{in type const {id:?}}}"),
724 }
725 }
726 }
727
728 /// The defs which have a body.
729 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
730 pub enum DefWithBodyId {
731 FunctionId(FunctionId),
732 StaticId(StaticId),
733 ConstId(ConstId),
734 InTypeConstId(InTypeConstId),
735 VariantId(EnumVariantId),
736 }
737
738 impl_from!(FunctionId, ConstId, StaticId, InTypeConstId for DefWithBodyId);
739
740 impl From<EnumVariantId> for DefWithBodyId {
from(id: EnumVariantId) -> Self741 fn from(id: EnumVariantId) -> Self {
742 DefWithBodyId::VariantId(id)
743 }
744 }
745
746 impl DefWithBodyId {
as_generic_def_id(self) -> Option<GenericDefId>747 pub fn as_generic_def_id(self) -> Option<GenericDefId> {
748 match self {
749 DefWithBodyId::FunctionId(f) => Some(f.into()),
750 DefWithBodyId::StaticId(_) => None,
751 DefWithBodyId::ConstId(c) => Some(c.into()),
752 DefWithBodyId::VariantId(c) => Some(c.into()),
753 // FIXME: stable rust doesn't allow generics in constants, but we should
754 // use `TypeOwnerId::as_generic_def_id` when it does.
755 DefWithBodyId::InTypeConstId(_) => None,
756 }
757 }
758 }
759
760 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
761 pub enum AssocItemId {
762 FunctionId(FunctionId),
763 ConstId(ConstId),
764 TypeAliasId(TypeAliasId),
765 }
766 // FIXME: not every function, ... is actually an assoc item. maybe we should make
767 // sure that you can only turn actual assoc items into AssocItemIds. This would
768 // require not implementing From, and instead having some checked way of
769 // casting them, and somehow making the constructors private, which would be annoying.
770 impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId);
771
772 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
773 pub enum GenericDefId {
774 FunctionId(FunctionId),
775 AdtId(AdtId),
776 TraitId(TraitId),
777 TraitAliasId(TraitAliasId),
778 TypeAliasId(TypeAliasId),
779 ImplId(ImplId),
780 // enum variants cannot have generics themselves, but their parent enums
781 // can, and this makes some code easier to write
782 EnumVariantId(EnumVariantId),
783 // consts can have type parameters from their parents (i.e. associated consts of traits)
784 ConstId(ConstId),
785 }
786 impl_from!(
787 FunctionId,
788 AdtId(StructId, EnumId, UnionId),
789 TraitId,
790 TraitAliasId,
791 TypeAliasId,
792 ImplId,
793 EnumVariantId,
794 ConstId
795 for GenericDefId
796 );
797
798 impl From<AssocItemId> for GenericDefId {
from(item: AssocItemId) -> Self799 fn from(item: AssocItemId) -> Self {
800 match item {
801 AssocItemId::FunctionId(f) => f.into(),
802 AssocItemId::ConstId(c) => c.into(),
803 AssocItemId::TypeAliasId(t) => t.into(),
804 }
805 }
806 }
807
808 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
809 pub enum AttrDefId {
810 ModuleId(ModuleId),
811 FieldId(FieldId),
812 AdtId(AdtId),
813 FunctionId(FunctionId),
814 EnumVariantId(EnumVariantId),
815 StaticId(StaticId),
816 ConstId(ConstId),
817 TraitId(TraitId),
818 TraitAliasId(TraitAliasId),
819 TypeAliasId(TypeAliasId),
820 MacroId(MacroId),
821 ImplId(ImplId),
822 GenericParamId(GenericParamId),
823 ExternBlockId(ExternBlockId),
824 }
825
826 impl_from!(
827 ModuleId,
828 FieldId,
829 AdtId(StructId, EnumId, UnionId),
830 EnumVariantId,
831 StaticId,
832 ConstId,
833 FunctionId,
834 TraitId,
835 TypeAliasId,
836 MacroId(Macro2Id, MacroRulesId, ProcMacroId),
837 ImplId,
838 GenericParamId
839 for AttrDefId
840 );
841
842 impl From<ItemContainerId> for AttrDefId {
from(acid: ItemContainerId) -> Self843 fn from(acid: ItemContainerId) -> Self {
844 match acid {
845 ItemContainerId::ModuleId(mid) => AttrDefId::ModuleId(mid),
846 ItemContainerId::ImplId(iid) => AttrDefId::ImplId(iid),
847 ItemContainerId::TraitId(tid) => AttrDefId::TraitId(tid),
848 ItemContainerId::ExternBlockId(id) => AttrDefId::ExternBlockId(id),
849 }
850 }
851 }
852
853 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
854 pub enum VariantId {
855 EnumVariantId(EnumVariantId),
856 StructId(StructId),
857 UnionId(UnionId),
858 }
859 impl_from!(EnumVariantId, StructId, UnionId for VariantId);
860
861 impl VariantId {
variant_data(self, db: &dyn db::DefDatabase) -> Arc<VariantData>862 pub fn variant_data(self, db: &dyn db::DefDatabase) -> Arc<VariantData> {
863 match self {
864 VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
865 VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
866 VariantId::EnumVariantId(it) => {
867 db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
868 }
869 }
870 }
871
file_id(self, db: &dyn db::DefDatabase) -> HirFileId872 pub fn file_id(self, db: &dyn db::DefDatabase) -> HirFileId {
873 match self {
874 VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(),
875 VariantId::StructId(it) => it.lookup(db).id.file_id(),
876 VariantId::UnionId(it) => it.lookup(db).id.file_id(),
877 }
878 }
879
adt_id(self) -> AdtId880 pub fn adt_id(self) -> AdtId {
881 match self {
882 VariantId::EnumVariantId(it) => it.parent.into(),
883 VariantId::StructId(it) => it.into(),
884 VariantId::UnionId(it) => it.into(),
885 }
886 }
887 }
888
889 trait Intern {
890 type ID;
intern(self, db: &dyn db::DefDatabase) -> Self::ID891 fn intern(self, db: &dyn db::DefDatabase) -> Self::ID;
892 }
893
894 pub trait Lookup {
895 type Data;
lookup(&self, db: &dyn db::DefDatabase) -> Self::Data896 fn lookup(&self, db: &dyn db::DefDatabase) -> Self::Data;
897 }
898
899 pub trait HasModule {
module(&self, db: &dyn db::DefDatabase) -> ModuleId900 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId;
901 }
902
903 impl HasModule for ItemContainerId {
module(&self, db: &dyn db::DefDatabase) -> ModuleId904 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
905 match *self {
906 ItemContainerId::ModuleId(it) => it,
907 ItemContainerId::ImplId(it) => it.lookup(db).container,
908 ItemContainerId::TraitId(it) => it.lookup(db).container,
909 ItemContainerId::ExternBlockId(it) => it.lookup(db).container,
910 }
911 }
912 }
913
914 impl<N: ItemTreeNode> HasModule for AssocItemLoc<N> {
module(&self, db: &dyn db::DefDatabase) -> ModuleId915 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
916 self.container.module(db)
917 }
918 }
919
920 impl HasModule for AdtId {
module(&self, db: &dyn db::DefDatabase) -> ModuleId921 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
922 match self {
923 AdtId::StructId(it) => it.lookup(db).container,
924 AdtId::UnionId(it) => it.lookup(db).container,
925 AdtId::EnumId(it) => it.lookup(db).container,
926 }
927 }
928 }
929
930 impl HasModule for VariantId {
module(&self, db: &dyn db::DefDatabase) -> ModuleId931 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
932 match self {
933 VariantId::EnumVariantId(it) => it.parent.lookup(db).container,
934 VariantId::StructId(it) => it.lookup(db).container,
935 VariantId::UnionId(it) => it.lookup(db).container,
936 }
937 }
938 }
939
940 impl HasModule for MacroId {
module(&self, db: &dyn db::DefDatabase) -> ModuleId941 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
942 match self {
943 MacroId::MacroRulesId(it) => it.lookup(db).container,
944 MacroId::Macro2Id(it) => it.lookup(db).container,
945 MacroId::ProcMacroId(it) => it.lookup(db).container.into(),
946 }
947 }
948 }
949
950 impl HasModule for TypeOwnerId {
module(&self, db: &dyn db::DefDatabase) -> ModuleId951 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
952 match self {
953 TypeOwnerId::FunctionId(x) => x.lookup(db).module(db),
954 TypeOwnerId::StaticId(x) => x.lookup(db).module(db),
955 TypeOwnerId::ConstId(x) => x.lookup(db).module(db),
956 TypeOwnerId::InTypeConstId(x) => x.lookup(db).owner.module(db),
957 TypeOwnerId::AdtId(x) => x.module(db),
958 TypeOwnerId::TraitId(x) => x.lookup(db).container,
959 TypeOwnerId::TraitAliasId(x) => x.lookup(db).container,
960 TypeOwnerId::TypeAliasId(x) => x.lookup(db).module(db),
961 TypeOwnerId::ImplId(x) => x.lookup(db).container,
962 TypeOwnerId::EnumVariantId(x) => x.parent.lookup(db).container,
963 TypeOwnerId::ModuleId(x) => *x,
964 }
965 }
966 }
967
968 impl HasModule for DefWithBodyId {
module(&self, db: &dyn db::DefDatabase) -> ModuleId969 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
970 match self {
971 DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
972 DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
973 DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
974 DefWithBodyId::VariantId(it) => it.parent.lookup(db).container,
975 DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db),
976 }
977 }
978 }
979
980 impl HasModule for GenericDefId {
module(&self, db: &dyn db::DefDatabase) -> ModuleId981 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
982 match self {
983 GenericDefId::FunctionId(it) => it.lookup(db).module(db),
984 GenericDefId::AdtId(it) => it.module(db),
985 GenericDefId::TraitId(it) => it.lookup(db).container,
986 GenericDefId::TraitAliasId(it) => it.lookup(db).container,
987 GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
988 GenericDefId::ImplId(it) => it.lookup(db).container,
989 GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container,
990 GenericDefId::ConstId(it) => it.lookup(db).module(db),
991 }
992 }
993 }
994
995 impl HasModule for TypeAliasId {
module(&self, db: &dyn db::DefDatabase) -> ModuleId996 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
997 self.lookup(db).module(db)
998 }
999 }
1000
1001 impl HasModule for TraitId {
module(&self, db: &dyn db::DefDatabase) -> ModuleId1002 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
1003 self.lookup(db).container
1004 }
1005 }
1006
1007 impl ModuleDefId {
1008 /// Returns the module containing `self` (or `self`, if `self` is itself a module).
1009 ///
1010 /// Returns `None` if `self` refers to a primitive type.
module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId>1011 pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
1012 Some(match self {
1013 ModuleDefId::ModuleId(id) => *id,
1014 ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
1015 ModuleDefId::AdtId(id) => id.module(db),
1016 ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container,
1017 ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
1018 ModuleDefId::StaticId(id) => id.lookup(db).module(db),
1019 ModuleDefId::TraitId(id) => id.lookup(db).container,
1020 ModuleDefId::TraitAliasId(id) => id.lookup(db).container,
1021 ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db),
1022 ModuleDefId::MacroId(id) => id.module(db),
1023 ModuleDefId::BuiltinType(_) => return None,
1024 })
1025 }
1026 }
1027
1028 impl AttrDefId {
krate(&self, db: &dyn db::DefDatabase) -> CrateId1029 pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId {
1030 match self {
1031 AttrDefId::ModuleId(it) => it.krate,
1032 AttrDefId::FieldId(it) => it.parent.module(db).krate,
1033 AttrDefId::AdtId(it) => it.module(db).krate,
1034 AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
1035 AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.krate,
1036 AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
1037 AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
1038 AttrDefId::TraitId(it) => it.lookup(db).container.krate,
1039 AttrDefId::TraitAliasId(it) => it.lookup(db).container.krate,
1040 AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate,
1041 AttrDefId::ImplId(it) => it.lookup(db).container.krate,
1042 AttrDefId::ExternBlockId(it) => it.lookup(db).container.krate,
1043 AttrDefId::GenericParamId(it) => {
1044 match it {
1045 GenericParamId::TypeParamId(it) => it.parent(),
1046 GenericParamId::ConstParamId(it) => it.parent(),
1047 GenericParamId::LifetimeParamId(it) => it.parent,
1048 }
1049 .module(db)
1050 .krate
1051 }
1052 AttrDefId::MacroId(it) => it.module(db).krate,
1053 }
1054 }
1055 }
1056
1057 /// A helper trait for converting to MacroCallId
1058 pub trait AsMacroCall {
as_call_id( &self, db: &dyn ExpandDatabase, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, ) -> Option<MacroCallId>1059 fn as_call_id(
1060 &self,
1061 db: &dyn ExpandDatabase,
1062 krate: CrateId,
1063 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
1064 ) -> Option<MacroCallId> {
1065 self.as_call_id_with_errors(db, krate, resolver).ok()?.value
1066 }
1067
as_call_id_with_errors( &self, db: &dyn ExpandDatabase, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>1068 fn as_call_id_with_errors(
1069 &self,
1070 db: &dyn ExpandDatabase,
1071 krate: CrateId,
1072 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
1073 ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>;
1074 }
1075
1076 impl AsMacroCall for InFile<&ast::MacroCall> {
as_call_id_with_errors( &self, db: &dyn ExpandDatabase, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>1077 fn as_call_id_with_errors(
1078 &self,
1079 db: &dyn ExpandDatabase,
1080 krate: CrateId,
1081 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
1082 ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
1083 let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
1084 let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
1085 let h = Hygiene::new(db, self.file_id);
1086 let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h));
1087
1088 let Some(path) = path else {
1089 return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation")));
1090 };
1091
1092 macro_call_as_call_id_(
1093 db,
1094 &AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
1095 expands_to,
1096 krate,
1097 resolver,
1098 )
1099 }
1100 }
1101
1102 /// Helper wrapper for `AstId` with `ModPath`
1103 #[derive(Clone, Debug, Eq, PartialEq)]
1104 struct AstIdWithPath<T: ast::AstNode> {
1105 ast_id: AstId<T>,
1106 path: path::ModPath,
1107 }
1108
1109 impl<T: ast::AstNode> AstIdWithPath<T> {
new(file_id: HirFileId, ast_id: FileAstId<T>, path: path::ModPath) -> AstIdWithPath<T>1110 fn new(file_id: HirFileId, ast_id: FileAstId<T>, path: path::ModPath) -> AstIdWithPath<T> {
1111 AstIdWithPath { ast_id: AstId::new(file_id, ast_id), path }
1112 }
1113 }
1114
macro_call_as_call_id( db: &dyn ExpandDatabase, call: &AstIdWithPath<ast::MacroCall>, expand_to: ExpandTo, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, ) -> Result<Option<MacroCallId>, UnresolvedMacro>1115 fn macro_call_as_call_id(
1116 db: &dyn ExpandDatabase,
1117 call: &AstIdWithPath<ast::MacroCall>,
1118 expand_to: ExpandTo,
1119 krate: CrateId,
1120 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
1121 ) -> Result<Option<MacroCallId>, UnresolvedMacro> {
1122 macro_call_as_call_id_(db, call, expand_to, krate, resolver).map(|res| res.value)
1123 }
1124
macro_call_as_call_id_( db: &dyn ExpandDatabase, call: &AstIdWithPath<ast::MacroCall>, expand_to: ExpandTo, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>1125 fn macro_call_as_call_id_(
1126 db: &dyn ExpandDatabase,
1127 call: &AstIdWithPath<ast::MacroCall>,
1128 expand_to: ExpandTo,
1129 krate: CrateId,
1130 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
1131 ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
1132 let def =
1133 resolver(call.path.clone()).ok_or_else(|| UnresolvedMacro { path: call.path.clone() })?;
1134
1135 let res = if let MacroDefKind::BuiltInEager(..) = def.kind {
1136 let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db));
1137 expand_eager_macro_input(db, krate, macro_call, def, &resolver)?
1138 } else {
1139 ExpandResult {
1140 value: Some(def.as_lazy_macro(
1141 db,
1142 krate,
1143 MacroCallKind::FnLike { ast_id: call.ast_id, expand_to },
1144 )),
1145 err: None,
1146 }
1147 };
1148 Ok(res)
1149 }
1150
macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId1151 pub fn macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId {
1152 match id {
1153 MacroId::Macro2Id(it) => {
1154 let loc = it.lookup(db);
1155
1156 let item_tree = loc.id.item_tree(db);
1157 let makro = &item_tree[loc.id.value];
1158 let in_file = |m: FileAstId<ast::MacroDef>| InFile::new(loc.id.file_id(), m.upcast());
1159 MacroDefId {
1160 krate: loc.container.krate,
1161 kind: match loc.expander {
1162 MacroExpander::Declarative => MacroDefKind::Declarative(in_file(makro.ast_id)),
1163 MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(it, in_file(makro.ast_id)),
1164 MacroExpander::BuiltInAttr(it) => {
1165 MacroDefKind::BuiltInAttr(it, in_file(makro.ast_id))
1166 }
1167 MacroExpander::BuiltInDerive(it) => {
1168 MacroDefKind::BuiltInDerive(it, in_file(makro.ast_id))
1169 }
1170 MacroExpander::BuiltInEager(it) => {
1171 MacroDefKind::BuiltInEager(it, in_file(makro.ast_id))
1172 }
1173 },
1174 local_inner: false,
1175 allow_internal_unsafe: loc.allow_internal_unsafe,
1176 }
1177 }
1178 MacroId::MacroRulesId(it) => {
1179 let loc = it.lookup(db);
1180
1181 let item_tree = loc.id.item_tree(db);
1182 let makro = &item_tree[loc.id.value];
1183 let in_file = |m: FileAstId<ast::MacroRules>| InFile::new(loc.id.file_id(), m.upcast());
1184 MacroDefId {
1185 krate: loc.container.krate,
1186 kind: match loc.expander {
1187 MacroExpander::Declarative => MacroDefKind::Declarative(in_file(makro.ast_id)),
1188 MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(it, in_file(makro.ast_id)),
1189 MacroExpander::BuiltInAttr(it) => {
1190 MacroDefKind::BuiltInAttr(it, in_file(makro.ast_id))
1191 }
1192 MacroExpander::BuiltInDerive(it) => {
1193 MacroDefKind::BuiltInDerive(it, in_file(makro.ast_id))
1194 }
1195 MacroExpander::BuiltInEager(it) => {
1196 MacroDefKind::BuiltInEager(it, in_file(makro.ast_id))
1197 }
1198 },
1199 local_inner: loc.local_inner,
1200 allow_internal_unsafe: loc.allow_internal_unsafe,
1201 }
1202 }
1203 MacroId::ProcMacroId(it) => {
1204 let loc = it.lookup(db);
1205
1206 let item_tree = loc.id.item_tree(db);
1207 let makro = &item_tree[loc.id.value];
1208 MacroDefId {
1209 krate: loc.container.krate,
1210 kind: MacroDefKind::ProcMacro(
1211 loc.expander,
1212 loc.kind,
1213 InFile::new(loc.id.file_id(), makro.ast_id),
1214 ),
1215 local_inner: false,
1216 allow_internal_unsafe: false,
1217 }
1218 }
1219 }
1220 }
1221
derive_macro_as_call_id( db: &dyn db::DefDatabase, item_attr: &AstIdWithPath<ast::Adt>, derive_attr_index: AttrId, derive_pos: u32, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>, ) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro>1222 fn derive_macro_as_call_id(
1223 db: &dyn db::DefDatabase,
1224 item_attr: &AstIdWithPath<ast::Adt>,
1225 derive_attr_index: AttrId,
1226 derive_pos: u32,
1227 krate: CrateId,
1228 resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>,
1229 ) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> {
1230 let (macro_id, def_id) = resolver(item_attr.path.clone())
1231 .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
1232 let call_id = def_id.as_lazy_macro(
1233 db.upcast(),
1234 krate,
1235 MacroCallKind::Derive {
1236 ast_id: item_attr.ast_id,
1237 derive_index: derive_pos,
1238 derive_attr_index,
1239 },
1240 );
1241 Ok((macro_id, def_id, call_id))
1242 }
1243
attr_macro_as_call_id( db: &dyn db::DefDatabase, item_attr: &AstIdWithPath<ast::Item>, macro_attr: &Attr, krate: CrateId, def: MacroDefId, ) -> MacroCallId1244 fn attr_macro_as_call_id(
1245 db: &dyn db::DefDatabase,
1246 item_attr: &AstIdWithPath<ast::Item>,
1247 macro_attr: &Attr,
1248 krate: CrateId,
1249 def: MacroDefId,
1250 ) -> MacroCallId {
1251 let arg = match macro_attr.input.as_deref() {
1252 Some(AttrInput::TokenTree(tt)) => (
1253 {
1254 let mut tt = tt.0.clone();
1255 tt.delimiter = tt::Delimiter::UNSPECIFIED;
1256 tt
1257 },
1258 tt.1.clone(),
1259 ),
1260 _ => (tt::Subtree::empty(), Default::default()),
1261 };
1262
1263 def.as_lazy_macro(
1264 db.upcast(),
1265 krate,
1266 MacroCallKind::Attr {
1267 ast_id: item_attr.ast_id,
1268 attr_args: Arc::new(arg),
1269 invoc_attr_index: macro_attr.id,
1270 },
1271 )
1272 }
1273 intern::impl_internable!(
1274 crate::type_ref::TypeRef,
1275 crate::type_ref::TraitRef,
1276 crate::type_ref::TypeBound,
1277 crate::path::GenericArgs,
1278 generics::GenericParams,
1279 );
1280