cairo_lang_semantic/resolve/
item.rs

1use cairo_lang_defs::ids::{
2    ConstantId, GenericTypeId, ImplAliasId, ImplDefId, ModuleId, ModuleItemId, ModuleTypeAliasId,
3    TopLevelLanguageElementId, TraitId, TraitItemId, 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::{ConstValue, 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    TraitItem(TraitItemId),
34}
35impl ResolvedGenericItem {
36    /// Wraps a ModuleItem with the corresponding ResolveGenericItem.
37    pub fn from_module_item(
38        db: &dyn SemanticGroup,
39        module_item: ModuleItemId,
40    ) -> Maybe<ResolvedGenericItem> {
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        })
65    }
66
67    pub fn full_path(&self, db: &dyn SemanticGroup) -> String {
68        let defs_db = db.upcast();
69        match self {
70            ResolvedGenericItem::GenericConstant(_) => "".into(),
71            ResolvedGenericItem::Module(id) => id.full_path(defs_db),
72            ResolvedGenericItem::GenericFunction(id) => id.format(db),
73            ResolvedGenericItem::GenericType(id) => id.full_path(defs_db),
74            ResolvedGenericItem::GenericTypeAlias(id) => id.full_path(defs_db),
75            ResolvedGenericItem::GenericImplAlias(id) => id.full_path(defs_db),
76            ResolvedGenericItem::Variant(id) => id.id.full_path(defs_db),
77            ResolvedGenericItem::Trait(id) => id.full_path(defs_db),
78            ResolvedGenericItem::Impl(id) => id.full_path(defs_db),
79            ResolvedGenericItem::Variable(_) => "".into(),
80            ResolvedGenericItem::TraitItem(id) => id.full_path(defs_db),
81        }
82    }
83}
84
85#[derive(Clone, PartialEq, Eq, Debug, DebugWithDb)]
86#[debug_db(dyn SemanticGroup + 'static)]
87pub enum ResolvedConcreteItem {
88    Constant(ConstValueId),
89    Module(ModuleId),
90    Function(FunctionId),
91    Type(TypeId),
92    Variant(ConcreteVariant),
93    Trait(ConcreteTraitId),
94    SelfTrait(ConcreteTraitId),
95    Impl(ImplId),
96}
97
98impl ResolvedConcreteItem {
99    pub fn generic(&self, db: &dyn SemanticGroup) -> Option<ResolvedGenericItem> {
100        Some(match self {
101            ResolvedConcreteItem::Constant(id) => {
102                if let ConstValue::ImplConstant(impl_constant_id) = id.lookup_intern(db) {
103                    ResolvedGenericItem::TraitItem(TraitItemId::Constant(
104                        impl_constant_id.trait_constant_id(),
105                    ))
106                } else {
107                    return None;
108                }
109            }
110            ResolvedConcreteItem::Module(item) => ResolvedGenericItem::Module(*item),
111            ResolvedConcreteItem::Function(function) => ResolvedGenericItem::GenericFunction(
112                function.lookup_intern(db).function.generic_function,
113            ),
114            ResolvedConcreteItem::Type(ty) => match ty.lookup_intern(db) {
115                TypeLongId::Concrete(concrete) => {
116                    ResolvedGenericItem::GenericType(concrete.generic_type(db))
117                }
118                TypeLongId::ImplType(impl_type_id) => {
119                    ResolvedGenericItem::TraitItem(TraitItemId::Type(impl_type_id.ty()))
120                }
121                _ => return None,
122            },
123            ResolvedConcreteItem::Variant(ConcreteVariant { concrete_enum_id, id, ty, idx }) => {
124                ResolvedGenericItem::Variant(Variant {
125                    enum_id: concrete_enum_id.enum_id(db),
126                    id: *id,
127                    ty: *ty,
128                    idx: *idx,
129                })
130            }
131            ResolvedConcreteItem::Trait(concrete_trait) => {
132                ResolvedGenericItem::Trait(concrete_trait.lookup_intern(db).trait_id)
133            }
134            ResolvedConcreteItem::SelfTrait(concrete_trait_id) => {
135                ResolvedGenericItem::Trait(concrete_trait_id.trait_id(db))
136            }
137            ResolvedConcreteItem::Impl(impl_id) => match impl_id.lookup_intern(db) {
138                ImplLongId::Concrete(concrete_impl_id) => {
139                    ResolvedGenericItem::Impl(concrete_impl_id.lookup_intern(db).impl_def_id)
140                }
141                ImplLongId::ImplImpl(impl_impl_id) => {
142                    ResolvedGenericItem::TraitItem(TraitItemId::Impl(impl_impl_id.trait_impl_id()))
143                }
144                ImplLongId::SelfImpl(concrete_trait_id) => {
145                    ResolvedGenericItem::Trait(concrete_trait_id.trait_id(db))
146                }
147                ImplLongId::GenericParameter(_)
148                | ImplLongId::ImplVar(_)
149                | ImplLongId::GeneratedImpl(_) => return None,
150            },
151        })
152    }
153}