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}
579impl UnstableSalsaId for TraitTypeId {
580 fn get_internal_id(&self) -> &salsa::InternId {
581 &self.0
582 }
583}
584
585define_named_language_element_id!(
587 TraitConstantId,
588 TraitConstantLongId,
589 ast::TraitItemConstant,
590 lookup_intern_trait_constant,
591 intern_trait_constant
592);
593impl TraitConstantId {
594 pub fn trait_id(&self, db: &dyn DefsGroup) -> TraitId {
595 let TraitConstantLongId(module_file_id, ptr) = self.lookup_intern(db);
596 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db.upcast(), 3));
598 TraitLongId(module_file_id, trait_ptr).intern(db)
599 }
600}
601impl TopLevelLanguageElementId for TraitConstantId {
602 fn full_path(&self, db: &dyn DefsGroup) -> String {
603 format!("{}::{}", self.trait_id(db).full_path(db), self.name(db))
604 }
605}
606
607define_named_language_element_id!(
609 TraitImplId,
610 TraitImplLongId,
611 ast::TraitItemImpl,
612 lookup_intern_trait_impl,
613 intern_trait_impl
614);
615impl TraitImplId {
616 pub fn trait_id(&self, db: &dyn DefsGroup) -> TraitId {
617 let TraitImplLongId(module_file_id, ptr) = self.lookup_intern(db);
618 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db.upcast(), 3));
620 TraitLongId(module_file_id, trait_ptr).intern(db)
621 }
622}
623impl TopLevelLanguageElementId for TraitImplId {
624 fn full_path(&self, db: &dyn DefsGroup) -> String {
625 format!("{}::{}", self.trait_id(db).full_path(db), self.name(db))
626 }
627}
628
629define_named_language_element_id!(
631 TraitFunctionId,
632 TraitFunctionLongId,
633 ast::TraitItemFunction,
634 lookup_intern_trait_function,
635 intern_trait_function
636);
637impl TraitFunctionId {
638 pub fn trait_id(&self, db: &dyn DefsGroup) -> TraitId {
639 let TraitFunctionLongId(module_file_id, ptr) = self.lookup_intern(db);
640 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db.upcast(), 3));
642 TraitLongId(module_file_id, trait_ptr).intern(db)
643 }
644}
645impl TopLevelLanguageElementId for TraitFunctionId {
646 fn full_path(&self, db: &dyn DefsGroup) -> String {
647 format!("{}::{}", self.trait_id(db).full_path(db), self.name(db))
648 }
649}
650
651define_named_language_element_id!(
653 MemberId,
654 MemberLongId,
655 ast::Member,
656 lookup_intern_member,
657 intern_member
658);
659impl MemberId {
660 pub fn struct_id(&self, db: &dyn DefsGroup) -> StructId {
661 let MemberLongId(module_file_id, ptr) = self.lookup_intern(db);
662 let struct_ptr = ast::ItemStructPtr(ptr.untyped().nth_parent(db.upcast(), 2));
663 StructLongId(module_file_id, struct_ptr).intern(db)
664 }
665}
666
667impl TopLevelLanguageElementId for MemberId {
668 fn full_path(&self, db: &dyn DefsGroup) -> String {
669 format!("{}::{}", self.struct_id(db).full_path(db), self.name(db))
670 }
671}
672
673define_named_language_element_id!(
675 VariantId,
676 VariantLongId,
677 ast::Variant,
678 lookup_intern_variant,
679 intern_variant
680);
681impl VariantId {
682 pub fn enum_id(&self, db: &dyn DefsGroup) -> EnumId {
683 let VariantLongId(module_file_id, ptr) = self.lookup_intern(db);
684 let struct_ptr = ast::ItemEnumPtr(ptr.untyped().nth_parent(db.upcast(), 2));
685 EnumLongId(module_file_id, struct_ptr).intern(db)
686 }
687}
688
689impl TopLevelLanguageElementId for VariantId {
690 fn full_path(&self, db: &dyn DefsGroup) -> String {
691 format!("{}::{}", self.enum_id(db).full_path(db), self.name(db))
692 }
693}
694
695define_language_element_id_as_enum! {
696 pub enum VarId {
698 Param(ParamId),
699 Local(LocalVarId),
700 Item(StatementItemId),
701 }
703}
704
705define_top_level_language_element_id!(
707 ParamId,
708 ParamLongId,
709 ast::Param,
710 lookup_intern_param,
711 intern_param
712);
713define_language_element_id_basic!(
714 GenericParamId,
715 GenericParamLongId,
716 ast::GenericParam,
717 lookup_intern_generic_param,
718 intern_generic_param
719);
720impl GenericParamLongId {
721 pub fn name(&self, db: &dyn SyntaxGroup) -> Option<SmolStr> {
722 let SyntaxStablePtr::Child { key_fields, kind, .. } = self.1.0.lookup_intern(db) else {
723 unreachable!()
724 };
725 require(!matches!(
726 kind,
727 SyntaxKind::GenericParamImplAnonymous | SyntaxKind::GenericParamNegativeImpl
728 ))?;
729
730 let name_green = TerminalIdentifierGreen(key_fields[0]);
731 Some(name_green.identifier(db))
732 }
733
734 pub fn debug_name(&self, db: &dyn SyntaxGroup) -> SmolStr {
735 self.name(db).unwrap_or_else(|| "_".into())
736 }
737 pub fn kind(&self, db: &dyn SyntaxGroup) -> GenericKind {
738 let SyntaxStablePtr::Child { kind, .. } = self.1.0.lookup_intern(db) else {
739 unreachable!()
740 };
741 match kind {
742 SyntaxKind::GenericParamType => GenericKind::Type,
743 SyntaxKind::GenericParamConst => GenericKind::Const,
744 SyntaxKind::GenericParamImplNamed | SyntaxKind::GenericParamImplAnonymous => {
745 GenericKind::Impl
746 }
747 SyntaxKind::GenericParamNegativeImpl => GenericKind::NegImpl,
748 _ => unreachable!(),
749 }
750 }
751 pub fn generic_item(&self, db: &dyn DefsGroup) -> GenericItemId {
753 let item_ptr = self.1.0.nth_parent(db.upcast(), 3);
754 GenericItemId::from_ptr(db, self.0, item_ptr)
755 }
756}
757impl GenericParamId {
758 pub fn name(&self, db: &dyn DefsGroup) -> Option<SmolStr> {
759 self.lookup_intern(db).name(db.upcast())
760 }
761 pub fn debug_name(&self, db: &dyn DefsGroup) -> SmolStr {
762 self.lookup_intern(db).debug_name(db.upcast())
763 }
764 pub fn format(&self, db: &dyn DefsGroup) -> String {
765 let long_ids = self.lookup_intern(db);
766 let SyntaxStablePtr::Child { key_fields, kind, .. } = long_ids.1.0.lookup_intern(db) else {
767 unreachable!()
768 };
769
770 let syntax_db = db.upcast();
771 if matches!(
772 kind,
773 SyntaxKind::GenericParamImplAnonymous | SyntaxKind::GenericParamNegativeImpl
774 ) {
775 return self.stable_location(db).syntax_node(db).get_text_without_trivia(syntax_db);
777 }
778
779 let name_green = TerminalIdentifierGreen(key_fields[0]);
780 name_green.identifier(syntax_db).into()
781 }
782
783 pub fn kind(&self, db: &dyn DefsGroup) -> GenericKind {
784 self.lookup_intern(db).kind(db.upcast())
785 }
786 pub fn generic_item(&self, db: &dyn DefsGroup) -> GenericItemId {
787 self.lookup_intern(db).generic_item(db.upcast())
788 }
789}
790impl DebugWithDb<dyn DefsGroup> for GenericParamLongId {
791 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &dyn DefsGroup) -> std::fmt::Result {
792 write!(
793 f,
794 "GenericParam{}({}::{})",
795 self.kind(db.upcast()),
796 self.generic_item(db).full_path(db),
797 self.debug_name(db.upcast())
798 )
799 }
800}
801
802define_language_element_id_as_enum! {
803 #[toplevel]
804 pub enum GenericModuleItemId {
806 FreeFunc(FreeFunctionId),
807 ExternFunc(ExternFunctionId),
808 TraitFunc(TraitFunctionId),
809 ImplFunc(ImplFunctionId),
810 Trait(TraitId),
811 Impl(ImplDefId),
812 Struct(StructId),
813 Enum(EnumId),
814 ExternType(ExternTypeId),
815 TypeAlias(ModuleTypeAliasId),
816 ImplAlias(ImplAliasId),
817 }
818}
819define_language_element_id_as_enum! {
820 #[toplevel]
821 pub enum GenericTraitItemId {
823 Type(TraitTypeId),
824 }
825}
826define_language_element_id_as_enum! {
827 #[toplevel]
828 pub enum GenericImplItemId {
830 Type(ImplTypeDefId),
831 }
832}
833
834define_language_element_id_as_enum! {
835 #[toplevel]
836 pub enum GenericItemId {
838 ModuleItem(GenericModuleItemId),
839 TraitItem(GenericTraitItemId),
840 ImplItem(GenericImplItemId),
841 }
842}
843impl GenericItemId {
844 pub fn from_ptr(
845 db: &dyn DefsGroup,
846 module_file: ModuleFileId,
847 stable_ptr: SyntaxStablePtrId,
848 ) -> Self {
849 let SyntaxStablePtr::Child { parent: parent0, kind, .. } = stable_ptr.lookup_intern(db)
850 else {
851 panic!()
852 };
853 match kind {
854 SyntaxKind::FunctionDeclaration => {
855 let SyntaxStablePtr::Child { parent: parent1, kind, .. } =
856 parent0.lookup_intern(db)
857 else {
858 panic!()
859 };
860 match kind {
861 SyntaxKind::FunctionWithBody => {
862 match parent1.parent(db.upcast()).lookup_intern(db) {
865 SyntaxStablePtr::Root(_, _) => {
866 GenericItemId::ModuleItem(GenericModuleItemId::FreeFunc(
867 FreeFunctionLongId(
868 module_file,
869 ast::FunctionWithBodyPtr(parent0),
870 )
871 .intern(db),
872 ))
873 }
874 SyntaxStablePtr::Child { kind, .. } => match kind {
875 SyntaxKind::ModuleBody => {
876 GenericItemId::ModuleItem(GenericModuleItemId::FreeFunc(
877 FreeFunctionLongId(
878 module_file,
879 ast::FunctionWithBodyPtr(parent0),
880 )
881 .intern(db),
882 ))
883 }
884 SyntaxKind::ImplBody => {
885 GenericItemId::ModuleItem(GenericModuleItemId::ImplFunc(
886 ImplFunctionLongId(
887 module_file,
888 ast::FunctionWithBodyPtr(parent0),
889 )
890 .intern(db),
891 ))
892 }
893 _ => panic!(),
894 },
895 }
896 }
897 SyntaxKind::ItemExternFunction => {
898 GenericItemId::ModuleItem(GenericModuleItemId::ExternFunc(
899 ExternFunctionLongId(module_file, ast::ItemExternFunctionPtr(parent0))
900 .intern(db),
901 ))
902 }
903 SyntaxKind::TraitItemFunction => {
904 GenericItemId::ModuleItem(GenericModuleItemId::TraitFunc(
905 TraitFunctionLongId(module_file, ast::TraitItemFunctionPtr(parent0))
906 .intern(db),
907 ))
908 }
909 _ => panic!(),
910 }
911 }
912 SyntaxKind::ItemImpl => GenericItemId::ModuleItem(GenericModuleItemId::Impl(
913 ImplDefLongId(module_file, ast::ItemImplPtr(stable_ptr)).intern(db),
914 )),
915 SyntaxKind::ItemTrait => GenericItemId::ModuleItem(GenericModuleItemId::Trait(
916 TraitLongId(module_file, ast::ItemTraitPtr(stable_ptr)).intern(db),
917 )),
918 SyntaxKind::ItemStruct => GenericItemId::ModuleItem(GenericModuleItemId::Struct(
919 StructLongId(module_file, ast::ItemStructPtr(stable_ptr)).intern(db),
920 )),
921 SyntaxKind::ItemEnum => GenericItemId::ModuleItem(GenericModuleItemId::Enum(
922 EnumLongId(module_file, ast::ItemEnumPtr(stable_ptr)).intern(db),
923 )),
924 SyntaxKind::ItemExternType => {
925 GenericItemId::ModuleItem(GenericModuleItemId::ExternType(
926 ExternTypeLongId(module_file, ast::ItemExternTypePtr(stable_ptr)).intern(db),
927 ))
928 }
929 SyntaxKind::ItemTypeAlias => {
930 match parent0.kind(db.upcast()) {
933 SyntaxKind::ModuleItemList => {
934 GenericItemId::ModuleItem(GenericModuleItemId::TypeAlias(
935 ModuleTypeAliasLongId(module_file, ast::ItemTypeAliasPtr(stable_ptr))
936 .intern(db),
937 ))
938 }
939 SyntaxKind::ImplItemList => GenericItemId::ImplItem(GenericImplItemId::Type(
940 ImplTypeDefLongId(module_file, ast::ItemTypeAliasPtr(stable_ptr))
941 .intern(db),
942 )),
943 _ => panic!(),
944 }
945 }
946 SyntaxKind::ItemImplAlias => GenericItemId::ModuleItem(GenericModuleItemId::ImplAlias(
947 ImplAliasLongId(module_file, ast::ItemImplAliasPtr(stable_ptr)).intern(db),
948 )),
949 SyntaxKind::TraitItemType => GenericItemId::TraitItem(GenericTraitItemId::Type(
950 TraitTypeLongId(module_file, ast::TraitItemTypePtr(stable_ptr)).intern(db),
951 )),
952 _ => panic!(),
953 }
954 }
955}
956
957#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
958pub enum GenericKind {
959 Type,
960 Const,
961 Impl,
962 NegImpl,
963}
964impl std::fmt::Display for GenericKind {
965 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
966 match self {
967 GenericKind::Type => write!(f, "Type"),
968 GenericKind::Const => write!(f, "Const"),
969 GenericKind::Impl => write!(f, "Impl"),
970 GenericKind::NegImpl => write!(f, "-Impl"),
971 }
972 }
973}
974
975define_language_element_id_basic!(
978 LocalVarId,
979 LocalVarLongId,
980 ast::TerminalIdentifier,
981 lookup_intern_local_var,
982 intern_local_var
983);
984impl DebugWithDb<dyn DefsGroup> for LocalVarLongId {
985 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &dyn DefsGroup) -> std::fmt::Result {
986 let syntax_db = db.upcast();
987 let LocalVarLongId(module_file_id, ptr) = self;
988 let text = ptr.lookup(syntax_db).text(syntax_db);
989 write!(f, "LocalVarId({}::{})", module_file_id.0.full_path(db), text)
990 }
991}
992
993define_top_level_language_element_id!(
994 StatementConstId,
995 StatementConstLongId,
996 ast::ItemConstant,
997 lookup_intern_statement_const,
998 intern_statement_const
999);
1000
1001define_top_level_language_element_id!(
1002 StatementUseId,
1003 StatementUseLongId,
1004 ast::UsePathLeaf,
1005 lookup_intern_statement_use,
1006 intern_statement_use
1007);
1008
1009define_language_element_id_as_enum! {
1010 #[toplevel]
1011 pub enum FunctionTitleId {
1013 Free(FreeFunctionId),
1014 Extern(ExternFunctionId),
1015 Trait(TraitFunctionId),
1016 Impl(ImplFunctionId),
1017 }
1018}
1019impl FunctionTitleId {
1020 pub fn format(&self, db: &dyn DefsGroup) -> String {
1021 let function_name = match *self {
1022 FunctionTitleId::Free(_) | FunctionTitleId::Extern(_) => self.name(db).into(),
1023 FunctionTitleId::Trait(id) => id.full_path(db),
1024 FunctionTitleId::Impl(id) => id.full_path(db),
1025 };
1026 format!("{}::{}", self.parent_module(db).full_path(db), function_name)
1027 }
1028}
1029
1030define_language_element_id_as_enum! {
1031 #[toplevel]
1032 pub enum GenericTypeId {
1034 Struct(StructId),
1035 Enum(EnumId),
1036 Extern(ExternTypeId),
1037 }
1039}
1040impl GenericTypeId {
1041 pub fn format(&self, db: &dyn DefsGroup) -> String {
1042 format!("{}::{}", self.parent_module(db).full_path(db), self.name(db))
1043 }
1044}
1045
1046impl OptionFrom<ModuleItemId> for GenericTypeId {
1048 fn option_from(item: ModuleItemId) -> Option<Self> {
1049 match item {
1050 ModuleItemId::Struct(id) => Some(GenericTypeId::Struct(id)),
1051 ModuleItemId::Enum(id) => Some(GenericTypeId::Enum(id)),
1052 ModuleItemId::ExternType(id) => Some(GenericTypeId::Extern(id)),
1053 ModuleItemId::Constant(_)
1054 | ModuleItemId::Submodule(_)
1055 | ModuleItemId::TypeAlias(_)
1056 | ModuleItemId::ImplAlias(_)
1057 | ModuleItemId::Use(_)
1058 | ModuleItemId::FreeFunction(_)
1059 | ModuleItemId::Trait(_)
1060 | ModuleItemId::Impl(_)
1061 | ModuleItemId::ExternFunction(_) => None,
1062 }
1063 }
1064}
1065
1066impl From<GenericItemId> for LookupItemId {
1068 fn from(item: GenericItemId) -> Self {
1069 match item {
1070 GenericItemId::ModuleItem(module_item) => match module_item {
1071 GenericModuleItemId::FreeFunc(id) => {
1072 LookupItemId::ModuleItem(ModuleItemId::FreeFunction(id))
1073 }
1074 GenericModuleItemId::ExternFunc(id) => {
1075 LookupItemId::ModuleItem(ModuleItemId::ExternFunction(id))
1076 }
1077 GenericModuleItemId::TraitFunc(id) => {
1078 LookupItemId::TraitItem(TraitItemId::Function(id))
1079 }
1080 GenericModuleItemId::ImplFunc(id) => {
1081 LookupItemId::ImplItem(ImplItemId::Function(id))
1082 }
1083 GenericModuleItemId::Trait(id) => LookupItemId::ModuleItem(ModuleItemId::Trait(id)),
1084 GenericModuleItemId::Impl(id) => LookupItemId::ModuleItem(ModuleItemId::Impl(id)),
1085 GenericModuleItemId::Struct(id) => {
1086 LookupItemId::ModuleItem(ModuleItemId::Struct(id))
1087 }
1088 GenericModuleItemId::Enum(id) => LookupItemId::ModuleItem(ModuleItemId::Enum(id)),
1089 GenericModuleItemId::ExternType(id) => {
1090 LookupItemId::ModuleItem(ModuleItemId::ExternType(id))
1091 }
1092 GenericModuleItemId::TypeAlias(id) => {
1093 LookupItemId::ModuleItem(ModuleItemId::TypeAlias(id))
1094 }
1095 GenericModuleItemId::ImplAlias(id) => {
1096 LookupItemId::ModuleItem(ModuleItemId::ImplAlias(id))
1097 }
1098 },
1099 GenericItemId::TraitItem(trait_item) => match trait_item {
1100 GenericTraitItemId::Type(id) => LookupItemId::TraitItem(TraitItemId::Type(id)),
1101 },
1102 GenericItemId::ImplItem(impl_item) => match impl_item {
1103 GenericImplItemId::Type(id) => LookupItemId::ImplItem(ImplItemId::Type(id)),
1104 },
1105 }
1106 }
1107}
1108
1109define_language_element_id_as_enum! {
1110 #[toplevel]
1111 pub enum StatementItemId {
1112 Constant(StatementConstId),
1113 Use(StatementUseId),
1114 }
1115}
1116
1117impl StatementItemId {
1118 pub fn name(&self, db: &dyn DefsGroup) -> SmolStr {
1119 match self {
1120 StatementItemId::Constant(id) => id.name(db),
1121 StatementItemId::Use(id) => id.name(db),
1122 }
1123 }
1124 pub fn name_stable_ptr(&self, db: &dyn DefsGroup) -> SyntaxStablePtrId {
1125 match self {
1126 StatementItemId::Constant(id) => {
1127 id.lookup_intern(db).1.lookup(db.upcast()).name(db.upcast()).stable_ptr().untyped()
1128 }
1129 StatementItemId::Use(id) => {
1130 id.lookup_intern(db).1.lookup(db.upcast()).name_stable_ptr(db.upcast())
1131 }
1132 }
1133 }
1134}
1135
1136define_language_element_id_as_enum! {
1137 #[toplevel]
1138 pub enum TraitItemId {
1140 Function(TraitFunctionId),
1141 Type(TraitTypeId),
1142 Constant(TraitConstantId),
1143 Impl(TraitImplId),
1144 }
1145}
1146impl TraitItemId {
1147 pub fn name(&self, db: &dyn DefsGroup) -> SmolStr {
1148 match self {
1149 TraitItemId::Function(id) => id.name(db),
1150 TraitItemId::Type(id) => id.name(db),
1151 TraitItemId::Constant(id) => id.name(db),
1152 TraitItemId::Impl(id) => id.name(db),
1153 }
1154 }
1155 pub fn trait_id(&self, db: &dyn DefsGroup) -> TraitId {
1156 match self {
1157 TraitItemId::Function(id) => id.trait_id(db),
1158 TraitItemId::Type(id) => id.trait_id(db),
1159 TraitItemId::Constant(id) => id.trait_id(db),
1160 TraitItemId::Impl(id) => id.trait_id(db),
1161 }
1162 }
1163}
1164
1165define_language_element_id_as_enum! {
1166 #[toplevel]
1167 pub enum ImplItemId {
1169 Function(ImplFunctionId),
1170 Type(ImplTypeDefId),
1171 Constant(ImplConstantDefId),
1172 Impl(ImplImplDefId),
1173 }
1174}
1175impl ImplItemId {
1176 pub fn name(&self, db: &dyn DefsGroup) -> SmolStr {
1177 match self {
1178 ImplItemId::Function(id) => id.name(db),
1179 ImplItemId::Type(id) => id.name(db),
1180 ImplItemId::Constant(id) => id.name(db),
1181 ImplItemId::Impl(id) => id.name(db),
1182 }
1183 }
1184 pub fn impl_def_id(&self, db: &dyn DefsGroup) -> ImplDefId {
1185 match self {
1186 ImplItemId::Function(id) => id.impl_def_id(db),
1187 ImplItemId::Type(id) => id.impl_def_id(db),
1188 ImplItemId::Constant(id) => id.impl_def_id(db),
1189 ImplItemId::Impl(id) => id.impl_def_id(db),
1190 }
1191 }
1192}
1193
1194define_language_element_id_as_enum! {
1195 pub enum LookupItemId {
1199 ModuleItem(ModuleItemId),
1200 TraitItem(TraitItemId),
1201 ImplItem(ImplItemId),
1202 }
1203}