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, SmolStrId};
31use cairo_lang_proc_macros::HeapSize;
32use cairo_lang_syntax::node::ast::TerminalIdentifierGreen;
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::{Terminal, TypedStablePtr, TypedSyntaxNode, ast};
37use cairo_lang_utils::{Intern, OptionFrom, define_short_id, require};
38use itertools::Itertools;
39use salsa::Database;
40
41use crate::db::ModuleData;
42use crate::diagnostic_utils::StableLocation;
43use crate::plugin::{InlineMacroExprPlugin, MacroPlugin};
44
45pub trait LanguageElementId<'db> {
47 fn parent_module(&self, db: &'db dyn Database) -> ModuleId<'db>;
48 fn untyped_stable_ptr(&self, db: &'db dyn Database) -> SyntaxStablePtrId<'db>;
49
50 fn stable_location(&self, db: &'db dyn Database) -> StableLocation<'db>;
51
52 fn module_data(&self, db: &'db dyn Database) -> Maybe<ModuleData<'db>> {
53 self.parent_module(db).module_data(db)
54 }
55}
56
57pub trait NamedLanguageElementLongId<'db> {
58 fn name(&self, db: &'db dyn Database) -> SmolStrId<'db>;
59 fn name_identifier(&'db self, db: &'db dyn Database) -> ast::TerminalIdentifier<'db>;
60}
61pub trait NamedLanguageElementId<'db>: LanguageElementId<'db> {
62 fn name(&self, db: &'db dyn Database) -> SmolStrId<'db>;
63 fn name_identifier(&'db self, db: &'db dyn Database) -> ast::TerminalIdentifier<'db>;
64}
65pub trait TopLevelLanguageElementId<'db>: NamedLanguageElementId<'db> {
66 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
68 let mut segments = self.parent_module(db).path_segments(db);
69 segments.push(self.name(db));
70 segments
71 }
72
73 fn full_path(&self, db: &'db dyn Database) -> String {
74 self.path_segments(db).iter().map(|s| s.long(db)).join("::")
75 }
76}
77
78macro_rules! define_top_level_language_element_id {
86 ($short_id:ident, $long_id:ident, $ast_ty:ty) => {
87 define_named_language_element_id!($short_id, $long_id, $ast_ty);
88 impl<'db> TopLevelLanguageElementId<'db> for $short_id<'db> {}
89 };
90}
91
92macro_rules! define_named_language_element_id {
99 ($short_id:ident, $long_id:ident, $ast_ty:ty) => {
100 define_language_element_id_basic!($short_id, $long_id, $ast_ty);
101 impl<'db> cairo_lang_debug::DebugWithDb<'db> for $long_id<'db> {
102 type Db = dyn Database;
103
104 fn fmt(
105 &self,
106 f: &mut std::fmt::Formatter<'_>,
107 db: &'db dyn Database,
108 ) -> std::fmt::Result {
109 write!(f, "{}({})", stringify!($short_id), self.clone().intern(db).full_path(db))
110 }
111 }
112 impl<'db> NamedLanguageElementLongId<'db> for $long_id<'db> {
113 fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
114 let terminal_green = self.1.name_green(db);
115 terminal_green.identifier(db)
116 }
117 fn name_identifier(&'db self, db: &'db dyn Database) -> ast::TerminalIdentifier<'db> {
118 let long = self.1.lookup(db);
119 long.name(db)
120 }
121 }
122 impl<'db> NamedLanguageElementId<'db> for $short_id<'db> {
123 fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
124 self.long(db).name(db)
125 }
126 fn name_identifier(&'db self, db: &'db dyn Database) -> ast::TerminalIdentifier<'db> {
127 let x = self.long(db);
128 x.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) => {
141 #[derive(Clone, PartialEq, Eq, Hash, Debug, salsa::Update, HeapSize)]
142 pub struct $long_id<'db>(
143 pub ModuleId<'db>,
144 pub <$ast_ty as TypedSyntaxNode<'db>>::StablePtr,
145 );
146 define_short_id!($short_id, $long_id<'db>);
147 impl<'db> $short_id<'db> {
148 pub fn stable_ptr(
149 &self,
150 db: &'db dyn Database,
151 ) -> <$ast_ty as TypedSyntaxNode<'db>>::StablePtr {
152 self.long(db).1
153 }
154 }
155 impl<'db> LanguageElementId<'db> for $short_id<'db> {
156 fn parent_module(&self, db: &'db dyn Database) -> ModuleId<'db> {
157 self.long(db).0
158 }
159 fn untyped_stable_ptr(&self, db: &'db dyn Database) -> SyntaxStablePtrId<'db> {
160 let stable_ptr = self.stable_ptr(db);
161 stable_ptr.untyped()
162 }
163 fn stable_location(&self, db: &'db dyn Database) -> StableLocation<'db> {
164 let $long_id(_module_id, stable_ptr) = self.long(db);
165 StableLocation::new(stable_ptr.untyped())
166 }
167 }
168 };
169}
170
171macro_rules! define_language_element_id_as_enum {
173 (
174 #[toplevel]
175 $(#[doc = $doc:expr])*
176 pub enum $enum_name:ident<$lifetime:lifetime> {
177 $($variant:ident ($variant_ty:ty),)*
178 }
179 ) => {
180 toplevel_enum! {
181 pub enum $enum_name<$lifetime> {
182 $($variant($variant_ty),)*
183 }
184 }
185 define_language_element_id_as_enum! {
186 $(#[doc = $doc])*
187 pub enum $enum_name<$lifetime> {
188 $($variant($variant_ty),)*
189 }
190 }
191 };
192 (
193 $(#[doc = $doc:expr])*
194 pub enum $enum_name:ident<$lifetime:lifetime> {
195 $($variant:ident ($variant_ty:ty),)*
196 }
197 ) => {
198 $(#[doc = $doc])*
199 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HeapSize, salsa::Update)]
200 pub enum $enum_name<$lifetime> {
201 $($variant($variant_ty),)*
202 }
203 impl<'db> cairo_lang_debug::DebugWithDb<'db> for $enum_name<'_> {
204 type Db = dyn Database;
205
206 fn fmt(
207 &self,
208 f: &mut std::fmt::Formatter<'_>,
209 db: &'db dyn Database,
210 ) -> std::fmt::Result {
211 match self {
212 $(
213 $enum_name::$variant(id) => id.fmt(f, db),
214 )*
215 }
216 }
217 }
218 impl<'db> LanguageElementId<'db> for $enum_name<'db> {
219 fn parent_module(&self, db: &'db dyn Database) -> ModuleId<'db> {
220 match self {
221 $(
222 $enum_name::$variant(id) => id.parent_module(db),
223 )*
224 }
225 }
226 fn untyped_stable_ptr(&self, db: &'db dyn Database) -> SyntaxStablePtrId<'db> {
227 match self {
228 $(
229 $enum_name::$variant(id) => id.untyped_stable_ptr(db),
230 )*
231 }
232 }
233 fn stable_location(&self, db: &'db dyn Database) -> StableLocation<'db> {
234 match self {
235 $(
236 $enum_name::$variant(id) => id.stable_location(db),
237 )*
238 }
239 }
240
241 }
242
243 $(
245 impl<$lifetime> OptionFrom<$enum_name<$lifetime>> for $variant_ty {
246 fn option_from(other: $enum_name<$lifetime>) -> Option<Self> {
247 #[allow(irrefutable_let_patterns)]
248 if let $enum_name::$variant(id) = other {
249 Some(id)
250 } else {
251 None
252 }
253 }
254 }
255 )*
256 };
257}
258
259macro_rules! toplevel_enum {
260 (
261 pub enum $enum_name:ident<$lifetime:lifetime> {
262 $($variant:ident ($variant_ty:ty),)*
263 }
264 ) => {
265 impl<'db> NamedLanguageElementId<'db> for $enum_name<'db> {
266 fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
267 match self {
268 $(
269 $enum_name::$variant(id) => id.name(db),
270 )*
271 }
272 }
273 fn name_identifier(&'db self, db: &'db dyn Database) -> ast::TerminalIdentifier<'db> {
274 match self {
275 $(
276 $enum_name::$variant(id) => id.name_identifier(db),
277 )*
278 }
279 }
280 }
281 impl<'db> TopLevelLanguageElementId<'db> for $enum_name<'db> {
282 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
283 match self {
284 $(
285 $enum_name::$variant(id) => id.path_segments(db),
286 )*
287 }
288 }
289 }
290 }
291}
292
293#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, salsa::Update, HeapSize)]
296pub enum ModuleId<'db> {
297 CrateRoot(CrateId<'db>),
298 Submodule(SubmoduleId<'db>),
299 MacroCall {
302 id: MacroCallId<'db>,
304 generated_file_id: FileId<'db>,
306 is_expose: bool,
308 },
309}
310impl<'db> ModuleId<'db> {
311 pub fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
313 match self {
314 ModuleId::CrateRoot(id) => vec![id.long(db).name()],
315 ModuleId::Submodule(id) => {
316 let mut segments = id.parent_module(db).path_segments(db);
317 segments.push(id.name(db));
318 segments
319 }
320 ModuleId::MacroCall { id, .. } => {
321 let mut segments = id.parent_module(db).path_segments(db);
322 segments.push(self.name(db));
323 segments
324 }
325 }
326 }
327
328 pub fn full_path(&self, db: &'db dyn Database) -> String {
329 self.path_segments(db).iter().map(|s| s.long(db)).join("::")
330 }
331 pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
332 match self {
333 ModuleId::CrateRoot(id) => id.long(db).name(),
334 ModuleId::Submodule(id) => id.name(db),
335 ModuleId::MacroCall { id, .. } => {
336 let inline_macro = id.stable_ptr(db).lookup(db);
339 let macro_name = inline_macro.path(db).identifier(db);
340 let offset = inline_macro.as_syntax_node().offset(db).as_u32();
341 SmolStrId::from(db, format!("{}!_#{}", macro_name.long(db), offset))
342 }
343 }
344 }
345 pub fn owning_crate(&self, db: &'db dyn Database) -> CrateId<'db> {
346 match self {
347 ModuleId::CrateRoot(crate_id) => *crate_id,
348 ModuleId::Submodule(submodule) => {
349 let parent: ModuleId<'db> = submodule.parent_module(db);
350 parent.owning_crate(db)
351 }
352 ModuleId::MacroCall { id, .. } => id.parent_module(db).owning_crate(db),
353 }
354 }
355 pub fn module_data(&self, db: &'db dyn Database) -> Maybe<ModuleData<'db>> {
356 crate::db::module_data(db, *self)
357 }
358}
359impl<'db> DebugWithDb<'db> for ModuleId<'db> {
360 type Db = dyn Database;
361
362 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
363 write!(f, "ModuleId({})", self.full_path(db))
364 }
365}
366
367#[derive(Clone, Debug, Hash, PartialEq, Eq, salsa::Update, HeapSize)]
369pub struct PluginGeneratedFileLongId<'db> {
370 pub module_id: ModuleId<'db>,
372 pub stable_ptr: SyntaxStablePtrId<'db>,
374 pub name: String,
376}
377define_short_id!(PluginGeneratedFileId, PluginGeneratedFileLongId<'db>);
378
379#[derive(Clone, Debug, HeapSize)]
381pub struct MacroPluginLongId(pub Arc<dyn MacroPlugin>);
382
383impl MacroPlugin for MacroPluginLongId {
384 fn generate_code<'db>(
385 &self,
386 db: &'db dyn Database,
387 item_ast: ast::ModuleItem<'db>,
388 metadata: &crate::plugin::MacroPluginMetadata<'_>,
389 ) -> crate::plugin::PluginResult<'db> {
390 self.0.generate_code(db, item_ast, metadata)
391 }
392
393 fn declared_attributes<'db>(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
394 self.0.declared_attributes(db)
395 }
396
397 fn declared_derives<'db>(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
398 self.0.declared_derives(db)
399 }
400
401 fn executable_attributes<'db>(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
402 self.0.executable_attributes(db)
403 }
404
405 fn phantom_type_attributes<'db>(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
406 self.0.phantom_type_attributes(db)
407 }
408
409 fn plugin_type_id(&self) -> std::any::TypeId {
410 self.0.plugin_type_id()
413 }
414}
415
416impl PartialEq for MacroPluginLongId {
419 fn eq(&self, other: &Self) -> bool {
420 Arc::ptr_eq(&self.0, &other.0)
421 }
422}
423
424impl Eq for MacroPluginLongId {}
425
426impl Hash for MacroPluginLongId {
427 fn hash<H: Hasher>(&self, state: &mut H) {
428 Arc::as_ptr(&self.0).hash(state)
429 }
430}
431
432define_short_id!(MacroPluginId, MacroPluginLongId);
433
434#[derive(Clone, Debug, HeapSize)]
436pub struct InlineMacroExprPluginLongId(pub Arc<dyn InlineMacroExprPlugin>);
437
438impl InlineMacroExprPlugin for InlineMacroExprPluginLongId {
439 fn generate_code<'db>(
440 &self,
441 db: &'db dyn Database,
442 item_ast: &ast::ExprInlineMacro<'db>,
443 metadata: &crate::plugin::MacroPluginMetadata<'_>,
444 ) -> crate::plugin::InlinePluginResult<'db> {
445 self.0.generate_code(db, item_ast, metadata)
446 }
447
448 fn documentation(&self) -> Option<String> {
449 self.0.documentation()
450 }
451
452 fn plugin_type_id(&self) -> std::any::TypeId {
453 self.0.plugin_type_id()
456 }
457}
458
459impl PartialEq for InlineMacroExprPluginLongId {
462 fn eq(&self, other: &Self) -> bool {
463 Arc::ptr_eq(&self.0, &other.0)
464 }
465}
466
467impl Eq for InlineMacroExprPluginLongId {}
468
469impl Hash for InlineMacroExprPluginLongId {
470 fn hash<H: Hasher>(&self, state: &mut H) {
471 Arc::as_ptr(&self.0).hash(state)
472 }
473}
474
475define_short_id!(InlineMacroExprPluginId, InlineMacroExprPluginLongId);
476
477define_language_element_id_as_enum! {
478 #[toplevel]
479 pub enum ModuleItemId<'db> {
481 Constant(ConstantId<'db>),
482 Submodule(SubmoduleId<'db>),
483 Use(UseId<'db>),
484 FreeFunction(FreeFunctionId<'db>),
485 Struct(StructId<'db>),
486 Enum(EnumId<'db>),
487 TypeAlias(ModuleTypeAliasId<'db>),
488 ImplAlias(ImplAliasId<'db>),
489 Trait(TraitId<'db>),
490 Impl(ImplDefId<'db>),
491 ExternType(ExternTypeId<'db>),
492 ExternFunction(ExternFunctionId<'db>),
493 MacroDeclaration(MacroDeclarationId<'db>),
494 }
495}
496
497#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, salsa::Update)]
500pub enum ImportableId<'db> {
501 Constant(ConstantId<'db>),
502 Submodule(SubmoduleId<'db>),
503 Crate(CrateId<'db>),
504 FreeFunction(FreeFunctionId<'db>),
505 Struct(StructId<'db>),
506 Enum(EnumId<'db>),
507 Variant(VariantId<'db>),
508 TypeAlias(ModuleTypeAliasId<'db>),
509 ImplAlias(ImplAliasId<'db>),
510 Trait(TraitId<'db>),
511 Impl(ImplDefId<'db>),
512 ExternType(ExternTypeId<'db>),
513 ExternFunction(ExternFunctionId<'db>),
514 MacroDeclaration(MacroDeclarationId<'db>),
515}
516
517impl<'db> ImportableId<'db> {
518 pub fn parent_module(&self, db: &'db dyn Database) -> Option<ModuleId<'db>> {
520 Some(match self {
521 ImportableId::Constant(id) => id.parent_module(db),
522 ImportableId::Submodule(id) => id.parent_module(db),
523 ImportableId::Crate(_) => return None,
524 ImportableId::FreeFunction(id) => id.parent_module(db),
525 ImportableId::Struct(id) => id.parent_module(db),
526 ImportableId::Enum(id) => id.parent_module(db),
527 ImportableId::Variant(id) => id.parent_module(db),
528 ImportableId::TypeAlias(id) => id.parent_module(db),
529 ImportableId::ImplAlias(id) => id.parent_module(db),
530 ImportableId::Trait(id) => id.parent_module(db),
531 ImportableId::Impl(id) => id.parent_module(db),
532 ImportableId::ExternType(id) => id.parent_module(db),
533 ImportableId::ExternFunction(id) => id.parent_module(db),
534 ImportableId::MacroDeclaration(id) => id.parent_module(db),
535 })
536 }
537
538 pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
540 match self {
541 ImportableId::Constant(id) => id.name(db),
542 ImportableId::Submodule(id) => id.name(db),
543 ImportableId::FreeFunction(id) => id.name(db),
544 ImportableId::Struct(id) => id.name(db),
545 ImportableId::Enum(id) => id.name(db),
546 ImportableId::TypeAlias(id) => id.name(db),
547 ImportableId::ImplAlias(id) => id.name(db),
548 ImportableId::Trait(id) => id.name(db),
549 ImportableId::Impl(id) => id.name(db),
550 ImportableId::ExternType(id) => id.name(db),
551 ImportableId::ExternFunction(id) => id.name(db),
552 ImportableId::MacroDeclaration(id) => id.name(db),
553 ImportableId::Crate(crate_id) => crate_id.long(db).name(),
554 ImportableId::Variant(variant_id) => variant_id.name(db),
555 }
556 }
557}
558
559impl<'db> From<ConstantId<'db>> for ImportableId<'db> {
560 fn from(id: ConstantId<'db>) -> Self {
561 ImportableId::Constant(id)
562 }
563}
564
565impl<'db> From<SubmoduleId<'db>> for ImportableId<'db> {
566 fn from(id: SubmoduleId<'db>) -> Self {
567 ImportableId::Submodule(id)
568 }
569}
570
571impl<'db> From<CrateId<'db>> for ImportableId<'db> {
572 fn from(id: CrateId<'db>) -> Self {
573 ImportableId::Crate(id)
574 }
575}
576
577impl<'db> From<FreeFunctionId<'db>> for ImportableId<'db> {
578 fn from(id: FreeFunctionId<'db>) -> Self {
579 ImportableId::FreeFunction(id)
580 }
581}
582
583impl<'db> From<StructId<'db>> for ImportableId<'db> {
584 fn from(id: StructId<'db>) -> Self {
585 ImportableId::Struct(id)
586 }
587}
588
589impl<'db> From<EnumId<'db>> for ImportableId<'db> {
590 fn from(id: EnumId<'db>) -> Self {
591 ImportableId::Enum(id)
592 }
593}
594
595impl<'db> From<VariantId<'db>> for ImportableId<'db> {
596 fn from(id: VariantId<'db>) -> Self {
597 ImportableId::Variant(id)
598 }
599}
600
601impl<'db> From<ModuleTypeAliasId<'db>> for ImportableId<'db> {
602 fn from(id: ModuleTypeAliasId<'db>) -> Self {
603 ImportableId::TypeAlias(id)
604 }
605}
606
607impl<'db> From<ImplAliasId<'db>> for ImportableId<'db> {
608 fn from(id: ImplAliasId<'db>) -> Self {
609 ImportableId::ImplAlias(id)
610 }
611}
612
613impl<'db> From<TraitId<'db>> for ImportableId<'db> {
614 fn from(id: TraitId<'db>) -> Self {
615 ImportableId::Trait(id)
616 }
617}
618
619impl<'db> From<ImplDefId<'db>> for ImportableId<'db> {
620 fn from(id: ImplDefId<'db>) -> Self {
621 ImportableId::Impl(id)
622 }
623}
624
625impl<'db> From<ExternTypeId<'db>> for ImportableId<'db> {
626 fn from(id: ExternTypeId<'db>) -> Self {
627 ImportableId::ExternType(id)
628 }
629}
630
631impl<'db> From<ExternFunctionId<'db>> for ImportableId<'db> {
632 fn from(id: ExternFunctionId<'db>) -> Self {
633 ImportableId::ExternFunction(id)
634 }
635}
636
637impl<'db> From<MacroDeclarationId<'db>> for ImportableId<'db> {
638 fn from(id: MacroDeclarationId<'db>) -> Self {
639 ImportableId::MacroDeclaration(id)
640 }
641}
642
643impl<'db> From<&ConstantId<'db>> for ImportableId<'db> {
644 fn from(id: &ConstantId<'db>) -> Self {
645 ImportableId::Constant(*id)
646 }
647}
648
649impl<'db> From<&SubmoduleId<'db>> for ImportableId<'db> {
650 fn from(id: &SubmoduleId<'db>) -> Self {
651 ImportableId::Submodule(*id)
652 }
653}
654
655impl<'db> From<&CrateId<'db>> for ImportableId<'db> {
656 fn from(id: &CrateId<'db>) -> Self {
657 ImportableId::Crate(*id)
658 }
659}
660
661impl<'db> From<&FreeFunctionId<'db>> for ImportableId<'db> {
662 fn from(id: &FreeFunctionId<'db>) -> Self {
663 ImportableId::FreeFunction(*id)
664 }
665}
666
667impl<'db> From<&StructId<'db>> for ImportableId<'db> {
668 fn from(id: &StructId<'db>) -> Self {
669 ImportableId::Struct(*id)
670 }
671}
672
673impl<'db> From<&EnumId<'db>> for ImportableId<'db> {
674 fn from(id: &EnumId<'db>) -> Self {
675 ImportableId::Enum(*id)
676 }
677}
678
679impl<'db> From<&VariantId<'db>> for ImportableId<'db> {
680 fn from(id: &VariantId<'db>) -> Self {
681 ImportableId::Variant(*id)
682 }
683}
684
685impl<'db> From<&ModuleTypeAliasId<'db>> for ImportableId<'db> {
686 fn from(id: &ModuleTypeAliasId<'db>) -> Self {
687 ImportableId::TypeAlias(*id)
688 }
689}
690
691impl<'db> From<&ImplAliasId<'db>> for ImportableId<'db> {
692 fn from(id: &ImplAliasId<'db>) -> Self {
693 ImportableId::ImplAlias(*id)
694 }
695}
696
697impl<'db> From<&TraitId<'db>> for ImportableId<'db> {
698 fn from(id: &TraitId<'db>) -> Self {
699 ImportableId::Trait(*id)
700 }
701}
702
703impl<'db> From<&ImplDefId<'db>> for ImportableId<'db> {
704 fn from(id: &ImplDefId<'db>) -> Self {
705 ImportableId::Impl(*id)
706 }
707}
708
709impl<'db> From<&ExternTypeId<'db>> for ImportableId<'db> {
710 fn from(id: &ExternTypeId<'db>) -> Self {
711 ImportableId::ExternType(*id)
712 }
713}
714
715impl<'db> From<&ExternFunctionId<'db>> for ImportableId<'db> {
716 fn from(id: &ExternFunctionId<'db>) -> Self {
717 ImportableId::ExternFunction(*id)
718 }
719}
720
721impl<'db> From<&MacroDeclarationId<'db>> for ImportableId<'db> {
722 fn from(id: &MacroDeclarationId<'db>) -> Self {
723 ImportableId::MacroDeclaration(*id)
724 }
725}
726
727impl<'db> From<ModuleItemId<'db>> for Option<ImportableId<'db>> {
728 fn from(module_item_id: ModuleItemId<'db>) -> Self {
729 match module_item_id {
730 ModuleItemId::Constant(id) => Some(ImportableId::Constant(id)),
731 ModuleItemId::Submodule(id) => Some(ImportableId::Submodule(id)),
732 ModuleItemId::FreeFunction(id) => Some(ImportableId::FreeFunction(id)),
733 ModuleItemId::Struct(id) => Some(ImportableId::Struct(id)),
734 ModuleItemId::Enum(id) => Some(ImportableId::Enum(id)),
735 ModuleItemId::TypeAlias(id) => Some(ImportableId::TypeAlias(id)),
736 ModuleItemId::ImplAlias(id) => Some(ImportableId::ImplAlias(id)),
737 ModuleItemId::Trait(id) => Some(ImportableId::Trait(id)),
738 ModuleItemId::Impl(id) => Some(ImportableId::Impl(id)),
739 ModuleItemId::ExternType(id) => Some(ImportableId::ExternType(id)),
740 ModuleItemId::ExternFunction(id) => Some(ImportableId::ExternFunction(id)),
741 ModuleItemId::MacroDeclaration(id) => Some(ImportableId::MacroDeclaration(id)),
742 ModuleItemId::Use(_) => None,
743 }
744 }
745}
746
747define_top_level_language_element_id!(SubmoduleId, SubmoduleLongId, ast::ItemModule<'db>);
748impl<'db> UnstableSalsaId for SubmoduleId<'db> {
749 fn get_internal_id(&self) -> salsa::Id {
750 self.0
751 }
752}
753
754define_top_level_language_element_id!(ConstantId, ConstantLongId, ast::ItemConstant<'db>);
755define_language_element_id_basic!(GlobalUseId, GlobalUseLongId, ast::UsePathStar<'db>);
756define_top_level_language_element_id!(UseId, UseLongId, ast::UsePathLeaf<'db>);
757define_top_level_language_element_id!(
758 FreeFunctionId,
759 FreeFunctionLongId,
760 ast::FunctionWithBody<'db>
761);
762
763define_top_level_language_element_id!(
764 MacroDeclarationId,
765 MacroDeclarationLongId,
766 ast::ItemMacroDeclaration<'db>
767);
768
769define_language_element_id_basic!(MacroCallId, MacroCallLongId, ast::ItemInlineMacro<'db>);
770
771impl<'db> UnstableSalsaId for MacroCallId<'db> {
772 fn get_internal_id(&self) -> salsa::Id {
773 self.0
774 }
775}
776
777impl<'db> UnstableSalsaId for FreeFunctionId<'db> {
778 fn get_internal_id(&self) -> salsa::Id {
779 self.0
780 }
781}
782
783define_top_level_language_element_id!(ImplDefId, ImplDefLongId, ast::ItemImpl<'db>);
785impl<'db> UnstableSalsaId for ImplDefId<'db> {
786 fn get_internal_id(&self) -> salsa::Id {
787 self.0
788 }
789}
790
791define_named_language_element_id!(ImplTypeDefId, ImplTypeDefLongId, ast::ItemTypeAlias<'db>);
793impl<'db> ImplTypeDefId<'db> {
794 pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
795 let ImplTypeDefLongId(module_id, ptr) = self.long(db).clone();
796
797 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
799 ImplDefLongId(module_id, impl_ptr).intern(db)
800 }
801}
802impl<'db> TopLevelLanguageElementId<'db> for ImplTypeDefId<'db> {
803 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
804 let mut segments = self.impl_def_id(db).path_segments(db);
805 segments.push(self.name(db));
806 segments
807 }
808}
809
810define_named_language_element_id!(ImplConstantDefId, ImplConstantDefLongId, ast::ItemConstant<'db>);
812impl<'db> ImplConstantDefId<'db> {
813 pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
814 let ImplConstantDefLongId(module_id, ptr) = self.long(db).clone();
815
816 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
818 ImplDefLongId(module_id, impl_ptr).intern(db)
819 }
820}
821impl<'db> TopLevelLanguageElementId<'db> for ImplConstantDefId<'db> {
822 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
823 let mut segments = self.impl_def_id(db).path_segments(db);
824 segments.push(self.name(db));
825 segments
826 }
827}
828
829define_named_language_element_id!(ImplImplDefId, ImplImplDefLongId, ast::ItemImplAlias<'db>);
831impl<'db> ImplImplDefId<'db> {
832 pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
833 let ImplImplDefLongId(module_id, ptr) = self.long(db).clone();
834
835 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
837 ImplDefLongId(module_id, impl_ptr).intern(db)
838 }
839}
840impl<'db> TopLevelLanguageElementId<'db> for ImplImplDefId<'db> {
841 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
842 let mut segments = self.impl_def_id(db).path_segments(db);
843 segments.push(self.name(db));
844 segments
845 }
846}
847
848define_named_language_element_id!(ImplFunctionId, ImplFunctionLongId, ast::FunctionWithBody<'db>);
850impl<'db> ImplFunctionId<'db> {
851 pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
852 let ImplFunctionLongId(module_id, ptr) = self.long(db).clone();
853
854 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
856 ImplDefLongId(module_id, impl_ptr).intern(db)
857 }
858}
859impl<'db> UnstableSalsaId for ImplFunctionId<'db> {
860 fn get_internal_id(&self) -> salsa::Id {
861 self.0
862 }
863}
864impl<'db> TopLevelLanguageElementId<'db> for ImplFunctionId<'db> {
865 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
866 let mut segments = self.impl_def_id(db).path_segments(db);
867 segments.push(self.name(db));
868 segments
869 }
870}
871
872define_language_element_id_as_enum! {
873 #[toplevel]
874 pub enum FunctionWithBodyId<'db> {
876 Free(FreeFunctionId<'db>),
877 Impl(ImplFunctionId<'db>),
878 Trait(TraitFunctionId<'db>),
879 }
880}
881
882define_top_level_language_element_id!(
883 ExternFunctionId,
884 ExternFunctionLongId,
885 ast::ItemExternFunction<'db>
886);
887define_top_level_language_element_id!(StructId, StructLongId, ast::ItemStruct<'db>);
888define_top_level_language_element_id!(EnumId, EnumLongId, ast::ItemEnum<'db>);
889define_top_level_language_element_id!(
890 ModuleTypeAliasId,
891 ModuleTypeAliasLongId,
892 ast::ItemTypeAlias<'db>
893);
894define_top_level_language_element_id!(ImplAliasId, ImplAliasLongId, ast::ItemImplAlias<'db>);
895impl<'db> UnstableSalsaId for ImplAliasId<'db> {
896 fn get_internal_id(&self) -> salsa::Id {
897 self.0
898 }
899}
900define_top_level_language_element_id!(ExternTypeId, ExternTypeLongId, ast::ItemExternType<'db>);
901
902define_top_level_language_element_id!(TraitId, TraitLongId, ast::ItemTrait<'db>);
904
905define_named_language_element_id!(TraitTypeId, TraitTypeLongId, ast::TraitItemType<'db>);
907impl<'db> TraitTypeId<'db> {
908 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
909 let TraitTypeLongId(module_id, ptr) = self.long(db).clone();
910 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
912 TraitLongId(module_id, trait_ptr).intern(db)
913 }
914}
915impl<'db> TopLevelLanguageElementId<'db> for TraitTypeId<'db> {
916 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
917 let mut segments = self.trait_id(db).path_segments(db);
918 segments.push(self.name(db));
919 segments
920 }
921}
922impl<'db> UnstableSalsaId for TraitTypeId<'db> {
923 fn get_internal_id(&self) -> salsa::Id {
924 self.0
925 }
926}
927
928define_named_language_element_id!(
930 TraitConstantId,
931 TraitConstantLongId,
932 ast::TraitItemConstant<'db>
933);
934impl<'db> TraitConstantId<'db> {
935 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
936 let TraitConstantLongId(module_id, ptr) = self.long(db).clone();
937 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
939 TraitLongId(module_id, trait_ptr).intern(db)
940 }
941}
942impl<'db> TopLevelLanguageElementId<'db> for TraitConstantId<'db> {
943 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
944 let mut segments = self.trait_id(db).path_segments(db);
945 segments.push(self.name(db));
946 segments
947 }
948}
949
950define_named_language_element_id!(TraitImplId, TraitImplLongId, ast::TraitItemImpl<'db>);
952impl<'db> TraitImplId<'db> {
953 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
954 let TraitImplLongId(module_id, ptr) = self.long(db).clone();
955 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
957 TraitLongId(module_id, trait_ptr).intern(db)
958 }
959}
960impl<'db> TopLevelLanguageElementId<'db> for TraitImplId<'db> {
961 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
962 let mut segments = self.trait_id(db).path_segments(db);
963 segments.push(self.name(db));
964 segments
965 }
966}
967impl<'db> UnstableSalsaId for TraitImplId<'db> {
968 fn get_internal_id(&self) -> salsa::Id {
969 self.0
970 }
971}
972
973define_named_language_element_id!(
975 TraitFunctionId,
976 TraitFunctionLongId,
977 ast::TraitItemFunction<'db>
978);
979impl<'db> TraitFunctionId<'db> {
980 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
981 let TraitFunctionLongId(module_id, ptr) = self.long(db).clone();
982 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
984 TraitLongId(module_id, trait_ptr).intern(db)
985 }
986}
987impl<'db> TopLevelLanguageElementId<'db> for TraitFunctionId<'db> {
988 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
989 let mut segments = self.trait_id(db).path_segments(db);
990 segments.push(self.name(db));
991 segments
992 }
993}
994
995define_named_language_element_id!(MemberId, MemberLongId, ast::Member<'db>);
997impl<'db> MemberId<'db> {
998 pub fn struct_id(&self, db: &'db dyn Database) -> StructId<'db> {
999 let MemberLongId(module_id, ptr) = self.long(db).clone();
1000 let struct_ptr = ast::ItemStructPtr(ptr.untyped().nth_parent(db, 2));
1001 StructLongId(module_id, struct_ptr).intern(db)
1002 }
1003}
1004
1005impl<'db> TopLevelLanguageElementId<'db> for MemberId<'db> {
1006 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
1007 let mut segments = self.struct_id(db).path_segments(db);
1008 segments.push(self.name(db));
1009 segments
1010 }
1011}
1012
1013define_named_language_element_id!(VariantId, VariantLongId, ast::Variant<'db>);
1015impl<'db> VariantId<'db> {
1016 pub fn enum_id(&self, db: &'db dyn Database) -> EnumId<'db> {
1017 let VariantLongId(module_id, ptr) = self.long(db).clone();
1018 let struct_ptr = ast::ItemEnumPtr(ptr.untyped().nth_parent(db, 2));
1019 EnumLongId(module_id, struct_ptr).intern(db)
1020 }
1021}
1022
1023impl<'db> TopLevelLanguageElementId<'db> for VariantId<'db> {
1024 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
1025 let mut segments = self.enum_id(db).path_segments(db);
1026 segments.push(self.name(db));
1027 segments
1028 }
1029}
1030
1031define_language_element_id_as_enum! {
1032 pub enum VarId<'db> {
1034 Param(ParamId<'db>),
1035 Local(LocalVarId<'db>),
1036 Item(StatementItemId<'db>),
1037 }
1039}
1040
1041define_top_level_language_element_id!(ParamId, ParamLongId, ast::Param<'db>);
1043define_language_element_id_basic!(GenericParamId, GenericParamLongId, ast::GenericParam<'db>);
1044impl<'db> GenericParamLongId<'db> {
1045 pub fn name(&self, db: &'db dyn Database) -> Option<SmolStrId<'db>> {
1046 let node = self.1.0.0;
1047 assert!(!node.is_root());
1048 let key_fields = node.key_fields(db);
1049 let kind = node.kind(db);
1050 require(!matches!(
1051 kind,
1052 SyntaxKind::GenericParamImplAnonymous | SyntaxKind::GenericParamNegativeImpl
1053 ))?;
1054
1055 let name_green = TerminalIdentifierGreen(key_fields[0]);
1056 Some(name_green.identifier(db))
1057 }
1058
1059 pub fn debug_name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1060 self.name(db).unwrap_or(SmolStrId::from(db, "_"))
1061 }
1062 pub fn kind(&self, db: &dyn Database) -> GenericKind {
1063 let node = self.1.0.0;
1064 assert!(!node.is_root());
1065 let kind = node.kind(db);
1066 match kind {
1067 SyntaxKind::GenericParamType => GenericKind::Type,
1068 SyntaxKind::GenericParamConst => GenericKind::Const,
1069 SyntaxKind::GenericParamImplNamed | SyntaxKind::GenericParamImplAnonymous => {
1070 GenericKind::Impl
1071 }
1072 SyntaxKind::GenericParamNegativeImpl => GenericKind::NegImpl,
1073 _ => unreachable!(),
1074 }
1075 }
1076 pub fn generic_item<'s, 'd: 's>(&'s self, db: &'d dyn Database) -> GenericItemId<'s> {
1078 let item_ptr = self.1.0.nth_parent(db, 3);
1079 GenericItemId::from_ptr(db, self.0, item_ptr)
1080 }
1081
1082 pub fn has_type_constraints_syntax(&self, db: &dyn Database) -> bool {
1084 let param = ast::GenericParamPtr(self.1.0).lookup(db);
1085 match param {
1086 ast::GenericParam::Type(_) => false,
1087 ast::GenericParam::Const(_) => false,
1088 ast::GenericParam::ImplNamed(imp) => {
1089 matches!(
1090 imp.type_constrains(db),
1091 ast::OptionAssociatedItemConstraints::AssociatedItemConstraints(_)
1092 )
1093 }
1094 ast::GenericParam::ImplAnonymous(imp) => {
1095 matches!(
1096 imp.type_constrains(db),
1097 ast::OptionAssociatedItemConstraints::AssociatedItemConstraints(_)
1098 )
1099 }
1100 ast::GenericParam::NegativeImpl(_) => false,
1101 }
1102 }
1103}
1104impl<'db> GenericParamId<'db> {
1105 pub fn name(&self, db: &'db dyn Database) -> Option<SmolStrId<'db>> {
1106 self.long(db).name(db)
1107 }
1108 pub fn debug_name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1109 self.long(db).debug_name(db)
1110 }
1111 pub fn format(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1112 let long_ids = self.long(db);
1113 let node = long_ids.1.0.0;
1114 assert!(!node.is_root());
1115 let key_fields = node.key_fields(db);
1116 let kind = node.kind(db);
1117
1118 if matches!(
1119 kind,
1120 SyntaxKind::GenericParamImplAnonymous | SyntaxKind::GenericParamNegativeImpl
1121 ) {
1122 return self.stable_location(db).syntax_node(db).get_text_without_trivia(db);
1124 }
1125
1126 let name_green = TerminalIdentifierGreen(key_fields[0]);
1127 name_green.identifier(db)
1128 }
1129
1130 pub fn kind(&self, db: &dyn Database) -> GenericKind {
1131 self.long(db).kind(db)
1132 }
1133 pub fn generic_item(&self, db: &'db dyn Database) -> GenericItemId<'db> {
1134 self.long(db).generic_item(db)
1135 }
1136}
1137
1138impl<'db> UnstableSalsaId for GenericParamId<'db> {
1139 fn get_internal_id(&self) -> salsa::Id {
1140 self.0
1141 }
1142}
1143
1144impl<'db> DebugWithDb<'db> for GenericParamLongId<'db> {
1145 type Db = dyn Database;
1146
1147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
1148 write!(
1149 f,
1150 "GenericParam{}({}::{})",
1151 self.kind(db),
1152 self.generic_item(db).full_path(db),
1153 self.debug_name(db).long(db)
1154 )
1155 }
1156}
1157
1158define_language_element_id_as_enum! {
1159 #[toplevel]
1160 pub enum GenericModuleItemId<'db> {
1162 FreeFunc(FreeFunctionId<'db>),
1163 ExternFunc(ExternFunctionId<'db>),
1164 TraitFunc(TraitFunctionId<'db>),
1165 ImplFunc(ImplFunctionId<'db>),
1166 Trait(TraitId<'db>),
1167 Impl(ImplDefId<'db>),
1168 Struct(StructId<'db>),
1169 Enum(EnumId<'db>),
1170 ExternType(ExternTypeId<'db>),
1171 TypeAlias(ModuleTypeAliasId<'db>),
1172 ImplAlias(ImplAliasId<'db>),
1173 }
1174}
1175define_language_element_id_as_enum! {
1176 #[toplevel]
1177 pub enum GenericTraitItemId<'db> {
1179 Type(TraitTypeId<'db>),
1180 }
1181}
1182define_language_element_id_as_enum! {
1183 #[toplevel]
1184 pub enum GenericImplItemId<'db> {
1186 Type(ImplTypeDefId<'db>),
1187 }
1188}
1189
1190define_language_element_id_as_enum! {
1191 #[toplevel]
1192 pub enum GenericItemId<'db> {
1194 ModuleItem(GenericModuleItemId<'db>),
1195 TraitItem(GenericTraitItemId<'db>),
1196 ImplItem(GenericImplItemId<'db>),
1197 }
1198}
1199impl<'db> GenericItemId<'db> {
1200 pub fn from_ptr(
1201 db: &'db dyn Database,
1202 module_file: ModuleId<'db>,
1203 stable_ptr: SyntaxStablePtrId<'db>,
1204 ) -> Self {
1205 let node = stable_ptr.0;
1206 let parent0 = node.parent(db).expect("GenericItem should have a parent");
1207 let kind = node.kind(db);
1208 match kind {
1209 SyntaxKind::FunctionDeclaration => {
1210 let parent1 = parent0.parent(db).expect("FunctionDeclaration parent should exist");
1211 let kind = parent0.kind(db);
1212 match kind {
1213 SyntaxKind::FunctionWithBody => {
1214 let parent0_ptr = SyntaxStablePtrId(parent0);
1217 match parent1.parent(db).map(|p| p.kind(db)) {
1218 Some(SyntaxKind::SyntaxFile) | Some(SyntaxKind::ModuleBody) => {
1220 GenericItemId::ModuleItem(GenericModuleItemId::FreeFunc(
1221 FreeFunctionLongId(
1222 module_file,
1223 ast::FunctionWithBodyPtr(parent0_ptr),
1224 )
1225 .intern(db),
1226 ))
1227 }
1228 Some(SyntaxKind::ImplBody) => {
1229 GenericItemId::ModuleItem(GenericModuleItemId::ImplFunc(
1230 ImplFunctionLongId(
1231 module_file,
1232 ast::FunctionWithBodyPtr(parent0_ptr),
1233 )
1234 .intern(db),
1235 ))
1236 }
1237 _ => panic!(
1238 "Got bad syntax kind @ parent of {}. {:?}",
1239 parent1.kind(db),
1240 kind
1241 ),
1242 }
1243 }
1244 SyntaxKind::ItemExternFunction => {
1245 GenericItemId::ModuleItem(GenericModuleItemId::ExternFunc(
1246 ExternFunctionLongId(
1247 module_file,
1248 ast::ItemExternFunctionPtr(SyntaxStablePtrId(parent0)),
1249 )
1250 .intern(db),
1251 ))
1252 }
1253 SyntaxKind::TraitItemFunction => {
1254 GenericItemId::ModuleItem(GenericModuleItemId::TraitFunc(
1255 TraitFunctionLongId(
1256 module_file,
1257 ast::TraitItemFunctionPtr(SyntaxStablePtrId(parent0)),
1258 )
1259 .intern(db),
1260 ))
1261 }
1262 _ => panic!(),
1263 }
1264 }
1265 SyntaxKind::ItemImpl => GenericItemId::ModuleItem(GenericModuleItemId::Impl(
1266 ImplDefLongId(module_file, ast::ItemImplPtr(stable_ptr)).intern(db),
1267 )),
1268 SyntaxKind::ItemTrait => GenericItemId::ModuleItem(GenericModuleItemId::Trait(
1269 TraitLongId(module_file, ast::ItemTraitPtr(stable_ptr)).intern(db),
1270 )),
1271 SyntaxKind::ItemStruct => GenericItemId::ModuleItem(GenericModuleItemId::Struct(
1272 StructLongId(module_file, ast::ItemStructPtr(stable_ptr)).intern(db),
1273 )),
1274 SyntaxKind::ItemEnum => GenericItemId::ModuleItem(GenericModuleItemId::Enum(
1275 EnumLongId(module_file, ast::ItemEnumPtr(stable_ptr)).intern(db),
1276 )),
1277 SyntaxKind::ItemExternType => {
1278 GenericItemId::ModuleItem(GenericModuleItemId::ExternType(
1279 ExternTypeLongId(module_file, ast::ItemExternTypePtr(stable_ptr)).intern(db),
1280 ))
1281 }
1282 SyntaxKind::ItemTypeAlias => {
1283 match parent0.kind(db) {
1286 SyntaxKind::ModuleItemList => {
1287 GenericItemId::ModuleItem(GenericModuleItemId::TypeAlias(
1288 ModuleTypeAliasLongId(module_file, ast::ItemTypeAliasPtr(stable_ptr))
1289 .intern(db),
1290 ))
1291 }
1292 SyntaxKind::ImplItemList => GenericItemId::ImplItem(GenericImplItemId::Type(
1293 ImplTypeDefLongId(module_file, ast::ItemTypeAliasPtr(stable_ptr))
1294 .intern(db),
1295 )),
1296 _ => panic!(),
1297 }
1298 }
1299 SyntaxKind::ItemImplAlias => GenericItemId::ModuleItem(GenericModuleItemId::ImplAlias(
1300 ImplAliasLongId(module_file, ast::ItemImplAliasPtr(stable_ptr)).intern(db),
1301 )),
1302 SyntaxKind::TraitItemType => GenericItemId::TraitItem(GenericTraitItemId::Type(
1303 TraitTypeLongId(module_file, ast::TraitItemTypePtr(stable_ptr)).intern(db),
1304 )),
1305 _ => panic!(),
1306 }
1307 }
1308}
1309
1310#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, salsa::Update)]
1311pub enum GenericKind {
1312 Type,
1313 Const,
1314 Impl,
1315 NegImpl,
1316}
1317impl std::fmt::Display for GenericKind {
1318 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1319 match self {
1320 GenericKind::Type => write!(f, "Type"),
1321 GenericKind::Const => write!(f, "Const"),
1322 GenericKind::Impl => write!(f, "Impl"),
1323 GenericKind::NegImpl => write!(f, "-Impl"),
1324 }
1325 }
1326}
1327
1328define_language_element_id_basic!(LocalVarId, LocalVarLongId, ast::TerminalIdentifier<'db>);
1331impl<'db> DebugWithDb<'db> for LocalVarLongId<'db> {
1332 type Db = dyn Database;
1333
1334 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
1335 let LocalVarLongId(module_id, ptr) = self;
1336 let text = ptr.lookup(db).text(db).long(db);
1337 write!(f, "LocalVarId({}::{})", module_id.full_path(db), text)
1338 }
1339}
1340
1341define_top_level_language_element_id!(
1342 StatementConstId,
1343 StatementConstLongId,
1344 ast::ItemConstant<'db>
1345);
1346
1347define_top_level_language_element_id!(StatementUseId, StatementUseLongId, ast::UsePathLeaf<'db>);
1348
1349define_language_element_id_as_enum! {
1350 #[toplevel]
1351 pub enum FunctionTitleId<'db> {
1353 Free(FreeFunctionId<'db>),
1354 Extern(ExternFunctionId<'db>),
1355 Trait(TraitFunctionId<'db>),
1356 Impl(ImplFunctionId<'db>),
1357 }
1358}
1359impl<'db> FunctionTitleId<'db> {
1360 pub fn format(&self, db: &dyn Database) -> String {
1361 let function_name = match *self {
1362 FunctionTitleId::Free(_) | FunctionTitleId::Extern(_) => self.name(db).to_string(db),
1363 FunctionTitleId::Trait(id) => id.full_path(db),
1364 FunctionTitleId::Impl(id) => id.full_path(db),
1365 };
1366 format!("{}::{}", self.parent_module(db).full_path(db), function_name)
1367 }
1368}
1369
1370define_language_element_id_as_enum! {
1371 #[toplevel]
1372 pub enum GenericTypeId<'db> {
1374 Struct(StructId<'db>),
1375 Enum(EnumId<'db>),
1376 Extern(ExternTypeId<'db>),
1377 }
1378}
1379impl<'db> GenericTypeId<'db> {
1380 pub fn format(&self, db: &dyn Database) -> String {
1381 format!("{}::{}", self.parent_module(db).full_path(db), self.name(db).long(db))
1382 }
1383}
1384
1385impl<'db> OptionFrom<ModuleItemId<'db>> for GenericTypeId<'db> {
1387 fn option_from(item: ModuleItemId<'db>) -> Option<Self> {
1388 match item {
1389 ModuleItemId::Struct(id) => Some(GenericTypeId::Struct(id)),
1390 ModuleItemId::Enum(id) => Some(GenericTypeId::Enum(id)),
1391 ModuleItemId::ExternType(id) => Some(GenericTypeId::Extern(id)),
1392 ModuleItemId::Constant(_)
1393 | ModuleItemId::Submodule(_)
1394 | ModuleItemId::TypeAlias(_)
1395 | ModuleItemId::ImplAlias(_)
1396 | ModuleItemId::Use(_)
1397 | ModuleItemId::FreeFunction(_)
1398 | ModuleItemId::Trait(_)
1399 | ModuleItemId::Impl(_)
1400 | ModuleItemId::ExternFunction(_)
1401 | ModuleItemId::MacroDeclaration(_) => None,
1402 }
1403 }
1404}
1405
1406impl<'db> From<GenericItemId<'db>> for LookupItemId<'db> {
1408 fn from(item: GenericItemId<'db>) -> Self {
1409 match item {
1410 GenericItemId::ModuleItem(module_item) => match module_item {
1411 GenericModuleItemId::FreeFunc(id) => {
1412 LookupItemId::ModuleItem(ModuleItemId::FreeFunction(id))
1413 }
1414 GenericModuleItemId::ExternFunc(id) => {
1415 LookupItemId::ModuleItem(ModuleItemId::ExternFunction(id))
1416 }
1417 GenericModuleItemId::TraitFunc(id) => {
1418 LookupItemId::TraitItem(TraitItemId::Function(id))
1419 }
1420 GenericModuleItemId::ImplFunc(id) => {
1421 LookupItemId::ImplItem(ImplItemId::Function(id))
1422 }
1423 GenericModuleItemId::Trait(id) => LookupItemId::ModuleItem(ModuleItemId::Trait(id)),
1424 GenericModuleItemId::Impl(id) => LookupItemId::ModuleItem(ModuleItemId::Impl(id)),
1425 GenericModuleItemId::Struct(id) => {
1426 LookupItemId::ModuleItem(ModuleItemId::Struct(id))
1427 }
1428 GenericModuleItemId::Enum(id) => LookupItemId::ModuleItem(ModuleItemId::Enum(id)),
1429 GenericModuleItemId::ExternType(id) => {
1430 LookupItemId::ModuleItem(ModuleItemId::ExternType(id))
1431 }
1432 GenericModuleItemId::TypeAlias(id) => {
1433 LookupItemId::ModuleItem(ModuleItemId::TypeAlias(id))
1434 }
1435 GenericModuleItemId::ImplAlias(id) => {
1436 LookupItemId::ModuleItem(ModuleItemId::ImplAlias(id))
1437 }
1438 },
1439 GenericItemId::TraitItem(trait_item) => match trait_item {
1440 GenericTraitItemId::Type(id) => LookupItemId::TraitItem(TraitItemId::Type(id)),
1441 },
1442 GenericItemId::ImplItem(impl_item) => match impl_item {
1443 GenericImplItemId::Type(id) => LookupItemId::ImplItem(ImplItemId::Type(id)),
1444 },
1445 }
1446 }
1447}
1448
1449define_language_element_id_as_enum! {
1450 #[toplevel]
1451 pub enum StatementItemId<'db> {
1452 Constant(StatementConstId<'db>),
1453 Use(StatementUseId<'db>),
1454 }
1455}
1456
1457impl<'db> StatementItemId<'db> {
1458 pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1459 match self {
1460 StatementItemId::Constant(id) => id.name(db),
1461 StatementItemId::Use(id) => id.name(db),
1462 }
1463 }
1464 pub fn name_stable_ptr(&self, db: &'db dyn Database) -> SyntaxStablePtrId<'db> {
1465 match self {
1466 StatementItemId::Constant(id) => {
1467 let id: &StatementConstId<'db> = id;
1468 let item_id = id.long(db).1.lookup(db);
1469 item_id.name(db).stable_ptr(db).untyped()
1470 }
1471 StatementItemId::Use(id) => {
1472 let item_id = id.long(db).1.lookup(db);
1473 item_id.name_stable_ptr(db)
1474 }
1475 }
1476 }
1477}
1478
1479define_language_element_id_as_enum! {
1480 #[toplevel]
1481 pub enum TraitItemId<'db> {
1483 Function(TraitFunctionId<'db>),
1484 Type(TraitTypeId<'db>),
1485 Constant(TraitConstantId<'db>),
1486 Impl(TraitImplId<'db>),
1487 }
1488}
1489impl<'db> TraitItemId<'db> {
1490 pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1491 match self {
1492 TraitItemId::Function(id) => id.name(db),
1493 TraitItemId::Type(id) => id.name(db),
1494 TraitItemId::Constant(id) => id.name(db),
1495 TraitItemId::Impl(id) => id.name(db),
1496 }
1497 }
1498 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
1499 match self {
1500 TraitItemId::Function(id) => id.trait_id(db),
1501 TraitItemId::Type(id) => id.trait_id(db),
1502 TraitItemId::Constant(id) => id.trait_id(db),
1503 TraitItemId::Impl(id) => id.trait_id(db),
1504 }
1505 }
1506}
1507
1508define_language_element_id_as_enum! {
1509 #[toplevel]
1510 pub enum ImplItemId<'db> {
1512 Function(ImplFunctionId<'db>),
1513 Type(ImplTypeDefId<'db>),
1514 Constant(ImplConstantDefId<'db>),
1515 Impl(ImplImplDefId<'db>),
1516 }
1517}
1518impl<'db> ImplItemId<'db> {
1519 pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1520 match self {
1521 ImplItemId::Function(id) => id.name(db),
1522 ImplItemId::Type(id) => id.name(db),
1523 ImplItemId::Constant(id) => id.name(db),
1524 ImplItemId::Impl(id) => id.name(db),
1525 }
1526 }
1527 pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
1528 match self {
1529 ImplItemId::Function(id) => id.impl_def_id(db),
1530 ImplItemId::Type(id) => id.impl_def_id(db),
1531 ImplItemId::Constant(id) => id.impl_def_id(db),
1532 ImplItemId::Impl(id) => id.impl_def_id(db),
1533 }
1534 }
1535}
1536
1537define_language_element_id_as_enum! {
1538 #[toplevel]
1539 pub enum LookupItemId<'db> {
1543 ModuleItem(ModuleItemId<'db>),
1544 TraitItem(TraitItemId<'db>),
1545 ImplItem(ImplItemId<'db>),
1546 }
1547}