1use derive_generic_visitor::*;
2use macros::{EnumAsGetters, EnumIsA};
3use serde::{Deserialize, Serialize};
4use serde_state::{DeserializeState, SerializeState};
5
6use crate::ast::*;
7use crate::ids::IndexVec;
8use crate::utils::serialize_map_to_array::SeqHashMapToArray;
9
10#[derive(Debug, Clone)]
24#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
25#[serde_state(state_implements = DedupSerializerState)]
26pub struct TypeDecl {
27 pub def_id: TypeDeclId,
28 pub item_meta: ItemMeta,
30 pub generics: GenericParams,
31 pub src: TypeSource,
33 pub kind: TypeDeclKind,
35 #[serde(with = "SeqHashMapToArray::<TargetTriple, Layout>")]
38 pub layout: SeqHashMap<TargetTriple, Layout>,
39 pub ptr_metadata: PtrMetadata,
41 pub marker_traits: Option<Box<ImplementsMarkerTraits>>,
44}
45
46generate_index_type!(VariantId, "Variant");
47generate_index_type!(FieldId, "Field");
48
49#[derive(Debug, Clone)]
50#[derive(EnumIsA, EnumAsGetters)]
51#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
52pub enum TypeDeclKind {
53 Struct(IndexVec<FieldId, Field>),
54 Enum(IndexVec<VariantId, Variant>),
55 Union(IndexVec<FieldId, Field>),
56 Opaque,
60 Alias(Ty),
63 #[cfg_attr(feature = "charon_on_charon", charon::rename("TDeclError"))]
66 Error(String),
67}
68
69#[derive(Debug, Clone)]
70#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
71#[serde_state(stateless)]
72pub struct Variant {
73 pub id: VariantId,
74 pub span: Span,
75 pub attr_info: AttrInfo,
76 #[cfg_attr(feature = "charon_on_charon", charon::rename("variant_name"))]
77 pub name: String,
78 #[serde_state(stateful)]
79 pub fields: IndexVec<FieldId, Field>,
80 pub discriminant: IntegerValue,
84}
85
86#[derive(Debug, Clone)]
87#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
88#[serde_state(stateless)]
89pub struct Field {
90 pub span: Span,
91 pub attr_info: AttrInfo,
92 #[cfg_attr(feature = "charon_on_charon", charon::rename("field_name"))]
93 pub name: String,
94 pub is_positional: bool,
97 #[cfg_attr(feature = "charon_on_charon", charon::rename("field_ty"))]
98 #[serde_state(stateful)]
99 pub ty: Ty,
100}
101
102#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
106#[derive(EnumIsA)]
107#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
108#[serde_state(default_state = ())]
109pub enum PtrMetadata {
110 #[cfg_attr(feature = "charon_on_charon", charon::rename("NoMetadata"))]
112 None,
113 Length,
119 VTable(TypeDeclRef),
121 InheritFrom(Ty),
125}
126
127#[derive(Debug, Clone)]
129#[derive(EnumIsA, EnumAsGetters)]
130#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
131#[cfg_attr(feature = "charon_on_charon", charon::variants_suffix("Type"))]
132pub enum TypeSource {
133 Normal,
135 Closure { info: ClosureInfo },
137 VTable {
139 dyn_predicate: DynPredicate,
141 field_map: IndexVec<FieldId, VTableField>,
143 supertrait_map: IndexVec<TraitClauseId, Option<FieldId>>,
146 },
147 Builtin(BuiltinAdt),
149}
150
151#[derive(Debug, Clone, Copy, PartialEq, Eq)]
153#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
154#[serde_state(stateless)]
155pub struct ImplementsMarkerTraits {
156 pub is_sized: bool,
157 pub is_send: bool,
158 pub is_sync: bool,
159 pub is_freeze: bool,
160 pub is_unpin: bool,
161}
162
163#[derive(Debug, Clone, PartialEq, Eq)]
164#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
165#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("VTable"))]
166pub enum VTableField {
167 Size,
168 Align,
169 Drop,
170 Method(TraitMethodId, MetadataPath),
171 SuperTrait(TraitClauseId),
172}
173
174#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
176#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
177pub struct ClosureInfo {
178 #[serde_state(stateless)]
179 pub kind: ClosureKind,
180 pub closure_body: FunDeclRef,
182 pub fn_once_impl: RegionBinder<TraitImplRef>,
184 pub fn_mut_impl: Option<RegionBinder<TraitImplRef>>,
186 pub fn_impl: Option<RegionBinder<TraitImplRef>>,
188 pub signature: RegionBinder<FunSig>,
190}
191
192#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
193#[derive(Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
194pub enum ClosureKind {
195 Fn,
196 FnMut,
197 FnOnce,
198}
199
200impl TypeDecl {
201 pub fn get_fields(&self, variant: Option<VariantId>) -> Option<&IndexVec<FieldId, Field>> {
202 match &self.kind {
203 TypeDeclKind::Struct(fields) | TypeDeclKind::Union(fields) => Some(fields),
204 TypeDeclKind::Enum(variants) => Some(&variants[variant.unwrap()].fields),
205 _ => None,
206 }
207 }
208
209 pub fn get_field(&self, variant: Option<VariantId>, field: FieldId) -> Option<&Field> {
210 self.get_fields(variant)?.get(field)
211 }
212
213 pub fn get_field_by_name(
214 &self,
215 variant: Option<VariantId>,
216 field_name: &str,
217 ) -> Option<(FieldId, &Field)> {
218 let fields = match &self.kind {
219 TypeDeclKind::Struct(fields) | TypeDeclKind::Union(fields) => fields,
220 TypeDeclKind::Enum(variants) => &variants[variant.unwrap()].fields,
221 _ => return None,
222 };
223 fields
224 .iter_enumerated()
225 .find(|(_, field)| field.name == field_name)
226 }
227
228 pub fn self_ref(&self) -> TypeDeclRef {
230 TypeDeclRef {
231 id: self.def_id,
232 generics: Box::new(self.generics.identity_args()),
233 builtin: self.src.as_builtin().cloned(),
234 }
235 }
236}
237
238impl Variant {
239 pub fn renamed_name(&self) -> &str {
242 self.attr_info
243 .rename
244 .as_deref()
245 .unwrap_or(self.name.as_ref())
246 }
247
248 pub fn is_opaque(&self) -> bool {
250 self.attr_info
251 .attributes
252 .iter()
253 .any(|attr| attr.is_opaque())
254 }
255}
256
257impl Field {
258 pub fn renamed_name(&self) -> &str {
260 self.attr_info.rename.as_deref().unwrap_or(&self.name)
261 }
262
263 pub fn is_opaque(&self) -> bool {
265 self.attr_info
266 .attributes
267 .iter()
268 .any(|attr| attr.is_opaque())
269 }
270}
271
272impl ClosureKind {
273 pub fn method_name(self) -> &'static str {
275 match self {
276 ClosureKind::FnOnce => "call_once",
277 ClosureKind::FnMut => "call_mut",
278 ClosureKind::Fn => "call",
279 }
280 }
281}
282
283impl PtrMetadata {
284 pub fn into_type(self) -> Ty {
285 match self {
286 PtrMetadata::None => Ty::mk_unit(),
287 PtrMetadata::Length => Ty::mk_usize(),
288 PtrMetadata::VTable(type_decl_ref) => Ty::new(TyKind::Ref(
289 Region::Static,
290 Ty::new(TyKind::Adt(type_decl_ref)),
291 RefKind::Shared,
292 )),
293 PtrMetadata::InheritFrom(ty) => Ty::new(TyKind::PtrMetadata(ty)),
294 }
295 }
296}