cairo_lang_semantic/resolve/
item.rs

1use cairo_lang_defs::ids::{
2    ConstantId, GenericTypeId, ImplAliasId, ImplDefId, MacroDeclarationId, ModuleId, ModuleItemId,
3    ModuleTypeAliasId, TopLevelLanguageElementId, TraitId, TraitItemId, VarId,
4};
5use cairo_lang_diagnostics::Maybe;
6use cairo_lang_proc_macros::DebugWithDb;
7use salsa::Database;
8
9use crate::items::constant::{ConstValue, ConstValueId};
10use crate::items::functions::GenericFunctionId;
11use crate::items::imp::{ImplId, ImplLongId};
12use crate::items::us::SemanticUseEx;
13use crate::{ConcreteTraitId, ConcreteVariant, FunctionId, TypeId, TypeLongId, Variant};
14
15// Resolved items:
16// ResolvedConcreteItem - returned by resolve_concrete_path(). Paths with generic arguments.
17// ResolvedGenericItem - returned by resolve_generic_path(). Paths without generic arguments.
18
19#[derive(Clone, PartialEq, Eq, Debug, DebugWithDb, salsa::Update)]
20#[debug_db(dyn Database)]
21pub enum ResolvedGenericItem<'db> {
22    GenericConstant(ConstantId<'db>),
23    Module(ModuleId<'db>),
24    GenericFunction(GenericFunctionId<'db>),
25    GenericType(GenericTypeId<'db>),
26    GenericTypeAlias(ModuleTypeAliasId<'db>),
27    GenericImplAlias(ImplAliasId<'db>),
28    Variant(Variant<'db>),
29    Trait(TraitId<'db>),
30    Impl(ImplDefId<'db>),
31    Variable(VarId<'db>),
32    Macro(MacroDeclarationId<'db>),
33    TraitItem(TraitItemId<'db>),
34}
35impl<'db> ResolvedGenericItem<'db> {
36    /// Wraps a ModuleItem with the corresponding ResolveGenericItem.
37    pub fn from_module_item(
38        db: &'db dyn Database,
39        module_item: ModuleItemId<'db>,
40    ) -> Maybe<ResolvedGenericItem<'db>> {
41        Ok(match module_item {
42            ModuleItemId::Constant(id) => ResolvedGenericItem::GenericConstant(id),
43            ModuleItemId::Submodule(id) => ResolvedGenericItem::Module(ModuleId::Submodule(id)),
44            ModuleItemId::Use(id) => {
45                // Note that `use_resolved_item` needs to be called before
46                // `use_semantic_diagnostics` to handle cycles.
47                db.use_resolved_item(id)?
48            }
49            ModuleItemId::FreeFunction(id) => {
50                ResolvedGenericItem::GenericFunction(GenericFunctionId::Free(id))
51            }
52            ModuleItemId::ExternFunction(id) => {
53                ResolvedGenericItem::GenericFunction(GenericFunctionId::Extern(id))
54            }
55            ModuleItemId::Struct(id) => ResolvedGenericItem::GenericType(GenericTypeId::Struct(id)),
56            ModuleItemId::Enum(id) => ResolvedGenericItem::GenericType(GenericTypeId::Enum(id)),
57            ModuleItemId::TypeAlias(id) => ResolvedGenericItem::GenericTypeAlias(id),
58            ModuleItemId::ImplAlias(id) => ResolvedGenericItem::GenericImplAlias(id),
59            ModuleItemId::ExternType(id) => {
60                ResolvedGenericItem::GenericType(GenericTypeId::Extern(id))
61            }
62            ModuleItemId::Trait(id) => ResolvedGenericItem::Trait(id),
63            ModuleItemId::Impl(id) => ResolvedGenericItem::Impl(id),
64            ModuleItemId::MacroDeclaration(id) => ResolvedGenericItem::Macro(id),
65        })
66    }
67
68    pub fn full_path(&self, db: &dyn Database) -> String {
69        match self {
70            ResolvedGenericItem::GenericConstant(_) => "".into(),
71            ResolvedGenericItem::Module(id) => id.full_path(db),
72            ResolvedGenericItem::GenericFunction(id) => id.format(db),
73            ResolvedGenericItem::GenericType(id) => id.full_path(db),
74            ResolvedGenericItem::GenericTypeAlias(id) => id.full_path(db),
75            ResolvedGenericItem::GenericImplAlias(id) => id.full_path(db),
76            ResolvedGenericItem::Variant(id) => id.id.full_path(db),
77            ResolvedGenericItem::Trait(id) => id.full_path(db),
78            ResolvedGenericItem::Impl(id) => id.full_path(db),
79            ResolvedGenericItem::Macro(id) => id.full_path(db),
80            ResolvedGenericItem::Variable(_) => "".into(),
81            ResolvedGenericItem::TraitItem(id) => id.full_path(db),
82        }
83    }
84}
85
86#[derive(Clone, PartialEq, Eq, Debug, DebugWithDb, salsa::Update)]
87#[debug_db(dyn Database)]
88pub enum ResolvedConcreteItem<'db> {
89    Constant(ConstValueId<'db>),
90    Module(ModuleId<'db>),
91    Function(FunctionId<'db>),
92    Type(TypeId<'db>),
93    Variant(ConcreteVariant<'db>),
94    Trait(ConcreteTraitId<'db>),
95    SelfTrait(ConcreteTraitId<'db>),
96    Impl(ImplId<'db>),
97    Macro(MacroDeclarationId<'db>),
98}
99
100impl<'db> ResolvedConcreteItem<'db> {
101    pub fn generic(&self, db: &'db dyn Database) -> Option<ResolvedGenericItem<'db>> {
102        Some(match self {
103            ResolvedConcreteItem::Constant(id) => {
104                if let ConstValue::ImplConstant(impl_constant_id) = id.long(db) {
105                    ResolvedGenericItem::TraitItem(TraitItemId::Constant(
106                        impl_constant_id.trait_constant_id(),
107                    ))
108                } else {
109                    return None;
110                }
111            }
112            ResolvedConcreteItem::Module(item) => ResolvedGenericItem::Module(*item),
113            ResolvedConcreteItem::Function(function) => {
114                ResolvedGenericItem::GenericFunction(function.long(db).function.generic_function)
115            }
116            ResolvedConcreteItem::Type(ty) => match ty.long(db) {
117                TypeLongId::Concrete(concrete) => {
118                    ResolvedGenericItem::GenericType(concrete.generic_type(db))
119                }
120                TypeLongId::ImplType(impl_type_id) => {
121                    ResolvedGenericItem::TraitItem(TraitItemId::Type(impl_type_id.ty()))
122                }
123                _ => return None,
124            },
125            ResolvedConcreteItem::Variant(ConcreteVariant { concrete_enum_id, id, ty, idx }) => {
126                ResolvedGenericItem::Variant(Variant {
127                    enum_id: concrete_enum_id.enum_id(db),
128                    id: *id,
129                    ty: *ty,
130                    idx: *idx,
131                })
132            }
133            ResolvedConcreteItem::Trait(concrete_trait) => {
134                ResolvedGenericItem::Trait(concrete_trait.long(db).trait_id)
135            }
136            ResolvedConcreteItem::SelfTrait(concrete_trait_id) => {
137                ResolvedGenericItem::Trait(concrete_trait_id.trait_id(db))
138            }
139            ResolvedConcreteItem::Impl(impl_id) => match impl_id.long(db) {
140                ImplLongId::Concrete(concrete_impl_id) => {
141                    ResolvedGenericItem::Impl(concrete_impl_id.long(db).impl_def_id)
142                }
143                ImplLongId::ImplImpl(impl_impl_id) => {
144                    ResolvedGenericItem::TraitItem(TraitItemId::Impl(impl_impl_id.trait_impl_id()))
145                }
146                ImplLongId::SelfImpl(concrete_trait_id) => {
147                    ResolvedGenericItem::Trait(concrete_trait_id.trait_id(db))
148                }
149                ImplLongId::GenericParameter(_)
150                | ImplLongId::ImplVar(_)
151                | ImplLongId::GeneratedImpl(_) => return None,
152            },
153            ResolvedConcreteItem::Macro(macro_declaration_id) => {
154                ResolvedGenericItem::Macro(*macro_declaration_id)
155            }
156        })
157    }
158}