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