1use std::hash::{Hash, Hasher};
25use std::sync::Arc;
26
27use cairo_lang_debug::debug::DebugWithDb;
28use cairo_lang_diagnostics::Maybe;
29pub use cairo_lang_filesystem::ids::UnstableSalsaId;
30use cairo_lang_filesystem::ids::{CrateId, FileId};
31use cairo_lang_syntax::node::ast::TerminalIdentifierGreen;
32use cairo_lang_syntax::node::db::SyntaxGroup;
33use cairo_lang_syntax::node::helpers::{GetIdentifier, HasName, NameGreen};
34use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
35use cairo_lang_syntax::node::kind::SyntaxKind;
36use cairo_lang_syntax::node::stable_ptr::SyntaxStablePtr;
37use cairo_lang_syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode, ast};
38use cairo_lang_utils::{Intern, LookupIntern, OptionFrom, define_short_id, require};
39use smol_str::SmolStr;
40
41use crate::db::DefsGroup;
42use crate::diagnostic_utils::StableLocation;
43use crate::plugin::{InlineMacroExprPlugin, MacroPlugin};
44
45pub trait LanguageElementId {
47 fn module_file_id(&self, db: &dyn DefsGroup) -> ModuleFileId;
48 fn untyped_stable_ptr(&self, db: &dyn DefsGroup) -> SyntaxStablePtrId;
49
50 fn parent_module(&self, db: &dyn DefsGroup) -> ModuleId {
51 self.module_file_id(db).0
52 }
53 fn file_index(&self, db: &dyn DefsGroup) -> FileIndex {
54 self.module_file_id(db).1
55 }
56
57 fn stable_location(&self, db: &dyn DefsGroup) -> StableLocation;
58}
59
60pub trait NamedLanguageElementLongId {
61 fn name(&self, db: &dyn DefsGroup) -> SmolStr;
62 fn name_identifier(&self, db: &dyn DefsGroup) -> ast::TerminalIdentifier;
63}
64pub trait NamedLanguageElementId: LanguageElementId {
65 fn name(&self, db: &dyn DefsGroup) -> SmolStr;
66 fn name_identifier(&self, db: &dyn DefsGroup) -> ast::TerminalIdentifier;
67}
68pub trait TopLevelLanguageElementId: NamedLanguageElementId {
69 fn full_path(&self, db: &dyn DefsGroup) -> String {
70 format!("{}::{}", self.parent_module(db).full_path(db), self.name(db))
71 }
72}
73
74macro_rules! define_top_level_language_element_id {
82 ($short_id:ident, $long_id:ident, $ast_ty:ty, $lookup:ident, $intern:ident) => {
83 define_named_language_element_id!($short_id, $long_id, $ast_ty, $lookup, $intern);
84 impl TopLevelLanguageElementId for $short_id {}
85 };
86}
87
88macro_rules! define_named_language_element_id {
95 ($short_id:ident, $long_id:ident, $ast_ty:ty, $lookup:ident, $intern:ident) => {
96 define_language_element_id_basic!($short_id, $long_id, $ast_ty, $lookup, $intern);
97 impl<'a, T: ?Sized + cairo_lang_utils::Upcast<dyn DefsGroup + 'a>>
98 cairo_lang_debug::DebugWithDb<T> for $long_id
99 {
100 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &T) -> std::fmt::Result {
101 let db: &(dyn DefsGroup + 'a) = db.upcast();
102 let $long_id(module_file_id, _stable_ptr) = self;
103 write!(
104 f,
105 "{}({}::{})",
106 stringify!($short_id),
107 module_file_id.0.full_path(db),
108 self.name(db)
109 )
110 }
111 }
112 impl NamedLanguageElementLongId for $long_id {
113 fn name(&self, db: &dyn DefsGroup) -> SmolStr {
114 let terminal_green = self.1.name_green(db);
115 terminal_green.identifier(db)
116 }
117 fn name_identifier(&self, db: &dyn DefsGroup) -> ast::TerminalIdentifier {
118 self.1.lookup(db).name(db)
119 }
120 }
121 impl NamedLanguageElementId for $short_id {
122 fn name(&self, db: &dyn DefsGroup) -> SmolStr {
123 db.$lookup(*self).name(db)
124 }
125 fn name_identifier(&self, db: &dyn DefsGroup) -> ast::TerminalIdentifier {
126 db.$lookup(*self).name_identifier(db)
127 }
128 }
129 };
130}
131
132macro_rules! define_language_element_id_basic {
138 ($short_id:ident, $long_id:ident, $ast_ty:ty, $lookup:ident, $intern:ident) => {
139 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
140 pub struct $long_id(pub ModuleFileId, pub <$ast_ty as TypedSyntaxNode>::StablePtr);
141 define_short_id!($short_id, $long_id, DefsGroup, $lookup, $intern);
142 impl $short_id {
143 pub fn stable_ptr(
144 &self,
145 db: &dyn DefsGroup,
146 ) -> <$ast_ty as TypedSyntaxNode>::StablePtr {
147 db.$lookup(*self).1
148 }
149 }
150 impl LanguageElementId for $short_id {
151 fn module_file_id(&self, db: &dyn DefsGroup) -> ModuleFileId {
152 db.$lookup(*self).0
153 }
154 fn untyped_stable_ptr(&self, db: &dyn DefsGroup) -> SyntaxStablePtrId {
155 self.stable_ptr(db).untyped()
156 }
157 fn stable_location(&self, db: &dyn DefsGroup) -> StableLocation {
158 let $long_id(_module_file_id, stable_ptr) = db.$lookup(*self);
159 StableLocation::new(stable_ptr.untyped())
160 }
161 }
162 };
163}
164
165macro_rules! define_language_element_id_as_enum {
167 (
168 #[toplevel]
169 $(#[doc = $doc:expr])*
170 pub enum $enum_name:ident {
171 $($variant:ident ($variant_ty:ty),)*
172 }
173 ) => {
174 toplevel_enum! {
175 pub enum $enum_name {
176 $($variant($variant_ty),)*
177 }
178 }
179 define_language_element_id_as_enum! {
180 $(#[doc = $doc])*
181 pub enum $enum_name {
182 $($variant($variant_ty),)*
183 }
184 }
185 };
186 (
187 $(#[doc = $doc:expr])*
188 pub enum $enum_name:ident {
189 $($variant:ident ($variant_ty:ty),)*
190 }
191 ) => {
192 $(#[doc = $doc])*
193 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
194 pub enum $enum_name {
195 $($variant($variant_ty),)*
196 }
197 impl<T: ?Sized + cairo_lang_utils::Upcast<dyn DefsGroup + 'static>> cairo_lang_debug::DebugWithDb<T>
198 for $enum_name
199 {
200 fn fmt(
201 &self,
202 f: &mut std::fmt::Formatter<'_>,
203 db: &T,
204 ) -> std::fmt::Result {
205 let db : &(dyn DefsGroup + 'static) = db.upcast();
206 match self {
207 $(
208 $enum_name::$variant(id) => id.fmt(f, db),
209 )*
210 }
211 }
212 }
213 impl LanguageElementId for $enum_name {
214 fn module_file_id(&self, db: &dyn DefsGroup) -> ModuleFileId {
215 match self {
216 $(
217 $enum_name::$variant(id) => id.module_file_id(db),
218 )*
219 }
220 }
221 fn untyped_stable_ptr(&self, db: &dyn DefsGroup) -> SyntaxStablePtrId {
222 match self {
223 $(
224 $enum_name::$variant(id) => id.untyped_stable_ptr(db),
225 )*
226 }
227 }
228 fn stable_location(&self, db: &dyn DefsGroup) -> StableLocation {
229 match self {
230 $(
231 $enum_name::$variant(id) => id.stable_location(db),
232 )*
233 }
234 }
235
236 }
237
238 $(
240 impl OptionFrom<$enum_name> for $variant_ty {
241 fn option_from(other: $enum_name) -> Option<Self> {
242 #[allow(irrefutable_let_patterns)]
243 if let $enum_name::$variant(id) = other {
244 Some(id)
245 } else {
246 None
247 }
248 }
249 }
250 )*
251 }
252}
253
254macro_rules! toplevel_enum {
255 (
256 pub enum $enum_name:ident {
257 $($variant:ident ($variant_ty:ty),)*
258 }
259 ) => {
260 impl NamedLanguageElementId for $enum_name {
261 fn name(&self, db: &dyn DefsGroup) -> SmolStr {
262 match self {
263 $(
264 $enum_name::$variant(id) => id.name(db),
265 )*
266 }
267 }
268 fn name_identifier(&self, db: &dyn DefsGroup) -> ast::TerminalIdentifier {
269 match self {
270 $(
271 $enum_name::$variant(id) => id.name_identifier(db),
272 )*
273 }
274 }
275 }
276 impl TopLevelLanguageElementId for $enum_name {}
277 }
278}
279
280#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
282pub enum ModuleId {
283 CrateRoot(CrateId),
284 Submodule(SubmoduleId),
285}
286impl ModuleId {
287 pub fn full_path(&self, db: &dyn DefsGroup) -> String {
288 match self {
289 ModuleId::CrateRoot(id) => id.lookup_intern(db).name().into(),
290 ModuleId::Submodule(id) => {
291 format!("{}::{}", id.parent_module(db).full_path(db), id.name(db))
292 }
293 }
294 }
295 pub fn name(&self, db: &dyn DefsGroup) -> SmolStr {
296 match self {
297 ModuleId::CrateRoot(id) => id.lookup_intern(db).name(),
298 ModuleId::Submodule(id) => id.name(db),
299 }
300 }
301 pub fn owning_crate(&self, db: &dyn DefsGroup) -> CrateId {
302 match self {
303 ModuleId::CrateRoot(crate_id) => *crate_id,
304 ModuleId::Submodule(submodule) => submodule.parent_module(db).owning_crate(db),
305 }
306 }
307}
308impl DebugWithDb<dyn DefsGroup> for ModuleId {
309 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &dyn DefsGroup) -> std::fmt::Result {
310 write!(f, "ModuleId({})", self.full_path(db))
311 }
312}
313#[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq)]
315pub struct FileIndex(pub usize);
316#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
317pub struct ModuleFileId(pub ModuleId, pub FileIndex);
318impl ModuleFileId {
319 pub fn file_id(&self, db: &dyn DefsGroup) -> Maybe<FileId> {
320 Ok(db.module_files(self.0)?[self.1.0])
321 }
322}
323
324#[derive(Clone, Debug, Hash, PartialEq, Eq)]
326pub struct PluginGeneratedFileLongId {
327 pub module_id: ModuleId,
329 pub stable_ptr: SyntaxStablePtrId,
331 pub name: SmolStr,
333}
334define_short_id!(
335 PluginGeneratedFileId,
336 PluginGeneratedFileLongId,
337 DefsGroup,
338 lookup_intern_plugin_generated_file,
339 intern_plugin_generated_file
340);
341
342#[derive(Clone, Debug)]
344pub struct MacroPluginLongId(pub Arc<dyn MacroPlugin>);
345
346impl MacroPlugin for MacroPluginLongId {
347 fn generate_code(
348 &self,
349 db: &dyn SyntaxGroup,
350 item_ast: ast::ModuleItem,
351 metadata: &crate::plugin::MacroPluginMetadata<'_>,
352 ) -> crate::plugin::PluginResult {
353 self.0.generate_code(db, item_ast, metadata)
354 }
355
356 fn declared_attributes(&self) -> Vec<String> {
357 self.0.declared_attributes()
358 }
359
360 fn declared_derives(&self) -> Vec<String> {
361 self.0.declared_derives()
362 }
363
364 fn executable_attributes(&self) -> Vec<String> {
365 self.0.executable_attributes()
366 }
367
368 fn phantom_type_attributes(&self) -> Vec<String> {
369 self.0.phantom_type_attributes()
370 }
371
372 fn plugin_type_id(&self) -> std::any::TypeId {
373 self.0.plugin_type_id()
376 }
377}
378
379impl PartialEq for MacroPluginLongId {
382 fn eq(&self, other: &Self) -> bool {
383 Arc::ptr_eq(&self.0, &other.0)
384 }
385}
386
387impl Eq for MacroPluginLongId {}
388
389impl Hash for MacroPluginLongId {
390 fn hash<H: Hasher>(&self, state: &mut H) {
391 Arc::as_ptr(&self.0).hash(state)
392 }
393}
394
395define_short_id!(
396 MacroPluginId,
397 MacroPluginLongId,
398 DefsGroup,
399 lookup_intern_macro_plugin,
400 intern_macro_plugin
401);
402
403#[derive(Clone, Debug)]
405pub struct InlineMacroExprPluginLongId(pub Arc<dyn InlineMacroExprPlugin>);
406
407impl InlineMacroExprPlugin for InlineMacroExprPluginLongId {
408 fn generate_code(
409 &self,
410 db: &dyn SyntaxGroup,
411 item_ast: &ast::ExprInlineMacro,
412 metadata: &crate::plugin::MacroPluginMetadata<'_>,
413 ) -> crate::plugin::InlinePluginResult {
414 self.0.generate_code(db, item_ast, metadata)
415 }
416
417 fn documentation(&self) -> Option<String> {
418 self.0.documentation()
419 }
420
421 fn plugin_type_id(&self) -> std::any::TypeId {
422 self.0.plugin_type_id()
425 }
426}
427
428impl PartialEq for InlineMacroExprPluginLongId {
431 fn eq(&self, other: &Self) -> bool {
432 Arc::ptr_eq(&self.0, &other.0)
433 }
434}
435
436impl Eq for InlineMacroExprPluginLongId {}
437
438impl Hash for InlineMacroExprPluginLongId {
439 fn hash<H: Hasher>(&self, state: &mut H) {
440 Arc::as_ptr(&self.0).hash(state)
441 }
442}
443
444define_short_id!(
445 InlineMacroExprPluginId,
446 InlineMacroExprPluginLongId,
447 DefsGroup,
448 lookup_intern_inline_macro_plugin,
449 intern_inline_macro_plugin
450);
451
452define_language_element_id_as_enum! {
453 #[toplevel]
454 pub enum ModuleItemId {
456 Constant(ConstantId),
457 Submodule(SubmoduleId),
458 Use(UseId),
459 FreeFunction(FreeFunctionId),
460 Struct(StructId),
461 Enum(EnumId),
462 TypeAlias(ModuleTypeAliasId),
463 ImplAlias(ImplAliasId),
464 Trait(TraitId),
465 Impl(ImplDefId),
466 ExternType(ExternTypeId),
467 ExternFunction(ExternFunctionId),
468 MacroDeclaration(MacroDeclarationId),
469 }
470}
471
472#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
475pub enum ImportableId {
476 Constant(ConstantId),
477 Submodule(SubmoduleId),
478 Crate(CrateId),
479 FreeFunction(FreeFunctionId),
480 Struct(StructId),
481 Enum(EnumId),
482 Variant(VariantId),
483 TypeAlias(ModuleTypeAliasId),
484 ImplAlias(ImplAliasId),
485 Trait(TraitId),
486 Impl(ImplDefId),
487 ExternType(ExternTypeId),
488 ExternFunction(ExternFunctionId),
489 MacroDeclaration(MacroDeclarationId),
490}
491
492define_top_level_language_element_id!(
493 SubmoduleId,
494 SubmoduleLongId,
495 ast::ItemModule,
496 lookup_intern_submodule,
497 intern_submodule
498);
499impl UnstableSalsaId for SubmoduleId {
500 fn get_internal_id(&self) -> &salsa::InternId {
501 &self.0
502 }
503}
504
505define_top_level_language_element_id!(
506 ConstantId,
507 ConstantLongId,
508 ast::ItemConstant,
509 lookup_intern_constant,
510 intern_constant
511);
512define_language_element_id_basic!(
513 GlobalUseId,
514 GlobalUseLongId,
515 ast::UsePathStar,
516 lookup_intern_global_use,
517 intern_global_use
518);
519define_top_level_language_element_id!(
520 UseId,
521 UseLongId,
522 ast::UsePathLeaf,
523 lookup_intern_use,
524 intern_use
525);
526define_top_level_language_element_id!(
527 FreeFunctionId,
528 FreeFunctionLongId,
529 ast::FunctionWithBody,
530 lookup_intern_free_function,
531 intern_free_function
532);
533
534define_top_level_language_element_id!(
535 MacroDeclarationId,
536 MacroDeclarationLongId,
537 ast::ItemMacroDeclaration,
538 lookup_intern_macro_declaration,
539 intern_macro_declaration
540);
541
542impl UnstableSalsaId for FreeFunctionId {
543 fn get_internal_id(&self) -> &salsa::InternId {
544 &self.0
545 }
546}
547
548define_top_level_language_element_id!(
550 ImplDefId,
551 ImplDefLongId,
552 ast::ItemImpl,
553 lookup_intern_impl_def,
554 intern_impl_def
555);
556
557define_named_language_element_id!(
559 ImplTypeDefId,
560 ImplTypeDefLongId,
561 ast::ItemTypeAlias,
562 lookup_intern_impl_type_def,
563 intern_impl_type_def
564);
565impl ImplTypeDefId {
566 pub fn impl_def_id(&self, db: &dyn DefsGroup) -> ImplDefId {
567 let ImplTypeDefLongId(module_file_id, ptr) = self.lookup_intern(db);
568
569 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
571 ImplDefLongId(module_file_id, impl_ptr).intern(db)
572 }
573}
574impl TopLevelLanguageElementId for ImplTypeDefId {
575 fn full_path(&self, db: &dyn DefsGroup) -> String {
576 format!("{}::{}", self.impl_def_id(db).full_path(db), self.name(db))
577 }
578}
579
580define_named_language_element_id!(
582 ImplConstantDefId,
583 ImplConstantDefLongId,
584 ast::ItemConstant,
585 lookup_intern_impl_constant_def,
586 intern_impl_constant_def
587);
588impl ImplConstantDefId {
589 pub fn impl_def_id(&self, db: &dyn DefsGroup) -> ImplDefId {
590 let ImplConstantDefLongId(module_file_id, ptr) = self.lookup_intern(db);
591
592 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
594 ImplDefLongId(module_file_id, impl_ptr).intern(db)
595 }
596}
597impl TopLevelLanguageElementId for ImplConstantDefId {
598 fn full_path(&self, db: &dyn DefsGroup) -> String {
599 format!("{}::{}", self.impl_def_id(db).full_path(db), self.name(db))
600 }
601}
602
603define_named_language_element_id!(
605 ImplImplDefId,
606 ImplImplDefLongId,
607 ast::ItemImplAlias,
608 lookup_intern_impl_impl_def,
609 intern_impl_impl_def
610);
611impl ImplImplDefId {
612 pub fn impl_def_id(&self, db: &dyn DefsGroup) -> ImplDefId {
613 let ImplImplDefLongId(module_file_id, ptr) = self.lookup_intern(db);
614
615 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
617 ImplDefLongId(module_file_id, impl_ptr).intern(db)
618 }
619}
620impl TopLevelLanguageElementId for ImplImplDefId {
621 fn full_path(&self, db: &dyn DefsGroup) -> String {
622 format!("{}::{}", self.impl_def_id(db).full_path(db), self.name(db))
623 }
624}
625
626define_named_language_element_id!(
628 ImplFunctionId,
629 ImplFunctionLongId,
630 ast::FunctionWithBody,
631 lookup_intern_impl_function,
632 intern_impl_function
633);
634impl ImplFunctionId {
635 pub fn impl_def_id(&self, db: &dyn DefsGroup) -> ImplDefId {
636 let ImplFunctionLongId(module_file_id, ptr) = self.lookup_intern(db);
637
638 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
640 ImplDefLongId(module_file_id, impl_ptr).intern(db)
641 }
642}
643impl UnstableSalsaId for ImplFunctionId {
644 fn get_internal_id(&self) -> &salsa::InternId {
645 &self.0
646 }
647}
648impl TopLevelLanguageElementId for ImplFunctionId {
649 fn full_path(&self, db: &dyn DefsGroup) -> String {
650 format!("{}::{}", self.impl_def_id(db).full_path(db), self.name(db))
651 }
652}
653
654define_language_element_id_as_enum! {
655 #[toplevel]
656 pub enum FunctionWithBodyId {
658 Free(FreeFunctionId),
659 Impl(ImplFunctionId),
660 Trait(TraitFunctionId),
661 }
662}
663
664define_top_level_language_element_id!(
665 ExternFunctionId,
666 ExternFunctionLongId,
667 ast::ItemExternFunction,
668 lookup_intern_extern_function,
669 intern_extern_function
670);
671define_top_level_language_element_id!(
672 StructId,
673 StructLongId,
674 ast::ItemStruct,
675 lookup_intern_struct,
676 intern_struct
677);
678define_top_level_language_element_id!(
679 EnumId,
680 EnumLongId,
681 ast::ItemEnum,
682 lookup_intern_enum,
683 intern_enum
684);
685define_top_level_language_element_id!(
686 ModuleTypeAliasId,
687 ModuleTypeAliasLongId,
688 ast::ItemTypeAlias,
689 lookup_intern_module_type_alias,
690 intern_module_type_alias
691);
692define_top_level_language_element_id!(
693 ImplAliasId,
694 ImplAliasLongId,
695 ast::ItemImplAlias,
696 lookup_intern_impl_alias,
697 intern_impl_alias
698);
699define_top_level_language_element_id!(
700 ExternTypeId,
701 ExternTypeLongId,
702 ast::ItemExternType,
703 lookup_intern_extern_type,
704 intern_extern_type
705);
706
707define_top_level_language_element_id!(
709 TraitId,
710 TraitLongId,
711 ast::ItemTrait,
712 lookup_intern_trait,
713 intern_trait
714);
715
716define_named_language_element_id!(
718 TraitTypeId,
719 TraitTypeLongId,
720 ast::TraitItemType,
721 lookup_intern_trait_type,
722 intern_trait_type
723);
724impl TraitTypeId {
725 pub fn trait_id(&self, db: &dyn DefsGroup) -> TraitId {
726 let TraitTypeLongId(module_file_id, ptr) = self.lookup_intern(db);
727 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
729 TraitLongId(module_file_id, trait_ptr).intern(db)
730 }
731}
732impl TopLevelLanguageElementId for TraitTypeId {
733 fn full_path(&self, db: &dyn DefsGroup) -> String {
734 format!("{}::{}", self.trait_id(db).full_path(db), self.name(db))
735 }
736}
737impl UnstableSalsaId for TraitTypeId {
738 fn get_internal_id(&self) -> &salsa::InternId {
739 &self.0
740 }
741}
742
743define_named_language_element_id!(
745 TraitConstantId,
746 TraitConstantLongId,
747 ast::TraitItemConstant,
748 lookup_intern_trait_constant,
749 intern_trait_constant
750);
751impl TraitConstantId {
752 pub fn trait_id(&self, db: &dyn DefsGroup) -> TraitId {
753 let TraitConstantLongId(module_file_id, ptr) = self.lookup_intern(db);
754 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
756 TraitLongId(module_file_id, trait_ptr).intern(db)
757 }
758}
759impl TopLevelLanguageElementId for TraitConstantId {
760 fn full_path(&self, db: &dyn DefsGroup) -> String {
761 format!("{}::{}", self.trait_id(db).full_path(db), self.name(db))
762 }
763}
764
765define_named_language_element_id!(
767 TraitImplId,
768 TraitImplLongId,
769 ast::TraitItemImpl,
770 lookup_intern_trait_impl,
771 intern_trait_impl
772);
773impl TraitImplId {
774 pub fn trait_id(&self, db: &dyn DefsGroup) -> TraitId {
775 let TraitImplLongId(module_file_id, ptr) = self.lookup_intern(db);
776 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
778 TraitLongId(module_file_id, trait_ptr).intern(db)
779 }
780}
781impl TopLevelLanguageElementId for TraitImplId {
782 fn full_path(&self, db: &dyn DefsGroup) -> String {
783 format!("{}::{}", self.trait_id(db).full_path(db), self.name(db))
784 }
785}
786
787define_named_language_element_id!(
789 TraitFunctionId,
790 TraitFunctionLongId,
791 ast::TraitItemFunction,
792 lookup_intern_trait_function,
793 intern_trait_function
794);
795impl TraitFunctionId {
796 pub fn trait_id(&self, db: &dyn DefsGroup) -> TraitId {
797 let TraitFunctionLongId(module_file_id, ptr) = self.lookup_intern(db);
798 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
800 TraitLongId(module_file_id, trait_ptr).intern(db)
801 }
802}
803impl TopLevelLanguageElementId for TraitFunctionId {
804 fn full_path(&self, db: &dyn DefsGroup) -> String {
805 format!("{}::{}", self.trait_id(db).full_path(db), self.name(db))
806 }
807}
808
809define_named_language_element_id!(
811 MemberId,
812 MemberLongId,
813 ast::Member,
814 lookup_intern_member,
815 intern_member
816);
817impl MemberId {
818 pub fn struct_id(&self, db: &dyn DefsGroup) -> StructId {
819 let MemberLongId(module_file_id, ptr) = self.lookup_intern(db);
820 let struct_ptr = ast::ItemStructPtr(ptr.untyped().nth_parent(db, 2));
821 StructLongId(module_file_id, struct_ptr).intern(db)
822 }
823}
824
825impl TopLevelLanguageElementId for MemberId {
826 fn full_path(&self, db: &dyn DefsGroup) -> String {
827 format!("{}::{}", self.struct_id(db).full_path(db), self.name(db))
828 }
829}
830
831define_named_language_element_id!(
833 VariantId,
834 VariantLongId,
835 ast::Variant,
836 lookup_intern_variant,
837 intern_variant
838);
839impl VariantId {
840 pub fn enum_id(&self, db: &dyn DefsGroup) -> EnumId {
841 let VariantLongId(module_file_id, ptr) = self.lookup_intern(db);
842 let struct_ptr = ast::ItemEnumPtr(ptr.untyped().nth_parent(db, 2));
843 EnumLongId(module_file_id, struct_ptr).intern(db)
844 }
845}
846
847impl TopLevelLanguageElementId for VariantId {
848 fn full_path(&self, db: &dyn DefsGroup) -> String {
849 format!("{}::{}", self.enum_id(db).full_path(db), self.name(db))
850 }
851}
852
853define_language_element_id_as_enum! {
854 pub enum VarId {
856 Param(ParamId),
857 Local(LocalVarId),
858 Item(StatementItemId),
859 }
861}
862
863define_top_level_language_element_id!(
865 ParamId,
866 ParamLongId,
867 ast::Param,
868 lookup_intern_param,
869 intern_param
870);
871define_language_element_id_basic!(
872 GenericParamId,
873 GenericParamLongId,
874 ast::GenericParam,
875 lookup_intern_generic_param,
876 intern_generic_param
877);
878impl GenericParamLongId {
879 pub fn name(&self, db: &dyn SyntaxGroup) -> Option<SmolStr> {
880 let SyntaxStablePtr::Child { key_fields, kind, .. } = self.1.0.lookup_intern(db) else {
881 unreachable!()
882 };
883 require(!matches!(
884 kind,
885 SyntaxKind::GenericParamImplAnonymous | SyntaxKind::GenericParamNegativeImpl
886 ))?;
887
888 let name_green = TerminalIdentifierGreen(key_fields[0]);
889 Some(name_green.identifier(db))
890 }
891
892 pub fn debug_name(&self, db: &dyn SyntaxGroup) -> SmolStr {
893 self.name(db).unwrap_or_else(|| "_".into())
894 }
895 pub fn kind(&self, db: &dyn SyntaxGroup) -> GenericKind {
896 let SyntaxStablePtr::Child { kind, .. } = self.1.0.lookup_intern(db) else {
897 unreachable!()
898 };
899 match kind {
900 SyntaxKind::GenericParamType => GenericKind::Type,
901 SyntaxKind::GenericParamConst => GenericKind::Const,
902 SyntaxKind::GenericParamImplNamed | SyntaxKind::GenericParamImplAnonymous => {
903 GenericKind::Impl
904 }
905 SyntaxKind::GenericParamNegativeImpl => GenericKind::NegImpl,
906 _ => unreachable!(),
907 }
908 }
909 pub fn generic_item(&self, db: &dyn DefsGroup) -> GenericItemId {
911 let item_ptr = self.1.0.nth_parent(db, 3);
912 GenericItemId::from_ptr(db, self.0, item_ptr)
913 }
914}
915impl GenericParamId {
916 pub fn name(&self, db: &dyn DefsGroup) -> Option<SmolStr> {
917 self.lookup_intern(db).name(db)
918 }
919 pub fn debug_name(&self, db: &dyn DefsGroup) -> SmolStr {
920 self.lookup_intern(db).debug_name(db)
921 }
922 pub fn format(&self, db: &dyn DefsGroup) -> String {
923 let long_ids = self.lookup_intern(db);
924 let SyntaxStablePtr::Child { key_fields, kind, .. } = long_ids.1.0.lookup_intern(db) else {
925 unreachable!()
926 };
927
928 if matches!(
929 kind,
930 SyntaxKind::GenericParamImplAnonymous | SyntaxKind::GenericParamNegativeImpl
931 ) {
932 return self.stable_location(db).syntax_node(db).get_text_without_trivia(db);
934 }
935
936 let name_green = TerminalIdentifierGreen(key_fields[0]);
937 name_green.identifier(db).into()
938 }
939
940 pub fn kind(&self, db: &dyn DefsGroup) -> GenericKind {
941 self.lookup_intern(db).kind(db)
942 }
943 pub fn generic_item(&self, db: &dyn DefsGroup) -> GenericItemId {
944 self.lookup_intern(db).generic_item(db)
945 }
946}
947impl DebugWithDb<dyn DefsGroup> for GenericParamLongId {
948 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &dyn DefsGroup) -> std::fmt::Result {
949 write!(
950 f,
951 "GenericParam{}({}::{})",
952 self.kind(db),
953 self.generic_item(db).full_path(db),
954 self.debug_name(db)
955 )
956 }
957}
958
959define_language_element_id_as_enum! {
960 #[toplevel]
961 pub enum GenericModuleItemId {
963 FreeFunc(FreeFunctionId),
964 ExternFunc(ExternFunctionId),
965 TraitFunc(TraitFunctionId),
966 ImplFunc(ImplFunctionId),
967 Trait(TraitId),
968 Impl(ImplDefId),
969 Struct(StructId),
970 Enum(EnumId),
971 ExternType(ExternTypeId),
972 TypeAlias(ModuleTypeAliasId),
973 ImplAlias(ImplAliasId),
974 }
975}
976define_language_element_id_as_enum! {
977 #[toplevel]
978 pub enum GenericTraitItemId {
980 Type(TraitTypeId),
981 }
982}
983define_language_element_id_as_enum! {
984 #[toplevel]
985 pub enum GenericImplItemId {
987 Type(ImplTypeDefId),
988 }
989}
990
991define_language_element_id_as_enum! {
992 #[toplevel]
993 pub enum GenericItemId {
995 ModuleItem(GenericModuleItemId),
996 TraitItem(GenericTraitItemId),
997 ImplItem(GenericImplItemId),
998 }
999}
1000impl GenericItemId {
1001 pub fn from_ptr(
1002 db: &dyn DefsGroup,
1003 module_file: ModuleFileId,
1004 stable_ptr: SyntaxStablePtrId,
1005 ) -> Self {
1006 let SyntaxStablePtr::Child { parent: parent0, kind, .. } = stable_ptr.lookup_intern(db)
1007 else {
1008 panic!()
1009 };
1010 match kind {
1011 SyntaxKind::FunctionDeclaration => {
1012 let SyntaxStablePtr::Child { parent: parent1, kind, .. } =
1013 parent0.lookup_intern(db)
1014 else {
1015 panic!()
1016 };
1017 match kind {
1018 SyntaxKind::FunctionWithBody => {
1019 match parent1.parent(db).lookup_intern(db) {
1022 SyntaxStablePtr::Root(_, _) => {
1023 GenericItemId::ModuleItem(GenericModuleItemId::FreeFunc(
1024 FreeFunctionLongId(
1025 module_file,
1026 ast::FunctionWithBodyPtr(parent0),
1027 )
1028 .intern(db),
1029 ))
1030 }
1031 SyntaxStablePtr::Child { kind, .. } => match kind {
1032 SyntaxKind::ModuleBody => {
1033 GenericItemId::ModuleItem(GenericModuleItemId::FreeFunc(
1034 FreeFunctionLongId(
1035 module_file,
1036 ast::FunctionWithBodyPtr(parent0),
1037 )
1038 .intern(db),
1039 ))
1040 }
1041 SyntaxKind::ImplBody => {
1042 GenericItemId::ModuleItem(GenericModuleItemId::ImplFunc(
1043 ImplFunctionLongId(
1044 module_file,
1045 ast::FunctionWithBodyPtr(parent0),
1046 )
1047 .intern(db),
1048 ))
1049 }
1050 _ => panic!(),
1051 },
1052 }
1053 }
1054 SyntaxKind::ItemExternFunction => {
1055 GenericItemId::ModuleItem(GenericModuleItemId::ExternFunc(
1056 ExternFunctionLongId(module_file, ast::ItemExternFunctionPtr(parent0))
1057 .intern(db),
1058 ))
1059 }
1060 SyntaxKind::TraitItemFunction => {
1061 GenericItemId::ModuleItem(GenericModuleItemId::TraitFunc(
1062 TraitFunctionLongId(module_file, ast::TraitItemFunctionPtr(parent0))
1063 .intern(db),
1064 ))
1065 }
1066 _ => panic!(),
1067 }
1068 }
1069 SyntaxKind::ItemImpl => GenericItemId::ModuleItem(GenericModuleItemId::Impl(
1070 ImplDefLongId(module_file, ast::ItemImplPtr(stable_ptr)).intern(db),
1071 )),
1072 SyntaxKind::ItemTrait => GenericItemId::ModuleItem(GenericModuleItemId::Trait(
1073 TraitLongId(module_file, ast::ItemTraitPtr(stable_ptr)).intern(db),
1074 )),
1075 SyntaxKind::ItemStruct => GenericItemId::ModuleItem(GenericModuleItemId::Struct(
1076 StructLongId(module_file, ast::ItemStructPtr(stable_ptr)).intern(db),
1077 )),
1078 SyntaxKind::ItemEnum => GenericItemId::ModuleItem(GenericModuleItemId::Enum(
1079 EnumLongId(module_file, ast::ItemEnumPtr(stable_ptr)).intern(db),
1080 )),
1081 SyntaxKind::ItemExternType => {
1082 GenericItemId::ModuleItem(GenericModuleItemId::ExternType(
1083 ExternTypeLongId(module_file, ast::ItemExternTypePtr(stable_ptr)).intern(db),
1084 ))
1085 }
1086 SyntaxKind::ItemTypeAlias => {
1087 match parent0.kind(db) {
1090 SyntaxKind::ModuleItemList => {
1091 GenericItemId::ModuleItem(GenericModuleItemId::TypeAlias(
1092 ModuleTypeAliasLongId(module_file, ast::ItemTypeAliasPtr(stable_ptr))
1093 .intern(db),
1094 ))
1095 }
1096 SyntaxKind::ImplItemList => GenericItemId::ImplItem(GenericImplItemId::Type(
1097 ImplTypeDefLongId(module_file, ast::ItemTypeAliasPtr(stable_ptr))
1098 .intern(db),
1099 )),
1100 _ => panic!(),
1101 }
1102 }
1103 SyntaxKind::ItemImplAlias => GenericItemId::ModuleItem(GenericModuleItemId::ImplAlias(
1104 ImplAliasLongId(module_file, ast::ItemImplAliasPtr(stable_ptr)).intern(db),
1105 )),
1106 SyntaxKind::TraitItemType => GenericItemId::TraitItem(GenericTraitItemId::Type(
1107 TraitTypeLongId(module_file, ast::TraitItemTypePtr(stable_ptr)).intern(db),
1108 )),
1109 _ => panic!(),
1110 }
1111 }
1112}
1113
1114#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
1115pub enum GenericKind {
1116 Type,
1117 Const,
1118 Impl,
1119 NegImpl,
1120}
1121impl std::fmt::Display for GenericKind {
1122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1123 match self {
1124 GenericKind::Type => write!(f, "Type"),
1125 GenericKind::Const => write!(f, "Const"),
1126 GenericKind::Impl => write!(f, "Impl"),
1127 GenericKind::NegImpl => write!(f, "-Impl"),
1128 }
1129 }
1130}
1131
1132define_language_element_id_basic!(
1135 LocalVarId,
1136 LocalVarLongId,
1137 ast::TerminalIdentifier,
1138 lookup_intern_local_var,
1139 intern_local_var
1140);
1141impl DebugWithDb<dyn DefsGroup> for LocalVarLongId {
1142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &dyn DefsGroup) -> std::fmt::Result {
1143 let LocalVarLongId(module_file_id, ptr) = self;
1144 let text = ptr.lookup(db).text(db);
1145 write!(f, "LocalVarId({}::{})", module_file_id.0.full_path(db), text)
1146 }
1147}
1148
1149define_top_level_language_element_id!(
1150 StatementConstId,
1151 StatementConstLongId,
1152 ast::ItemConstant,
1153 lookup_intern_statement_const,
1154 intern_statement_const
1155);
1156
1157define_top_level_language_element_id!(
1158 StatementUseId,
1159 StatementUseLongId,
1160 ast::UsePathLeaf,
1161 lookup_intern_statement_use,
1162 intern_statement_use
1163);
1164
1165define_language_element_id_as_enum! {
1166 #[toplevel]
1167 pub enum FunctionTitleId {
1169 Free(FreeFunctionId),
1170 Extern(ExternFunctionId),
1171 Trait(TraitFunctionId),
1172 Impl(ImplFunctionId),
1173 }
1174}
1175impl FunctionTitleId {
1176 pub fn format(&self, db: &dyn DefsGroup) -> String {
1177 let function_name = match *self {
1178 FunctionTitleId::Free(_) | FunctionTitleId::Extern(_) => self.name(db).into(),
1179 FunctionTitleId::Trait(id) => id.full_path(db),
1180 FunctionTitleId::Impl(id) => id.full_path(db),
1181 };
1182 format!("{}::{}", self.parent_module(db).full_path(db), function_name)
1183 }
1184}
1185
1186define_language_element_id_as_enum! {
1187 #[toplevel]
1188 pub enum GenericTypeId {
1190 Struct(StructId),
1191 Enum(EnumId),
1192 Extern(ExternTypeId),
1193 }
1195}
1196impl GenericTypeId {
1197 pub fn format(&self, db: &dyn DefsGroup) -> String {
1198 format!("{}::{}", self.parent_module(db).full_path(db), self.name(db))
1199 }
1200}
1201
1202impl OptionFrom<ModuleItemId> for GenericTypeId {
1204 fn option_from(item: ModuleItemId) -> Option<Self> {
1205 match item {
1206 ModuleItemId::Struct(id) => Some(GenericTypeId::Struct(id)),
1207 ModuleItemId::Enum(id) => Some(GenericTypeId::Enum(id)),
1208 ModuleItemId::ExternType(id) => Some(GenericTypeId::Extern(id)),
1209 ModuleItemId::Constant(_)
1210 | ModuleItemId::Submodule(_)
1211 | ModuleItemId::TypeAlias(_)
1212 | ModuleItemId::ImplAlias(_)
1213 | ModuleItemId::Use(_)
1214 | ModuleItemId::FreeFunction(_)
1215 | ModuleItemId::Trait(_)
1216 | ModuleItemId::Impl(_)
1217 | ModuleItemId::ExternFunction(_)
1218 | ModuleItemId::MacroDeclaration(_) => None,
1219 }
1220 }
1221}
1222
1223impl From<GenericItemId> for LookupItemId {
1225 fn from(item: GenericItemId) -> Self {
1226 match item {
1227 GenericItemId::ModuleItem(module_item) => match module_item {
1228 GenericModuleItemId::FreeFunc(id) => {
1229 LookupItemId::ModuleItem(ModuleItemId::FreeFunction(id))
1230 }
1231 GenericModuleItemId::ExternFunc(id) => {
1232 LookupItemId::ModuleItem(ModuleItemId::ExternFunction(id))
1233 }
1234 GenericModuleItemId::TraitFunc(id) => {
1235 LookupItemId::TraitItem(TraitItemId::Function(id))
1236 }
1237 GenericModuleItemId::ImplFunc(id) => {
1238 LookupItemId::ImplItem(ImplItemId::Function(id))
1239 }
1240 GenericModuleItemId::Trait(id) => LookupItemId::ModuleItem(ModuleItemId::Trait(id)),
1241 GenericModuleItemId::Impl(id) => LookupItemId::ModuleItem(ModuleItemId::Impl(id)),
1242 GenericModuleItemId::Struct(id) => {
1243 LookupItemId::ModuleItem(ModuleItemId::Struct(id))
1244 }
1245 GenericModuleItemId::Enum(id) => LookupItemId::ModuleItem(ModuleItemId::Enum(id)),
1246 GenericModuleItemId::ExternType(id) => {
1247 LookupItemId::ModuleItem(ModuleItemId::ExternType(id))
1248 }
1249 GenericModuleItemId::TypeAlias(id) => {
1250 LookupItemId::ModuleItem(ModuleItemId::TypeAlias(id))
1251 }
1252 GenericModuleItemId::ImplAlias(id) => {
1253 LookupItemId::ModuleItem(ModuleItemId::ImplAlias(id))
1254 }
1255 },
1256 GenericItemId::TraitItem(trait_item) => match trait_item {
1257 GenericTraitItemId::Type(id) => LookupItemId::TraitItem(TraitItemId::Type(id)),
1258 },
1259 GenericItemId::ImplItem(impl_item) => match impl_item {
1260 GenericImplItemId::Type(id) => LookupItemId::ImplItem(ImplItemId::Type(id)),
1261 },
1262 }
1263 }
1264}
1265
1266define_language_element_id_as_enum! {
1267 #[toplevel]
1268 pub enum StatementItemId {
1269 Constant(StatementConstId),
1270 Use(StatementUseId),
1271 }
1272}
1273
1274impl StatementItemId {
1275 pub fn name(&self, db: &dyn DefsGroup) -> SmolStr {
1276 match self {
1277 StatementItemId::Constant(id) => id.name(db),
1278 StatementItemId::Use(id) => id.name(db),
1279 }
1280 }
1281 pub fn name_stable_ptr(&self, db: &dyn DefsGroup) -> SyntaxStablePtrId {
1282 match self {
1283 StatementItemId::Constant(id) => {
1284 id.lookup_intern(db).1.lookup(db).name(db).stable_ptr(db).untyped()
1285 }
1286 StatementItemId::Use(id) => id.lookup_intern(db).1.lookup(db).name_stable_ptr(db),
1287 }
1288 }
1289}
1290
1291define_language_element_id_as_enum! {
1292 #[toplevel]
1293 pub enum TraitItemId {
1295 Function(TraitFunctionId),
1296 Type(TraitTypeId),
1297 Constant(TraitConstantId),
1298 Impl(TraitImplId),
1299 }
1300}
1301impl TraitItemId {
1302 pub fn name(&self, db: &dyn DefsGroup) -> SmolStr {
1303 match self {
1304 TraitItemId::Function(id) => id.name(db),
1305 TraitItemId::Type(id) => id.name(db),
1306 TraitItemId::Constant(id) => id.name(db),
1307 TraitItemId::Impl(id) => id.name(db),
1308 }
1309 }
1310 pub fn trait_id(&self, db: &dyn DefsGroup) -> TraitId {
1311 match self {
1312 TraitItemId::Function(id) => id.trait_id(db),
1313 TraitItemId::Type(id) => id.trait_id(db),
1314 TraitItemId::Constant(id) => id.trait_id(db),
1315 TraitItemId::Impl(id) => id.trait_id(db),
1316 }
1317 }
1318}
1319
1320define_language_element_id_as_enum! {
1321 #[toplevel]
1322 pub enum ImplItemId {
1324 Function(ImplFunctionId),
1325 Type(ImplTypeDefId),
1326 Constant(ImplConstantDefId),
1327 Impl(ImplImplDefId),
1328 }
1329}
1330impl ImplItemId {
1331 pub fn name(&self, db: &dyn DefsGroup) -> SmolStr {
1332 match self {
1333 ImplItemId::Function(id) => id.name(db),
1334 ImplItemId::Type(id) => id.name(db),
1335 ImplItemId::Constant(id) => id.name(db),
1336 ImplItemId::Impl(id) => id.name(db),
1337 }
1338 }
1339 pub fn impl_def_id(&self, db: &dyn DefsGroup) -> ImplDefId {
1340 match self {
1341 ImplItemId::Function(id) => id.impl_def_id(db),
1342 ImplItemId::Type(id) => id.impl_def_id(db),
1343 ImplItemId::Constant(id) => id.impl_def_id(db),
1344 ImplItemId::Impl(id) => id.impl_def_id(db),
1345 }
1346 }
1347}
1348
1349define_language_element_id_as_enum! {
1350 #[toplevel]
1351 pub enum LookupItemId {
1355 ModuleItem(ModuleItemId),
1356 TraitItem(TraitItemId),
1357 ImplItem(ImplItemId),
1358 }
1359}