cairo_lang_semantic/resolve/
item.rs

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