cairo_lang_semantic/resolve/
item.rs

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