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),
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 fn_once_impl: RegionBinder<TraitImplRef>,
182 pub fn_mut_impl: Option<RegionBinder<TraitImplRef>>,
184 pub fn_impl: Option<RegionBinder<TraitImplRef>>,
186 pub signature: RegionBinder<FunSig>,
188}
189
190#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
191#[derive(Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
192pub enum ClosureKind {
193 Fn,
194 FnMut,
195 FnOnce,
196}
197
198impl TypeDecl {
199 pub fn get_fields(&self, variant: Option<VariantId>) -> Option<&IndexVec<FieldId, Field>> {
200 match &self.kind {
201 TypeDeclKind::Struct(fields) | TypeDeclKind::Union(fields) => Some(fields),
202 TypeDeclKind::Enum(variants) => Some(&variants[variant.unwrap()].fields),
203 _ => None,
204 }
205 }
206
207 pub fn get_field(&self, variant: Option<VariantId>, field: FieldId) -> Option<&Field> {
208 self.get_fields(variant)?.get(field)
209 }
210
211 pub fn get_field_by_name(
212 &self,
213 variant: Option<VariantId>,
214 field_name: &str,
215 ) -> Option<(FieldId, &Field)> {
216 let fields = match &self.kind {
217 TypeDeclKind::Struct(fields) | TypeDeclKind::Union(fields) => fields,
218 TypeDeclKind::Enum(variants) => &variants[variant.unwrap()].fields,
219 _ => return None,
220 };
221 fields
222 .iter_enumerated()
223 .find(|(_, field)| field.name == field_name)
224 }
225
226 pub fn self_ref(&self) -> TypeDeclRef {
228 TypeDeclRef {
229 id: self.def_id,
230 generics: Box::new(self.generics.identity_args()),
231 builtin: self.src.as_builtin().cloned(),
232 }
233 }
234}
235
236impl Variant {
237 pub fn renamed_name(&self) -> &str {
240 self.attr_info
241 .rename
242 .as_deref()
243 .unwrap_or(self.name.as_ref())
244 }
245
246 pub fn is_opaque(&self) -> bool {
248 self.attr_info
249 .attributes
250 .iter()
251 .any(|attr| attr.is_opaque())
252 }
253}
254
255impl Field {
256 pub fn renamed_name(&self) -> &str {
258 self.attr_info.rename.as_deref().unwrap_or(&self.name)
259 }
260
261 pub fn is_opaque(&self) -> bool {
263 self.attr_info
264 .attributes
265 .iter()
266 .any(|attr| attr.is_opaque())
267 }
268}
269
270impl ClosureKind {
271 pub fn method_name(self) -> &'static str {
273 match self {
274 ClosureKind::FnOnce => "call_once",
275 ClosureKind::FnMut => "call_mut",
276 ClosureKind::Fn => "call",
277 }
278 }
279}
280
281impl PtrMetadata {
282 pub fn into_type(self) -> Ty {
283 match self {
284 PtrMetadata::None => Ty::mk_unit(),
285 PtrMetadata::Length => Ty::mk_usize(),
286 PtrMetadata::VTable(type_decl_ref) => Ty::new(TyKind::Ref(
287 Region::Static,
288 Ty::new(TyKind::Adt(type_decl_ref)),
289 RefKind::Shared,
290 )),
291 PtrMetadata::InheritFrom(ty) => Ty::new(TyKind::PtrMetadata(ty)),
292 }
293 }
294}