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