cairo_lang_sierra/extensions/
types.rs1use super::args_as_single_type;
2use super::error::{ExtensionError, SpecializationError};
3use super::type_specialization_context::TypeSpecializationContext;
4use crate::ids::{ConcreteTypeId, GenericTypeId};
5use crate::program::{ConcreteTypeLongId, GenericArg};
6
7pub trait GenericType: Sized {
9 type Concrete: ConcreteType;
10
11 fn by_id(id: &GenericTypeId) -> Option<Self>;
13 fn specialize(
15 &self,
16 context: &dyn TypeSpecializationContext,
17 args: &[GenericArg],
18 ) -> Result<Self::Concrete, SpecializationError>;
19}
20
21pub trait GenericTypeEx: GenericType {
23 fn specialize_by_id(
24 context: &dyn TypeSpecializationContext,
25 type_id: &GenericTypeId,
26 args: &[GenericArg],
27 ) -> Result<Self::Concrete, ExtensionError>;
28}
29impl<TGenericType: GenericType> GenericTypeEx for TGenericType {
30 fn specialize_by_id(
31 context: &dyn TypeSpecializationContext,
32 type_id: &GenericTypeId,
33 args: &[GenericArg],
34 ) -> Result<TGenericType::Concrete, ExtensionError> {
35 Self::by_id(type_id)
36 .ok_or_else(move || ExtensionError::TypeSpecialization {
37 type_id: type_id.clone(),
38 error: SpecializationError::UnsupportedId(type_id.0.clone()),
39 })?
40 .specialize(context, args)
41 .map_err(move |error| ExtensionError::TypeSpecialization {
42 type_id: type_id.clone(),
43 error,
44 })
45 }
46}
47
48pub trait NamedType: Default {
50 type Concrete: ConcreteType;
51 const ID: GenericTypeId;
52 fn id() -> GenericTypeId {
54 Self::ID
55 }
56 fn concrete_type_long_id(generic_args: &[GenericArg]) -> ConcreteTypeLongId {
58 ConcreteTypeLongId { generic_id: Self::id(), generic_args: generic_args.to_vec() }
59 }
60 fn specialize(
62 &self,
63 context: &dyn TypeSpecializationContext,
64 args: &[GenericArg],
65 ) -> Result<Self::Concrete, SpecializationError>;
66}
67impl<TNamedType: NamedType> GenericType for TNamedType {
68 type Concrete = <Self as NamedType>::Concrete;
69
70 fn by_id(id: &GenericTypeId) -> Option<Self> {
71 if &Self::ID == id { Some(Self::default()) } else { None }
72 }
73
74 fn specialize(
75 &self,
76 context: &dyn TypeSpecializationContext,
77 args: &[GenericArg],
78 ) -> Result<Self::Concrete, SpecializationError> {
79 <Self as NamedType>::specialize(self, context, args)
80 }
81}
82
83pub trait NoGenericArgsGenericType: Default {
85 const ID: GenericTypeId;
86 const STORABLE: bool;
87 const DUPLICATABLE: bool;
88 const DROPPABLE: bool;
89 const ZERO_SIZED: bool;
90}
91impl<T: NoGenericArgsGenericType> NamedType for T {
92 type Concrete = InfoOnlyConcreteType;
93 const ID: GenericTypeId = <Self as NoGenericArgsGenericType>::ID;
94
95 fn specialize(
96 &self,
97 _context: &dyn TypeSpecializationContext,
98 args: &[GenericArg],
99 ) -> Result<Self::Concrete, SpecializationError> {
100 if args.is_empty() {
101 Ok(Self::Concrete {
102 info: TypeInfo {
103 long_id: Self::concrete_type_long_id(args),
104 storable: T::STORABLE,
105 droppable: T::DROPPABLE,
106 duplicatable: T::DUPLICATABLE,
107 zero_sized: T::ZERO_SIZED,
108 },
109 })
110 } else {
111 Err(SpecializationError::WrongNumberOfGenericArgs)
112 }
113 }
114}
115
116pub trait GenericTypeArgGenericType: Default {
118 const ID: GenericTypeId;
119
120 fn calc_info(
122 &self,
123 context: &dyn TypeSpecializationContext,
124 long_id: ConcreteTypeLongId,
125 wrapped_info: TypeInfo,
126 ) -> Result<TypeInfo, SpecializationError>;
127}
128
129#[derive(Default)]
131pub struct GenericTypeArgGenericTypeWrapper<T: GenericTypeArgGenericType>(T);
132impl<T: GenericTypeArgGenericType> NamedType for GenericTypeArgGenericTypeWrapper<T> {
133 type Concrete = InfoAndTypeConcreteType;
134 const ID: GenericTypeId = T::ID;
135
136 fn specialize(
137 &self,
138 context: &dyn TypeSpecializationContext,
139 args: &[GenericArg],
140 ) -> Result<Self::Concrete, SpecializationError> {
141 let ty = args_as_single_type(args)?;
142 let long_id = Self::concrete_type_long_id(args);
143 let wrapped_info = context.get_type_info(ty.clone())?;
144 Ok(Self::Concrete { info: self.0.calc_info(context, long_id, wrapped_info)?, ty })
145 }
146}
147
148#[derive(Clone, Debug, Eq, PartialEq)]
150pub struct TypeInfo {
151 pub long_id: ConcreteTypeLongId,
153 pub storable: bool,
155 pub droppable: bool,
157 pub duplicatable: bool,
159 pub zero_sized: bool,
161}
162
163pub trait ConcreteType {
165 fn info(&self) -> &TypeInfo;
166}
167
168pub struct InfoOnlyConcreteType {
171 pub info: TypeInfo,
172}
173
174impl ConcreteType for InfoOnlyConcreteType {
175 fn info(&self) -> &TypeInfo {
176 &self.info
177 }
178}
179
180pub struct InfoAndTypeConcreteType {
182 pub info: TypeInfo,
183 pub ty: ConcreteTypeId,
184}
185
186impl ConcreteType for InfoAndTypeConcreteType {
187 fn info(&self) -> &TypeInfo {
188 &self.info
189 }
190}
191
192#[macro_export]
205macro_rules! define_type_hierarchy {
206 (pub enum $name:ident { $($variant_name:ident ($variant:ty),)* },
207 $concrete_name:ident) => {
208 #[allow(clippy::enum_variant_names)]
209 pub enum $name {
210 $($variant_name ($variant)),*
211 }
212
213 impl $crate::extensions::types::GenericType for $name {
214 type Concrete = $concrete_name;
215 fn by_id(id: &$crate::ids::GenericTypeId) -> Option<Self> {
216 $(
217 if let Some(res) = <$variant>::by_id(id){
218 return Some(Self::$variant_name(res));
219 }
220 )*
221 None
222 }
223 fn specialize(
224 &self,
225 context: &dyn $crate::extensions::type_specialization_context::TypeSpecializationContext,
226 args: &[$crate::program::GenericArg]
227 ) -> Result<Self::Concrete, $crate::extensions::SpecializationError>{
228 match self {
229 $(
230 Self::$variant_name(value) => {
231 Ok(Self::Concrete::$variant_name(
232 <$variant as $crate::extensions::GenericType>::specialize(
233 value, context, args,
234 )?
235 .into(),
236 ))
237 }
238 ),*
239 }
240 }
241 }
242
243 pub enum $concrete_name {
244 $($variant_name (<$variant as $crate::extensions::GenericType> ::Concrete),)*
245 }
246 impl $crate::extensions::ConcreteType for $concrete_name {
247 fn info(&self) -> &$crate::extensions::types::TypeInfo {
248 match self {
249 $(Self::$variant_name(value) => value.info()),*
250 }
251 }
252 }
253 }
254}