1use std::cmp::{Ord, PartialOrd};
2
3use derive_generic_visitor::{Drive, DriveMut, DriveTwo};
4use serde::{Deserialize, Serialize};
5use serde_state::{DeserializeState, SerializeState};
6
7use crate::ast::*;
8use macros::{EnumAsGetters, EnumIsA, VariantIndexArity, VariantName};
9
10generate_index_type!(FunDeclId, "Fun");
11generate_index_type!(TypeDeclId, "Adt");
12
13impl TypeDeclId {
14 pub const UNIT: Self = Self::ZERO;
17}
18generate_index_type!(GlobalDeclId, "Global");
19generate_index_type!(TraitDeclId, "TraitDecl");
20generate_index_type!(TraitImplId, "TraitImpl");
21
22#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
24#[derive(EnumIsA, EnumAsGetters, VariantName, VariantIndexArity)]
25#[derive(
26 Serialize,
27 Deserialize,
28 SerializeState,
29 DeserializeState,
30 Drive,
31 DriveMut,
32 DriveTwo
33)]
34#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Id"))]
35#[serde_state(stateless)]
36pub enum ItemId {
37 Type(TypeDeclId),
38 TraitDecl(TraitDeclId),
39 TraitImpl(TraitImplId),
40 Fun(FunDeclId),
41 Global(GlobalDeclId),
42}
43
44#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
46#[derive(EnumIsA, EnumAsGetters, VariantName, VariantIndexArity)]
47#[derive(
48 Serialize,
49 Deserialize,
50 SerializeState,
51 DeserializeState,
52 Drive,
53 DriveMut,
54 DriveTwo
55)]
56#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("AssocId"))]
57#[serde_state(stateless)]
58pub enum AssocItemId {
59 Type(AssocTypeId),
60 Method(TraitMethodId),
61 Const(AssocConstId),
62}
63
64#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
66#[derive(EnumIsA, EnumAsGetters, VariantName, VariantIndexArity)]
67#[derive(
68 Serialize,
69 Deserialize,
70 SerializeState,
71 DeserializeState,
72 Drive,
73 DriveMut,
74 DriveTwo
75)]
76#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Item"))]
77#[serde_state(stateless)]
78pub enum MaybeAssocItemId {
79 Free(ItemId),
80 Assoc(TraitDeclId, AssocItemId),
81}
82
83#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
88#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
89pub struct TypeDeclRef {
90 pub id: TypeDeclId,
91 pub generics: BoxedArgs,
92 pub builtin: Option<BuiltinAdt>,
94}
95
96#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
98#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
99pub struct FunDeclRef {
100 pub id: FunDeclId,
101 pub generics: BoxedArgs,
103}
104
105#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
106#[derive(EnumAsGetters)]
107#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
108pub enum FnPtrKind {
109 Fun(FunDeclId),
110 #[cfg_attr(feature = "charon_on_charon", charon::rename("TraitMethod"))]
112 Trait(TraitRef, TraitMethodId),
113}
114
115#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
117#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
118pub struct FnPtr {
119 pub kind: Box<FnPtrKind>,
120 pub generics: BoxedArgs,
121}
122
123#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
125#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
126pub struct GlobalDeclRef {
127 pub id: GlobalDeclId,
128 pub generics: BoxedArgs,
129}
130
131#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
140#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
141pub struct TraitDeclRef {
142 pub id: TraitDeclId,
143 pub generics: BoxedArgs,
144}
145
146#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
148#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
149pub struct TraitImplRef {
150 pub id: TraitImplId,
151 pub generics: BoxedArgs,
152}
153
154impl TypeDeclRef {
155 pub fn new(id: TypeDeclId, generics: GenericArgs, builtin: Option<BuiltinAdt>) -> Self {
156 Self {
157 id,
158 generics: Box::new(generics),
159 builtin,
160 }
161 }
162
163 pub fn as_builtin(&self) -> Option<BuiltinAdt> {
164 self.builtin
165 }
166
167 pub fn is_builtin(&self) -> bool {
168 self.builtin.is_some()
169 }
170
171 pub fn is_box(&self) -> bool {
173 matches!(self.builtin, Some(BuiltinAdt::Box))
174 }
175
176 pub fn is_tuple(&self) -> bool {
178 matches!(self.builtin, Some(BuiltinAdt::Tuple))
179 }
180
181 pub fn is_str(&self) -> bool {
183 matches!(self.builtin, Some(BuiltinAdt::Str))
184 }
185}
186
187impl TraitDeclRef {
188 pub fn self_ty<'a>(&'a self, krate: &'a TranslatedCrate) -> Option<&'a Ty> {
189 match self.generics.types.iter().next() {
190 Some(ty) => Some(ty),
191 None => {
193 let name = krate.item_name(self.id);
194 let args = name.name.last()?.as_monomorphized()?;
195 args.types.iter().next()
196 }
197 }
198 }
199}
200
201impl FnPtr {
202 pub fn new(kind: FnPtrKind, generics: impl Into<BoxedArgs>) -> Self {
203 Self {
204 kind: Box::new(kind),
205 generics: generics.into(),
206 }
207 }
208
209 pub fn pre_mono_generics<'a>(&'a self, krate: &'a TranslatedCrate) -> &'a GenericArgs {
211 match *self.kind {
212 FnPtrKind::Fun(fun_id) => krate
213 .item_name(fun_id)
214 .mono_args()
215 .unwrap_or(&self.generics),
216 FnPtrKind::Trait(..) => &self.generics,
218 }
219 }
220}
221
222#[derive(Debug, Clone, PartialEq, Eq)]
224#[derive(Drive, DriveMut, DriveTwo)]
225pub struct DeclRef<Id> {
226 pub id: Id,
227 pub generics: BoxedArgs,
228 pub trait_ref: Option<TraitRef>,
233}
234
235impl DeclRef<ItemId> {
236 pub fn try_convert_id<Id>(self) -> Result<DeclRef<Id>, <ItemId as TryInto<Id>>::Error>
237 where
238 ItemId: TryInto<Id>,
239 {
240 Ok(DeclRef {
241 id: self.id.try_into()?,
242 generics: self.generics,
243 trait_ref: self.trait_ref,
244 })
245 }
246}
247
248macro_rules! convert_item_ref {
250 ($item_ref_ty:ident($id:ident)) => {
251 impl TryFrom<DeclRef<ItemId>> for $item_ref_ty {
252 type Error = ();
253 fn try_from(item: DeclRef<ItemId>) -> Result<Self, ()> {
254 assert!(item.trait_ref.is_none());
255 Ok($item_ref_ty {
256 id: item.id.try_into()?,
257 generics: item.generics,
258 })
259 }
260 }
261 impl From<DeclRef<$id>> for $item_ref_ty {
262 fn from(item: DeclRef<$id>) -> Self {
263 assert!(item.trait_ref.is_none());
264 $item_ref_ty {
265 id: item.id,
266 generics: item.generics,
267 }
268 }
269 }
270 };
271}
272convert_item_ref!(FunDeclRef(FunDeclId));
275convert_item_ref!(GlobalDeclRef(GlobalDeclId));
276convert_item_ref!(TraitDeclRef(TraitDeclId));
277convert_item_ref!(TraitImplRef(TraitImplId));
278impl TryFrom<DeclRef<ItemId>> for FnPtr {
279 type Error = ();
280 fn try_from(item: DeclRef<ItemId>) -> Result<Self, ()> {
281 if item.trait_ref.is_some() {
282 panic!(
283 "converting `DeclRef<ItemId>` to `FnPtr` cannot
284 deal with the trait method case."
285 )
286 }
287 let id: FunDeclId = item.id.try_into()?;
288 Ok(FnPtr::new(id.into(), item.generics))
289 }
290}
291impl From<FunDeclRef> for FnPtr {
292 fn from(fn_ref: FunDeclRef) -> Self {
293 FnPtr::new(fn_ref.id.into(), fn_ref.generics)
294 }
295}
296
297macro_rules! wrap_unwrap_enum {
299 ($enum:ident::$variant:ident($variant_ty:ident)) => {
300 impl TryFrom<$enum> for $variant_ty {
301 type Error = ();
302 fn try_from(x: $enum) -> Result<Self, Self::Error> {
303 match x {
304 $enum::$variant(x) => Ok(x),
305 _ => Err(()),
306 }
307 }
308 }
309
310 impl From<$variant_ty> for $enum {
311 fn from(x: $variant_ty) -> Self {
312 $enum::$variant(x)
313 }
314 }
315 };
316}
317
318wrap_unwrap_enum!(ItemId::Fun(FunDeclId));
319wrap_unwrap_enum!(ItemId::Global(GlobalDeclId));
320wrap_unwrap_enum!(ItemId::Type(TypeDeclId));
321wrap_unwrap_enum!(ItemId::TraitDecl(TraitDeclId));
322wrap_unwrap_enum!(ItemId::TraitImpl(TraitImplId));
323wrap_unwrap_enum!(AssocItemId::Type(AssocTypeId));
324wrap_unwrap_enum!(AssocItemId::Method(TraitMethodId));
325wrap_unwrap_enum!(AssocItemId::Const(AssocConstId));
326
327impl From<FunDeclId> for FnPtrKind {
328 fn from(id: FunDeclId) -> Self {
329 Self::Fun(id)
330 }
331}