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 id.stable_ptr(db).lookup(db).as_syntax_node().get_text_without_trivia(db)
337 }
338 }
339 }
340 pub fn owning_crate(&self, db: &'db dyn Database) -> CrateId<'db> {
341 match self {
342 ModuleId::CrateRoot(crate_id) => *crate_id,
343 ModuleId::Submodule(submodule) => {
344 let parent: ModuleId<'db> = submodule.parent_module(db);
345 parent.owning_crate(db)
346 }
347 ModuleId::MacroCall { id, .. } => id.parent_module(db).owning_crate(db),
348 }
349 }
350 pub fn module_data(&self, db: &'db dyn Database) -> Maybe<ModuleData<'db>> {
351 crate::db::module_data(db, *self)
352 }
353}
354impl<'db> DebugWithDb<'db> for ModuleId<'db> {
355 type Db = dyn Database;
356
357 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
358 write!(f, "ModuleId({})", self.full_path(db))
359 }
360}
361
362#[derive(Clone, Debug, Hash, PartialEq, Eq, salsa::Update, HeapSize)]
364pub struct PluginGeneratedFileLongId<'db> {
365 pub module_id: ModuleId<'db>,
367 pub stable_ptr: SyntaxStablePtrId<'db>,
369 pub name: String,
371}
372define_short_id!(PluginGeneratedFileId, PluginGeneratedFileLongId<'db>);
373
374#[derive(Clone, Debug, HeapSize)]
376pub struct MacroPluginLongId(pub Arc<dyn MacroPlugin>);
377
378impl MacroPlugin for MacroPluginLongId {
379 fn generate_code<'db>(
380 &self,
381 db: &'db dyn Database,
382 item_ast: ast::ModuleItem<'db>,
383 metadata: &crate::plugin::MacroPluginMetadata<'_>,
384 ) -> crate::plugin::PluginResult<'db> {
385 self.0.generate_code(db, item_ast, metadata)
386 }
387
388 fn declared_attributes<'db>(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
389 self.0.declared_attributes(db)
390 }
391
392 fn declared_derives<'db>(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
393 self.0.declared_derives(db)
394 }
395
396 fn executable_attributes<'db>(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
397 self.0.executable_attributes(db)
398 }
399
400 fn phantom_type_attributes<'db>(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
401 self.0.phantom_type_attributes(db)
402 }
403
404 fn plugin_type_id(&self) -> std::any::TypeId {
405 self.0.plugin_type_id()
408 }
409}
410
411impl PartialEq for MacroPluginLongId {
414 fn eq(&self, other: &Self) -> bool {
415 Arc::ptr_eq(&self.0, &other.0)
416 }
417}
418
419impl Eq for MacroPluginLongId {}
420
421impl Hash for MacroPluginLongId {
422 fn hash<H: Hasher>(&self, state: &mut H) {
423 Arc::as_ptr(&self.0).hash(state)
424 }
425}
426
427define_short_id!(MacroPluginId, MacroPluginLongId);
428
429#[derive(Clone, Debug, HeapSize)]
431pub struct InlineMacroExprPluginLongId(pub Arc<dyn InlineMacroExprPlugin>);
432
433impl InlineMacroExprPlugin for InlineMacroExprPluginLongId {
434 fn generate_code<'db>(
435 &self,
436 db: &'db dyn Database,
437 item_ast: &ast::ExprInlineMacro<'db>,
438 metadata: &crate::plugin::MacroPluginMetadata<'_>,
439 ) -> crate::plugin::InlinePluginResult<'db> {
440 self.0.generate_code(db, item_ast, metadata)
441 }
442
443 fn documentation(&self) -> Option<String> {
444 self.0.documentation()
445 }
446
447 fn plugin_type_id(&self) -> std::any::TypeId {
448 self.0.plugin_type_id()
451 }
452}
453
454impl PartialEq for InlineMacroExprPluginLongId {
457 fn eq(&self, other: &Self) -> bool {
458 Arc::ptr_eq(&self.0, &other.0)
459 }
460}
461
462impl Eq for InlineMacroExprPluginLongId {}
463
464impl Hash for InlineMacroExprPluginLongId {
465 fn hash<H: Hasher>(&self, state: &mut H) {
466 Arc::as_ptr(&self.0).hash(state)
467 }
468}
469
470define_short_id!(InlineMacroExprPluginId, InlineMacroExprPluginLongId);
471
472define_language_element_id_as_enum! {
473 #[toplevel]
474 pub enum ModuleItemId<'db> {
476 Constant(ConstantId<'db>),
477 Submodule(SubmoduleId<'db>),
478 Use(UseId<'db>),
479 FreeFunction(FreeFunctionId<'db>),
480 Struct(StructId<'db>),
481 Enum(EnumId<'db>),
482 TypeAlias(ModuleTypeAliasId<'db>),
483 ImplAlias(ImplAliasId<'db>),
484 Trait(TraitId<'db>),
485 Impl(ImplDefId<'db>),
486 ExternType(ExternTypeId<'db>),
487 ExternFunction(ExternFunctionId<'db>),
488 MacroDeclaration(MacroDeclarationId<'db>),
489 }
490}
491
492#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, salsa::Update)]
495pub enum ImportableId<'db> {
496 Constant(ConstantId<'db>),
497 Submodule(SubmoduleId<'db>),
498 Crate(CrateId<'db>),
499 FreeFunction(FreeFunctionId<'db>),
500 Struct(StructId<'db>),
501 Enum(EnumId<'db>),
502 Variant(VariantId<'db>),
503 TypeAlias(ModuleTypeAliasId<'db>),
504 ImplAlias(ImplAliasId<'db>),
505 Trait(TraitId<'db>),
506 Impl(ImplDefId<'db>),
507 ExternType(ExternTypeId<'db>),
508 ExternFunction(ExternFunctionId<'db>),
509 MacroDeclaration(MacroDeclarationId<'db>),
510}
511
512impl<'db> ImportableId<'db> {
513 pub fn parent_module(&self, db: &'db dyn Database) -> Option<ModuleId<'db>> {
515 Some(match self {
516 ImportableId::Constant(id) => id.parent_module(db),
517 ImportableId::Submodule(id) => id.parent_module(db),
518 ImportableId::Crate(_) => return None,
519 ImportableId::FreeFunction(id) => id.parent_module(db),
520 ImportableId::Struct(id) => id.parent_module(db),
521 ImportableId::Enum(id) => id.parent_module(db),
522 ImportableId::Variant(id) => id.parent_module(db),
523 ImportableId::TypeAlias(id) => id.parent_module(db),
524 ImportableId::ImplAlias(id) => id.parent_module(db),
525 ImportableId::Trait(id) => id.parent_module(db),
526 ImportableId::Impl(id) => id.parent_module(db),
527 ImportableId::ExternType(id) => id.parent_module(db),
528 ImportableId::ExternFunction(id) => id.parent_module(db),
529 ImportableId::MacroDeclaration(id) => id.parent_module(db),
530 })
531 }
532
533 pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
535 match self {
536 ImportableId::Constant(id) => id.name(db),
537 ImportableId::Submodule(id) => id.name(db),
538 ImportableId::FreeFunction(id) => id.name(db),
539 ImportableId::Struct(id) => id.name(db),
540 ImportableId::Enum(id) => id.name(db),
541 ImportableId::TypeAlias(id) => id.name(db),
542 ImportableId::ImplAlias(id) => id.name(db),
543 ImportableId::Trait(id) => id.name(db),
544 ImportableId::Impl(id) => id.name(db),
545 ImportableId::ExternType(id) => id.name(db),
546 ImportableId::ExternFunction(id) => id.name(db),
547 ImportableId::MacroDeclaration(id) => id.name(db),
548 ImportableId::Crate(crate_id) => crate_id.long(db).name(),
549 ImportableId::Variant(variant_id) => variant_id.name(db),
550 }
551 }
552}
553
554impl<'db> From<ConstantId<'db>> for ImportableId<'db> {
555 fn from(id: ConstantId<'db>) -> Self {
556 ImportableId::Constant(id)
557 }
558}
559
560impl<'db> From<SubmoduleId<'db>> for ImportableId<'db> {
561 fn from(id: SubmoduleId<'db>) -> Self {
562 ImportableId::Submodule(id)
563 }
564}
565
566impl<'db> From<CrateId<'db>> for ImportableId<'db> {
567 fn from(id: CrateId<'db>) -> Self {
568 ImportableId::Crate(id)
569 }
570}
571
572impl<'db> From<FreeFunctionId<'db>> for ImportableId<'db> {
573 fn from(id: FreeFunctionId<'db>) -> Self {
574 ImportableId::FreeFunction(id)
575 }
576}
577
578impl<'db> From<StructId<'db>> for ImportableId<'db> {
579 fn from(id: StructId<'db>) -> Self {
580 ImportableId::Struct(id)
581 }
582}
583
584impl<'db> From<EnumId<'db>> for ImportableId<'db> {
585 fn from(id: EnumId<'db>) -> Self {
586 ImportableId::Enum(id)
587 }
588}
589
590impl<'db> From<VariantId<'db>> for ImportableId<'db> {
591 fn from(id: VariantId<'db>) -> Self {
592 ImportableId::Variant(id)
593 }
594}
595
596impl<'db> From<ModuleTypeAliasId<'db>> for ImportableId<'db> {
597 fn from(id: ModuleTypeAliasId<'db>) -> Self {
598 ImportableId::TypeAlias(id)
599 }
600}
601
602impl<'db> From<ImplAliasId<'db>> for ImportableId<'db> {
603 fn from(id: ImplAliasId<'db>) -> Self {
604 ImportableId::ImplAlias(id)
605 }
606}
607
608impl<'db> From<TraitId<'db>> for ImportableId<'db> {
609 fn from(id: TraitId<'db>) -> Self {
610 ImportableId::Trait(id)
611 }
612}
613
614impl<'db> From<ImplDefId<'db>> for ImportableId<'db> {
615 fn from(id: ImplDefId<'db>) -> Self {
616 ImportableId::Impl(id)
617 }
618}
619
620impl<'db> From<ExternTypeId<'db>> for ImportableId<'db> {
621 fn from(id: ExternTypeId<'db>) -> Self {
622 ImportableId::ExternType(id)
623 }
624}
625
626impl<'db> From<ExternFunctionId<'db>> for ImportableId<'db> {
627 fn from(id: ExternFunctionId<'db>) -> Self {
628 ImportableId::ExternFunction(id)
629 }
630}
631
632impl<'db> From<MacroDeclarationId<'db>> for ImportableId<'db> {
633 fn from(id: MacroDeclarationId<'db>) -> Self {
634 ImportableId::MacroDeclaration(id)
635 }
636}
637
638impl<'db> From<&ConstantId<'db>> for ImportableId<'db> {
639 fn from(id: &ConstantId<'db>) -> Self {
640 ImportableId::Constant(*id)
641 }
642}
643
644impl<'db> From<&SubmoduleId<'db>> for ImportableId<'db> {
645 fn from(id: &SubmoduleId<'db>) -> Self {
646 ImportableId::Submodule(*id)
647 }
648}
649
650impl<'db> From<&CrateId<'db>> for ImportableId<'db> {
651 fn from(id: &CrateId<'db>) -> Self {
652 ImportableId::Crate(*id)
653 }
654}
655
656impl<'db> From<&FreeFunctionId<'db>> for ImportableId<'db> {
657 fn from(id: &FreeFunctionId<'db>) -> Self {
658 ImportableId::FreeFunction(*id)
659 }
660}
661
662impl<'db> From<&StructId<'db>> for ImportableId<'db> {
663 fn from(id: &StructId<'db>) -> Self {
664 ImportableId::Struct(*id)
665 }
666}
667
668impl<'db> From<&EnumId<'db>> for ImportableId<'db> {
669 fn from(id: &EnumId<'db>) -> Self {
670 ImportableId::Enum(*id)
671 }
672}
673
674impl<'db> From<&VariantId<'db>> for ImportableId<'db> {
675 fn from(id: &VariantId<'db>) -> Self {
676 ImportableId::Variant(*id)
677 }
678}
679
680impl<'db> From<&ModuleTypeAliasId<'db>> for ImportableId<'db> {
681 fn from(id: &ModuleTypeAliasId<'db>) -> Self {
682 ImportableId::TypeAlias(*id)
683 }
684}
685
686impl<'db> From<&ImplAliasId<'db>> for ImportableId<'db> {
687 fn from(id: &ImplAliasId<'db>) -> Self {
688 ImportableId::ImplAlias(*id)
689 }
690}
691
692impl<'db> From<&TraitId<'db>> for ImportableId<'db> {
693 fn from(id: &TraitId<'db>) -> Self {
694 ImportableId::Trait(*id)
695 }
696}
697
698impl<'db> From<&ImplDefId<'db>> for ImportableId<'db> {
699 fn from(id: &ImplDefId<'db>) -> Self {
700 ImportableId::Impl(*id)
701 }
702}
703
704impl<'db> From<&ExternTypeId<'db>> for ImportableId<'db> {
705 fn from(id: &ExternTypeId<'db>) -> Self {
706 ImportableId::ExternType(*id)
707 }
708}
709
710impl<'db> From<&ExternFunctionId<'db>> for ImportableId<'db> {
711 fn from(id: &ExternFunctionId<'db>) -> Self {
712 ImportableId::ExternFunction(*id)
713 }
714}
715
716impl<'db> From<&MacroDeclarationId<'db>> for ImportableId<'db> {
717 fn from(id: &MacroDeclarationId<'db>) -> Self {
718 ImportableId::MacroDeclaration(*id)
719 }
720}
721
722impl<'db> From<ModuleItemId<'db>> for Option<ImportableId<'db>> {
723 fn from(module_item_id: ModuleItemId<'db>) -> Self {
724 match module_item_id {
725 ModuleItemId::Constant(id) => Some(ImportableId::Constant(id)),
726 ModuleItemId::Submodule(id) => Some(ImportableId::Submodule(id)),
727 ModuleItemId::FreeFunction(id) => Some(ImportableId::FreeFunction(id)),
728 ModuleItemId::Struct(id) => Some(ImportableId::Struct(id)),
729 ModuleItemId::Enum(id) => Some(ImportableId::Enum(id)),
730 ModuleItemId::TypeAlias(id) => Some(ImportableId::TypeAlias(id)),
731 ModuleItemId::ImplAlias(id) => Some(ImportableId::ImplAlias(id)),
732 ModuleItemId::Trait(id) => Some(ImportableId::Trait(id)),
733 ModuleItemId::Impl(id) => Some(ImportableId::Impl(id)),
734 ModuleItemId::ExternType(id) => Some(ImportableId::ExternType(id)),
735 ModuleItemId::ExternFunction(id) => Some(ImportableId::ExternFunction(id)),
736 ModuleItemId::MacroDeclaration(id) => Some(ImportableId::MacroDeclaration(id)),
737 ModuleItemId::Use(_) => None,
738 }
739 }
740}
741
742define_top_level_language_element_id!(SubmoduleId, SubmoduleLongId, ast::ItemModule<'db>);
743impl<'db> UnstableSalsaId for SubmoduleId<'db> {
744 fn get_internal_id(&self) -> salsa::Id {
745 self.0
746 }
747}
748
749define_top_level_language_element_id!(ConstantId, ConstantLongId, ast::ItemConstant<'db>);
750define_language_element_id_basic!(GlobalUseId, GlobalUseLongId, ast::UsePathStar<'db>);
751define_top_level_language_element_id!(UseId, UseLongId, ast::UsePathLeaf<'db>);
752define_top_level_language_element_id!(
753 FreeFunctionId,
754 FreeFunctionLongId,
755 ast::FunctionWithBody<'db>
756);
757
758define_top_level_language_element_id!(
759 MacroDeclarationId,
760 MacroDeclarationLongId,
761 ast::ItemMacroDeclaration<'db>
762);
763
764define_language_element_id_basic!(MacroCallId, MacroCallLongId, ast::ItemInlineMacro<'db>);
765
766impl<'db> UnstableSalsaId for MacroCallId<'db> {
767 fn get_internal_id(&self) -> salsa::Id {
768 self.0
769 }
770}
771
772impl<'db> UnstableSalsaId for FreeFunctionId<'db> {
773 fn get_internal_id(&self) -> salsa::Id {
774 self.0
775 }
776}
777
778define_top_level_language_element_id!(ImplDefId, ImplDefLongId, ast::ItemImpl<'db>);
780impl<'db> UnstableSalsaId for ImplDefId<'db> {
781 fn get_internal_id(&self) -> salsa::Id {
782 self.0
783 }
784}
785
786define_named_language_element_id!(ImplTypeDefId, ImplTypeDefLongId, ast::ItemTypeAlias<'db>);
788impl<'db> ImplTypeDefId<'db> {
789 pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
790 let ImplTypeDefLongId(module_id, ptr) = self.long(db).clone();
791
792 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
794 ImplDefLongId(module_id, impl_ptr).intern(db)
795 }
796}
797impl<'db> TopLevelLanguageElementId<'db> for ImplTypeDefId<'db> {
798 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
799 let mut segments = self.impl_def_id(db).path_segments(db);
800 segments.push(self.name(db));
801 segments
802 }
803}
804
805define_named_language_element_id!(ImplConstantDefId, ImplConstantDefLongId, ast::ItemConstant<'db>);
807impl<'db> ImplConstantDefId<'db> {
808 pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
809 let ImplConstantDefLongId(module_id, ptr) = self.long(db).clone();
810
811 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
813 ImplDefLongId(module_id, impl_ptr).intern(db)
814 }
815}
816impl<'db> TopLevelLanguageElementId<'db> for ImplConstantDefId<'db> {
817 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
818 let mut segments = self.impl_def_id(db).path_segments(db);
819 segments.push(self.name(db));
820 segments
821 }
822}
823
824define_named_language_element_id!(ImplImplDefId, ImplImplDefLongId, ast::ItemImplAlias<'db>);
826impl<'db> ImplImplDefId<'db> {
827 pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
828 let ImplImplDefLongId(module_id, ptr) = self.long(db).clone();
829
830 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
832 ImplDefLongId(module_id, impl_ptr).intern(db)
833 }
834}
835impl<'db> TopLevelLanguageElementId<'db> for ImplImplDefId<'db> {
836 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
837 let mut segments = self.impl_def_id(db).path_segments(db);
838 segments.push(self.name(db));
839 segments
840 }
841}
842
843define_named_language_element_id!(ImplFunctionId, ImplFunctionLongId, ast::FunctionWithBody<'db>);
845impl<'db> ImplFunctionId<'db> {
846 pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
847 let ImplFunctionLongId(module_id, ptr) = self.long(db).clone();
848
849 let impl_ptr = ast::ItemImplPtr(ptr.untyped().nth_parent(db, 3));
851 ImplDefLongId(module_id, impl_ptr).intern(db)
852 }
853}
854impl<'db> UnstableSalsaId for ImplFunctionId<'db> {
855 fn get_internal_id(&self) -> salsa::Id {
856 self.0
857 }
858}
859impl<'db> TopLevelLanguageElementId<'db> for ImplFunctionId<'db> {
860 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
861 let mut segments = self.impl_def_id(db).path_segments(db);
862 segments.push(self.name(db));
863 segments
864 }
865}
866
867define_language_element_id_as_enum! {
868 #[toplevel]
869 pub enum FunctionWithBodyId<'db> {
871 Free(FreeFunctionId<'db>),
872 Impl(ImplFunctionId<'db>),
873 Trait(TraitFunctionId<'db>),
874 }
875}
876
877define_top_level_language_element_id!(
878 ExternFunctionId,
879 ExternFunctionLongId,
880 ast::ItemExternFunction<'db>
881);
882define_top_level_language_element_id!(StructId, StructLongId, ast::ItemStruct<'db>);
883define_top_level_language_element_id!(EnumId, EnumLongId, ast::ItemEnum<'db>);
884define_top_level_language_element_id!(
885 ModuleTypeAliasId,
886 ModuleTypeAliasLongId,
887 ast::ItemTypeAlias<'db>
888);
889define_top_level_language_element_id!(ImplAliasId, ImplAliasLongId, ast::ItemImplAlias<'db>);
890impl<'db> UnstableSalsaId for ImplAliasId<'db> {
891 fn get_internal_id(&self) -> salsa::Id {
892 self.0
893 }
894}
895define_top_level_language_element_id!(ExternTypeId, ExternTypeLongId, ast::ItemExternType<'db>);
896
897define_top_level_language_element_id!(TraitId, TraitLongId, ast::ItemTrait<'db>);
899
900define_named_language_element_id!(TraitTypeId, TraitTypeLongId, ast::TraitItemType<'db>);
902impl<'db> TraitTypeId<'db> {
903 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
904 let TraitTypeLongId(module_id, ptr) = self.long(db).clone();
905 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
907 TraitLongId(module_id, trait_ptr).intern(db)
908 }
909}
910impl<'db> TopLevelLanguageElementId<'db> for TraitTypeId<'db> {
911 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
912 let mut segments = self.trait_id(db).path_segments(db);
913 segments.push(self.name(db));
914 segments
915 }
916}
917impl<'db> UnstableSalsaId for TraitTypeId<'db> {
918 fn get_internal_id(&self) -> salsa::Id {
919 self.0
920 }
921}
922
923define_named_language_element_id!(
925 TraitConstantId,
926 TraitConstantLongId,
927 ast::TraitItemConstant<'db>
928);
929impl<'db> TraitConstantId<'db> {
930 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
931 let TraitConstantLongId(module_id, ptr) = self.long(db).clone();
932 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
934 TraitLongId(module_id, trait_ptr).intern(db)
935 }
936}
937impl<'db> TopLevelLanguageElementId<'db> for TraitConstantId<'db> {
938 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
939 let mut segments = self.trait_id(db).path_segments(db);
940 segments.push(self.name(db));
941 segments
942 }
943}
944
945define_named_language_element_id!(TraitImplId, TraitImplLongId, ast::TraitItemImpl<'db>);
947impl<'db> TraitImplId<'db> {
948 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
949 let TraitImplLongId(module_id, ptr) = self.long(db).clone();
950 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
952 TraitLongId(module_id, trait_ptr).intern(db)
953 }
954}
955impl<'db> TopLevelLanguageElementId<'db> for TraitImplId<'db> {
956 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
957 let mut segments = self.trait_id(db).path_segments(db);
958 segments.push(self.name(db));
959 segments
960 }
961}
962impl<'db> UnstableSalsaId for TraitImplId<'db> {
963 fn get_internal_id(&self) -> salsa::Id {
964 self.0
965 }
966}
967
968define_named_language_element_id!(
970 TraitFunctionId,
971 TraitFunctionLongId,
972 ast::TraitItemFunction<'db>
973);
974impl<'db> TraitFunctionId<'db> {
975 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
976 let TraitFunctionLongId(module_id, ptr) = self.long(db).clone();
977 let trait_ptr = ast::ItemTraitPtr(ptr.untyped().nth_parent(db, 3));
979 TraitLongId(module_id, trait_ptr).intern(db)
980 }
981}
982impl<'db> TopLevelLanguageElementId<'db> for TraitFunctionId<'db> {
983 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
984 let mut segments = self.trait_id(db).path_segments(db);
985 segments.push(self.name(db));
986 segments
987 }
988}
989
990define_named_language_element_id!(MemberId, MemberLongId, ast::Member<'db>);
992impl<'db> MemberId<'db> {
993 pub fn struct_id(&self, db: &'db dyn Database) -> StructId<'db> {
994 let MemberLongId(module_id, ptr) = self.long(db).clone();
995 let struct_ptr = ast::ItemStructPtr(ptr.untyped().nth_parent(db, 2));
996 StructLongId(module_id, struct_ptr).intern(db)
997 }
998}
999
1000impl<'db> TopLevelLanguageElementId<'db> for MemberId<'db> {
1001 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
1002 let mut segments = self.struct_id(db).path_segments(db);
1003 segments.push(self.name(db));
1004 segments
1005 }
1006}
1007
1008define_named_language_element_id!(VariantId, VariantLongId, ast::Variant<'db>);
1010impl<'db> VariantId<'db> {
1011 pub fn enum_id(&self, db: &'db dyn Database) -> EnumId<'db> {
1012 let VariantLongId(module_id, ptr) = self.long(db).clone();
1013 let struct_ptr = ast::ItemEnumPtr(ptr.untyped().nth_parent(db, 2));
1014 EnumLongId(module_id, struct_ptr).intern(db)
1015 }
1016}
1017
1018impl<'db> TopLevelLanguageElementId<'db> for VariantId<'db> {
1019 fn path_segments(&self, db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
1020 let mut segments = self.enum_id(db).path_segments(db);
1021 segments.push(self.name(db));
1022 segments
1023 }
1024}
1025
1026define_language_element_id_as_enum! {
1027 pub enum VarId<'db> {
1029 Param(ParamId<'db>),
1030 Local(LocalVarId<'db>),
1031 Item(StatementItemId<'db>),
1032 }
1034}
1035
1036define_top_level_language_element_id!(ParamId, ParamLongId, ast::Param<'db>);
1038define_language_element_id_basic!(GenericParamId, GenericParamLongId, ast::GenericParam<'db>);
1039impl<'db> GenericParamLongId<'db> {
1040 pub fn name(&self, db: &'db dyn Database) -> Option<SmolStrId<'db>> {
1041 let node = self.1.0.0;
1042 assert!(!node.is_root());
1043 let key_fields = node.key_fields(db);
1044 let kind = node.kind(db);
1045 require(!matches!(
1046 kind,
1047 SyntaxKind::GenericParamImplAnonymous | SyntaxKind::GenericParamNegativeImpl
1048 ))?;
1049
1050 let name_green = TerminalIdentifierGreen(key_fields[0]);
1051 Some(name_green.identifier(db))
1052 }
1053
1054 pub fn debug_name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1055 self.name(db).unwrap_or(SmolStrId::from(db, "_"))
1056 }
1057 pub fn kind(&self, db: &dyn Database) -> GenericKind {
1058 let node = self.1.0.0;
1059 assert!(!node.is_root());
1060 let kind = node.kind(db);
1061 match kind {
1062 SyntaxKind::GenericParamType => GenericKind::Type,
1063 SyntaxKind::GenericParamConst => GenericKind::Const,
1064 SyntaxKind::GenericParamImplNamed | SyntaxKind::GenericParamImplAnonymous => {
1065 GenericKind::Impl
1066 }
1067 SyntaxKind::GenericParamNegativeImpl => GenericKind::NegImpl,
1068 _ => unreachable!(),
1069 }
1070 }
1071 pub fn generic_item<'s, 'd: 's>(&'s self, db: &'d dyn Database) -> GenericItemId<'s> {
1073 let item_ptr = self.1.0.nth_parent(db, 3);
1074 GenericItemId::from_ptr(db, self.0, item_ptr)
1075 }
1076
1077 pub fn has_type_constraints_syntax(&self, db: &dyn Database) -> bool {
1079 let param = ast::GenericParamPtr(self.1.0).lookup(db);
1080 match param {
1081 ast::GenericParam::Type(_) => false,
1082 ast::GenericParam::Const(_) => false,
1083 ast::GenericParam::ImplNamed(imp) => {
1084 matches!(
1085 imp.type_constrains(db),
1086 ast::OptionAssociatedItemConstraints::AssociatedItemConstraints(_)
1087 )
1088 }
1089 ast::GenericParam::ImplAnonymous(imp) => {
1090 matches!(
1091 imp.type_constrains(db),
1092 ast::OptionAssociatedItemConstraints::AssociatedItemConstraints(_)
1093 )
1094 }
1095 ast::GenericParam::NegativeImpl(_) => false,
1096 }
1097 }
1098}
1099impl<'db> GenericParamId<'db> {
1100 pub fn name(&self, db: &'db dyn Database) -> Option<SmolStrId<'db>> {
1101 self.long(db).name(db)
1102 }
1103 pub fn debug_name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1104 self.long(db).debug_name(db)
1105 }
1106 pub fn format(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1107 let long_ids = self.long(db);
1108 let node = long_ids.1.0.0;
1109 assert!(!node.is_root());
1110 let key_fields = node.key_fields(db);
1111 let kind = node.kind(db);
1112
1113 if matches!(
1114 kind,
1115 SyntaxKind::GenericParamImplAnonymous | SyntaxKind::GenericParamNegativeImpl
1116 ) {
1117 return self.stable_location(db).syntax_node(db).get_text_without_trivia(db);
1119 }
1120
1121 let name_green = TerminalIdentifierGreen(key_fields[0]);
1122 name_green.identifier(db)
1123 }
1124
1125 pub fn kind(&self, db: &dyn Database) -> GenericKind {
1126 self.long(db).kind(db)
1127 }
1128 pub fn generic_item(&self, db: &'db dyn Database) -> GenericItemId<'db> {
1129 self.long(db).generic_item(db)
1130 }
1131}
1132
1133impl<'db> UnstableSalsaId for GenericParamId<'db> {
1134 fn get_internal_id(&self) -> salsa::Id {
1135 self.0
1136 }
1137}
1138
1139impl<'db> DebugWithDb<'db> for GenericParamLongId<'db> {
1140 type Db = dyn Database;
1141
1142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
1143 write!(
1144 f,
1145 "GenericParam{}({}::{})",
1146 self.kind(db),
1147 self.generic_item(db).full_path(db),
1148 self.debug_name(db).long(db)
1149 )
1150 }
1151}
1152
1153define_language_element_id_as_enum! {
1154 #[toplevel]
1155 pub enum GenericModuleItemId<'db> {
1157 FreeFunc(FreeFunctionId<'db>),
1158 ExternFunc(ExternFunctionId<'db>),
1159 TraitFunc(TraitFunctionId<'db>),
1160 ImplFunc(ImplFunctionId<'db>),
1161 Trait(TraitId<'db>),
1162 Impl(ImplDefId<'db>),
1163 Struct(StructId<'db>),
1164 Enum(EnumId<'db>),
1165 ExternType(ExternTypeId<'db>),
1166 TypeAlias(ModuleTypeAliasId<'db>),
1167 ImplAlias(ImplAliasId<'db>),
1168 }
1169}
1170define_language_element_id_as_enum! {
1171 #[toplevel]
1172 pub enum GenericTraitItemId<'db> {
1174 Type(TraitTypeId<'db>),
1175 }
1176}
1177define_language_element_id_as_enum! {
1178 #[toplevel]
1179 pub enum GenericImplItemId<'db> {
1181 Type(ImplTypeDefId<'db>),
1182 }
1183}
1184
1185define_language_element_id_as_enum! {
1186 #[toplevel]
1187 pub enum GenericItemId<'db> {
1189 ModuleItem(GenericModuleItemId<'db>),
1190 TraitItem(GenericTraitItemId<'db>),
1191 ImplItem(GenericImplItemId<'db>),
1192 }
1193}
1194impl<'db> GenericItemId<'db> {
1195 pub fn from_ptr(
1196 db: &'db dyn Database,
1197 module_file: ModuleId<'db>,
1198 stable_ptr: SyntaxStablePtrId<'db>,
1199 ) -> Self {
1200 let node = stable_ptr.0;
1201 let parent0 = node.parent(db).expect("GenericItem should have a parent");
1202 let kind = node.kind(db);
1203 match kind {
1204 SyntaxKind::FunctionDeclaration => {
1205 let parent1 = parent0.parent(db).expect("FunctionDeclaration parent should exist");
1206 let kind = parent0.kind(db);
1207 match kind {
1208 SyntaxKind::FunctionWithBody => {
1209 let parent0_ptr = SyntaxStablePtrId(parent0);
1212 match parent1.parent(db).map(|p| p.kind(db)) {
1213 Some(SyntaxKind::SyntaxFile) | Some(SyntaxKind::ModuleBody) => {
1215 GenericItemId::ModuleItem(GenericModuleItemId::FreeFunc(
1216 FreeFunctionLongId(
1217 module_file,
1218 ast::FunctionWithBodyPtr(parent0_ptr),
1219 )
1220 .intern(db),
1221 ))
1222 }
1223 Some(SyntaxKind::ImplBody) => {
1224 GenericItemId::ModuleItem(GenericModuleItemId::ImplFunc(
1225 ImplFunctionLongId(
1226 module_file,
1227 ast::FunctionWithBodyPtr(parent0_ptr),
1228 )
1229 .intern(db),
1230 ))
1231 }
1232 _ => panic!(
1233 "Got bad syntax kind @ parent of {}. {:?}",
1234 parent1.kind(db),
1235 kind
1236 ),
1237 }
1238 }
1239 SyntaxKind::ItemExternFunction => {
1240 GenericItemId::ModuleItem(GenericModuleItemId::ExternFunc(
1241 ExternFunctionLongId(
1242 module_file,
1243 ast::ItemExternFunctionPtr(SyntaxStablePtrId(parent0)),
1244 )
1245 .intern(db),
1246 ))
1247 }
1248 SyntaxKind::TraitItemFunction => {
1249 GenericItemId::ModuleItem(GenericModuleItemId::TraitFunc(
1250 TraitFunctionLongId(
1251 module_file,
1252 ast::TraitItemFunctionPtr(SyntaxStablePtrId(parent0)),
1253 )
1254 .intern(db),
1255 ))
1256 }
1257 _ => panic!(),
1258 }
1259 }
1260 SyntaxKind::ItemImpl => GenericItemId::ModuleItem(GenericModuleItemId::Impl(
1261 ImplDefLongId(module_file, ast::ItemImplPtr(stable_ptr)).intern(db),
1262 )),
1263 SyntaxKind::ItemTrait => GenericItemId::ModuleItem(GenericModuleItemId::Trait(
1264 TraitLongId(module_file, ast::ItemTraitPtr(stable_ptr)).intern(db),
1265 )),
1266 SyntaxKind::ItemStruct => GenericItemId::ModuleItem(GenericModuleItemId::Struct(
1267 StructLongId(module_file, ast::ItemStructPtr(stable_ptr)).intern(db),
1268 )),
1269 SyntaxKind::ItemEnum => GenericItemId::ModuleItem(GenericModuleItemId::Enum(
1270 EnumLongId(module_file, ast::ItemEnumPtr(stable_ptr)).intern(db),
1271 )),
1272 SyntaxKind::ItemExternType => {
1273 GenericItemId::ModuleItem(GenericModuleItemId::ExternType(
1274 ExternTypeLongId(module_file, ast::ItemExternTypePtr(stable_ptr)).intern(db),
1275 ))
1276 }
1277 SyntaxKind::ItemTypeAlias => {
1278 match parent0.kind(db) {
1281 SyntaxKind::ModuleItemList => {
1282 GenericItemId::ModuleItem(GenericModuleItemId::TypeAlias(
1283 ModuleTypeAliasLongId(module_file, ast::ItemTypeAliasPtr(stable_ptr))
1284 .intern(db),
1285 ))
1286 }
1287 SyntaxKind::ImplItemList => GenericItemId::ImplItem(GenericImplItemId::Type(
1288 ImplTypeDefLongId(module_file, ast::ItemTypeAliasPtr(stable_ptr))
1289 .intern(db),
1290 )),
1291 _ => panic!(),
1292 }
1293 }
1294 SyntaxKind::ItemImplAlias => GenericItemId::ModuleItem(GenericModuleItemId::ImplAlias(
1295 ImplAliasLongId(module_file, ast::ItemImplAliasPtr(stable_ptr)).intern(db),
1296 )),
1297 SyntaxKind::TraitItemType => GenericItemId::TraitItem(GenericTraitItemId::Type(
1298 TraitTypeLongId(module_file, ast::TraitItemTypePtr(stable_ptr)).intern(db),
1299 )),
1300 _ => panic!(),
1301 }
1302 }
1303}
1304
1305#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, salsa::Update)]
1306pub enum GenericKind {
1307 Type,
1308 Const,
1309 Impl,
1310 NegImpl,
1311}
1312impl std::fmt::Display for GenericKind {
1313 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1314 match self {
1315 GenericKind::Type => write!(f, "Type"),
1316 GenericKind::Const => write!(f, "Const"),
1317 GenericKind::Impl => write!(f, "Impl"),
1318 GenericKind::NegImpl => write!(f, "-Impl"),
1319 }
1320 }
1321}
1322
1323define_language_element_id_basic!(LocalVarId, LocalVarLongId, ast::TerminalIdentifier<'db>);
1326impl<'db> DebugWithDb<'db> for LocalVarLongId<'db> {
1327 type Db = dyn Database;
1328
1329 fn fmt(&self, f: &mut std::fmt::Formatter<'_>, db: &'db dyn Database) -> std::fmt::Result {
1330 let LocalVarLongId(module_id, ptr) = self;
1331 let text = ptr.lookup(db).text(db).long(db);
1332 write!(f, "LocalVarId({}::{})", module_id.full_path(db), text)
1333 }
1334}
1335
1336define_top_level_language_element_id!(
1337 StatementConstId,
1338 StatementConstLongId,
1339 ast::ItemConstant<'db>
1340);
1341
1342define_top_level_language_element_id!(StatementUseId, StatementUseLongId, ast::UsePathLeaf<'db>);
1343
1344define_language_element_id_as_enum! {
1345 #[toplevel]
1346 pub enum FunctionTitleId<'db> {
1348 Free(FreeFunctionId<'db>),
1349 Extern(ExternFunctionId<'db>),
1350 Trait(TraitFunctionId<'db>),
1351 Impl(ImplFunctionId<'db>),
1352 }
1353}
1354impl<'db> FunctionTitleId<'db> {
1355 pub fn format(&self, db: &dyn Database) -> String {
1356 let function_name = match *self {
1357 FunctionTitleId::Free(_) | FunctionTitleId::Extern(_) => self.name(db).to_string(db),
1358 FunctionTitleId::Trait(id) => id.full_path(db),
1359 FunctionTitleId::Impl(id) => id.full_path(db),
1360 };
1361 format!("{}::{}", self.parent_module(db).full_path(db), function_name)
1362 }
1363}
1364
1365define_language_element_id_as_enum! {
1366 #[toplevel]
1367 pub enum GenericTypeId<'db> {
1369 Struct(StructId<'db>),
1370 Enum(EnumId<'db>),
1371 Extern(ExternTypeId<'db>),
1372 }
1373}
1374impl<'db> GenericTypeId<'db> {
1375 pub fn format(&self, db: &dyn Database) -> String {
1376 format!("{}::{}", self.parent_module(db).full_path(db), self.name(db).long(db))
1377 }
1378}
1379
1380impl<'db> OptionFrom<ModuleItemId<'db>> for GenericTypeId<'db> {
1382 fn option_from(item: ModuleItemId<'db>) -> Option<Self> {
1383 match item {
1384 ModuleItemId::Struct(id) => Some(GenericTypeId::Struct(id)),
1385 ModuleItemId::Enum(id) => Some(GenericTypeId::Enum(id)),
1386 ModuleItemId::ExternType(id) => Some(GenericTypeId::Extern(id)),
1387 ModuleItemId::Constant(_)
1388 | ModuleItemId::Submodule(_)
1389 | ModuleItemId::TypeAlias(_)
1390 | ModuleItemId::ImplAlias(_)
1391 | ModuleItemId::Use(_)
1392 | ModuleItemId::FreeFunction(_)
1393 | ModuleItemId::Trait(_)
1394 | ModuleItemId::Impl(_)
1395 | ModuleItemId::ExternFunction(_)
1396 | ModuleItemId::MacroDeclaration(_) => None,
1397 }
1398 }
1399}
1400
1401impl<'db> From<GenericItemId<'db>> for LookupItemId<'db> {
1403 fn from(item: GenericItemId<'db>) -> Self {
1404 match item {
1405 GenericItemId::ModuleItem(module_item) => match module_item {
1406 GenericModuleItemId::FreeFunc(id) => {
1407 LookupItemId::ModuleItem(ModuleItemId::FreeFunction(id))
1408 }
1409 GenericModuleItemId::ExternFunc(id) => {
1410 LookupItemId::ModuleItem(ModuleItemId::ExternFunction(id))
1411 }
1412 GenericModuleItemId::TraitFunc(id) => {
1413 LookupItemId::TraitItem(TraitItemId::Function(id))
1414 }
1415 GenericModuleItemId::ImplFunc(id) => {
1416 LookupItemId::ImplItem(ImplItemId::Function(id))
1417 }
1418 GenericModuleItemId::Trait(id) => LookupItemId::ModuleItem(ModuleItemId::Trait(id)),
1419 GenericModuleItemId::Impl(id) => LookupItemId::ModuleItem(ModuleItemId::Impl(id)),
1420 GenericModuleItemId::Struct(id) => {
1421 LookupItemId::ModuleItem(ModuleItemId::Struct(id))
1422 }
1423 GenericModuleItemId::Enum(id) => LookupItemId::ModuleItem(ModuleItemId::Enum(id)),
1424 GenericModuleItemId::ExternType(id) => {
1425 LookupItemId::ModuleItem(ModuleItemId::ExternType(id))
1426 }
1427 GenericModuleItemId::TypeAlias(id) => {
1428 LookupItemId::ModuleItem(ModuleItemId::TypeAlias(id))
1429 }
1430 GenericModuleItemId::ImplAlias(id) => {
1431 LookupItemId::ModuleItem(ModuleItemId::ImplAlias(id))
1432 }
1433 },
1434 GenericItemId::TraitItem(trait_item) => match trait_item {
1435 GenericTraitItemId::Type(id) => LookupItemId::TraitItem(TraitItemId::Type(id)),
1436 },
1437 GenericItemId::ImplItem(impl_item) => match impl_item {
1438 GenericImplItemId::Type(id) => LookupItemId::ImplItem(ImplItemId::Type(id)),
1439 },
1440 }
1441 }
1442}
1443
1444define_language_element_id_as_enum! {
1445 #[toplevel]
1446 pub enum StatementItemId<'db> {
1447 Constant(StatementConstId<'db>),
1448 Use(StatementUseId<'db>),
1449 }
1450}
1451
1452impl<'db> StatementItemId<'db> {
1453 pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1454 match self {
1455 StatementItemId::Constant(id) => id.name(db),
1456 StatementItemId::Use(id) => id.name(db),
1457 }
1458 }
1459 pub fn name_stable_ptr(&self, db: &'db dyn Database) -> SyntaxStablePtrId<'db> {
1460 match self {
1461 StatementItemId::Constant(id) => {
1462 let id: &StatementConstId<'db> = id;
1463 let item_id = id.long(db).1.lookup(db);
1464 item_id.name(db).stable_ptr(db).untyped()
1465 }
1466 StatementItemId::Use(id) => {
1467 let item_id = id.long(db).1.lookup(db);
1468 item_id.name_stable_ptr(db)
1469 }
1470 }
1471 }
1472}
1473
1474define_language_element_id_as_enum! {
1475 #[toplevel]
1476 pub enum TraitItemId<'db> {
1478 Function(TraitFunctionId<'db>),
1479 Type(TraitTypeId<'db>),
1480 Constant(TraitConstantId<'db>),
1481 Impl(TraitImplId<'db>),
1482 }
1483}
1484impl<'db> TraitItemId<'db> {
1485 pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1486 match self {
1487 TraitItemId::Function(id) => id.name(db),
1488 TraitItemId::Type(id) => id.name(db),
1489 TraitItemId::Constant(id) => id.name(db),
1490 TraitItemId::Impl(id) => id.name(db),
1491 }
1492 }
1493 pub fn trait_id(&self, db: &'db dyn Database) -> TraitId<'db> {
1494 match self {
1495 TraitItemId::Function(id) => id.trait_id(db),
1496 TraitItemId::Type(id) => id.trait_id(db),
1497 TraitItemId::Constant(id) => id.trait_id(db),
1498 TraitItemId::Impl(id) => id.trait_id(db),
1499 }
1500 }
1501}
1502
1503define_language_element_id_as_enum! {
1504 #[toplevel]
1505 pub enum ImplItemId<'db> {
1507 Function(ImplFunctionId<'db>),
1508 Type(ImplTypeDefId<'db>),
1509 Constant(ImplConstantDefId<'db>),
1510 Impl(ImplImplDefId<'db>),
1511 }
1512}
1513impl<'db> ImplItemId<'db> {
1514 pub fn name(&self, db: &'db dyn Database) -> SmolStrId<'db> {
1515 match self {
1516 ImplItemId::Function(id) => id.name(db),
1517 ImplItemId::Type(id) => id.name(db),
1518 ImplItemId::Constant(id) => id.name(db),
1519 ImplItemId::Impl(id) => id.name(db),
1520 }
1521 }
1522 pub fn impl_def_id(&self, db: &'db dyn Database) -> ImplDefId<'db> {
1523 match self {
1524 ImplItemId::Function(id) => id.impl_def_id(db),
1525 ImplItemId::Type(id) => id.impl_def_id(db),
1526 ImplItemId::Constant(id) => id.impl_def_id(db),
1527 ImplItemId::Impl(id) => id.impl_def_id(db),
1528 }
1529 }
1530}
1531
1532define_language_element_id_as_enum! {
1533 #[toplevel]
1534 pub enum LookupItemId<'db> {
1538 ModuleItem(ModuleItemId<'db>),
1539 TraitItem(TraitItemId<'db>),
1540 ImplItem(ImplItemId<'db>),
1541 }
1542}