Skip to main content

charon_lib/ast/
items.rs

1use crate::ast::*;
2use derive_generic_visitor::{ControlFlow, Drive, DriveMut, DriveTwo};
3use macros::{EnumAsGetters, EnumIsA, VariantIndexArity, VariantName};
4
5pub mod fun_decl;
6pub mod global_decl;
7pub mod item_ids;
8pub mod layout;
9pub mod trait_decl;
10pub mod trait_impl;
11pub mod type_decl;
12
13pub use fun_decl::*;
14pub use global_decl::*;
15pub use item_ids::*;
16pub use layout::*;
17pub use trait_decl::*;
18pub use trait_impl::*;
19pub use type_decl::*;
20
21/// A translated item.
22#[derive(
23    Debug,
24    PartialEq,
25    Eq,
26    EnumIsA,
27    EnumAsGetters,
28    VariantName,
29    VariantIndexArity,
30    Drive,
31    DriveMut,
32    DriveTwo,
33)]
34pub enum ItemByVal {
35    Type(TypeDecl),
36    Fun(FunDecl),
37    Global(GlobalDecl),
38    TraitDecl(TraitDecl),
39    TraitImpl(TraitImpl),
40}
41
42/// A reference to a translated item.
43#[derive(
44    Debug,
45    Clone,
46    Copy,
47    EnumIsA,
48    EnumAsGetters,
49    VariantName,
50    VariantIndexArity,
51    Drive,
52    DriveMut,
53    DriveTwo,
54)]
55pub enum ItemRef<'ctx> {
56    Type(&'ctx TypeDecl),
57    Fun(&'ctx FunDecl),
58    Global(&'ctx GlobalDecl),
59    TraitDecl(&'ctx TraitDecl),
60    TraitImpl(&'ctx TraitImpl),
61}
62
63/// A mutable reference to a translated item.
64#[derive(
65    Debug,
66    PartialEq,
67    Eq,
68    EnumIsA,
69    EnumAsGetters,
70    VariantName,
71    VariantIndexArity,
72    Drive,
73    DriveMut,
74    DriveTwo,
75)]
76pub enum ItemRefMut<'ctx> {
77    Type(&'ctx mut TypeDecl),
78    Fun(&'ctx mut FunDecl),
79    Global(&'ctx mut GlobalDecl),
80    TraitDecl(&'ctx mut TraitDecl),
81    TraitImpl(&'ctx mut TraitImpl),
82}
83
84impl ItemByVal {
85    pub fn as_ref(&self) -> ItemRef<'_> {
86        match self {
87            Self::Type(d) => ItemRef::Type(d),
88            Self::Fun(d) => ItemRef::Fun(d),
89            Self::Global(d) => ItemRef::Global(d),
90            Self::TraitDecl(d) => ItemRef::TraitDecl(d),
91            Self::TraitImpl(d) => ItemRef::TraitImpl(d),
92        }
93    }
94    pub fn as_mut(&mut self) -> ItemRefMut<'_> {
95        match self {
96            Self::Type(d) => ItemRefMut::Type(d),
97            Self::Fun(d) => ItemRefMut::Fun(d),
98            Self::Global(d) => ItemRefMut::Global(d),
99            Self::TraitDecl(d) => ItemRefMut::TraitDecl(d),
100            Self::TraitImpl(d) => ItemRefMut::TraitImpl(d),
101        }
102    }
103}
104
105impl<'ctx> ItemRef<'ctx> {
106    pub fn id(&self) -> ItemId {
107        match self {
108            ItemRef::Type(d) => d.def_id.into(),
109            ItemRef::Fun(d) => d.def_id.into(),
110            ItemRef::Global(d) => d.def_id.into(),
111            ItemRef::TraitDecl(d) => d.def_id.into(),
112            ItemRef::TraitImpl(d) => d.def_id.into(),
113        }
114    }
115
116    pub fn to_owned(&self) -> ItemByVal {
117        match *self {
118            Self::Type(d) => ItemByVal::Type(d.clone()),
119            Self::Fun(d) => ItemByVal::Fun(d.clone()),
120            Self::Global(d) => ItemByVal::Global(d.clone()),
121            Self::TraitDecl(d) => ItemByVal::TraitDecl(d.clone()),
122            Self::TraitImpl(d) => ItemByVal::TraitImpl(d.clone()),
123        }
124    }
125
126    pub fn item_meta(&self) -> &'ctx ItemMeta {
127        match self {
128            Self::Type(d) => &d.item_meta,
129            Self::Fun(d) => &d.item_meta,
130            Self::Global(d) => &d.item_meta,
131            Self::TraitDecl(d) => &d.item_meta,
132            Self::TraitImpl(d) => &d.item_meta,
133        }
134    }
135    /// The generic parameters of this item.
136    pub fn generic_params(&self) -> &'ctx GenericParams {
137        match self {
138            ItemRef::Type(d) => &d.generics,
139            ItemRef::Fun(d) => &d.generics,
140            ItemRef::Global(d) => &d.generics,
141            ItemRef::TraitDecl(d) => &d.generics,
142            ItemRef::TraitImpl(d) => &d.generics,
143        }
144    }
145
146    /// See [`GenericParams::identity_args`].
147    pub fn identity_args(&self) -> GenericArgs {
148        self.generic_params().identity_args()
149    }
150
151    /// We can't implement `AstVisitable` because of the `'static` constraint, but it's ok because
152    /// `ItemRef` isn't contained in any of our types.
153    pub fn drive<V: VisitAst>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
154        match *self {
155            ItemRef::Type(d) => visitor.visit(d),
156            ItemRef::Fun(d) => visitor.visit(d),
157            ItemRef::Global(d) => visitor.visit(d),
158            ItemRef::TraitDecl(d) => visitor.visit(d),
159            ItemRef::TraitImpl(d) => visitor.visit(d),
160        }
161    }
162
163    /// Visit all occurrences of that type inside `self`, in pre-order traversal.
164    pub fn dyn_visit<T: AstVisitable>(&self, f: impl FnMut(&T)) {
165        match *self {
166            ItemRef::Type(d) => d.dyn_visit(f),
167            ItemRef::Fun(d) => d.dyn_visit(f),
168            ItemRef::Global(d) => d.dyn_visit(f),
169            ItemRef::TraitDecl(d) => d.dyn_visit(f),
170            ItemRef::TraitImpl(d) => d.dyn_visit(f),
171        }
172    }
173}
174
175impl<'ctx> ItemRefMut<'ctx> {
176    pub fn as_ref(&self) -> ItemRef<'_> {
177        match self {
178            ItemRefMut::Type(d) => ItemRef::Type(d),
179            ItemRefMut::Fun(d) => ItemRef::Fun(d),
180            ItemRefMut::Global(d) => ItemRef::Global(d),
181            ItemRefMut::TraitDecl(d) => ItemRef::TraitDecl(d),
182            ItemRefMut::TraitImpl(d) => ItemRef::TraitImpl(d),
183        }
184    }
185    pub fn reborrow(&mut self) -> ItemRefMut<'_> {
186        match self {
187            ItemRefMut::Type(d) => ItemRefMut::Type(d),
188            ItemRefMut::Fun(d) => ItemRefMut::Fun(d),
189            ItemRefMut::Global(d) => ItemRefMut::Global(d),
190            ItemRefMut::TraitDecl(d) => ItemRefMut::TraitDecl(d),
191            ItemRefMut::TraitImpl(d) => ItemRefMut::TraitImpl(d),
192        }
193    }
194
195    pub fn set_id(&mut self, id: ItemId) {
196        match (self, id) {
197            (Self::Type(d), ItemId::Type(id)) => d.def_id = id,
198            (Self::Fun(d), ItemId::Fun(id)) => d.def_id = id,
199            (Self::Global(d), ItemId::Global(id)) => d.def_id = id,
200            (Self::TraitDecl(d), ItemId::TraitDecl(id)) => d.def_id = id,
201            (Self::TraitImpl(d), ItemId::TraitImpl(id)) => d.def_id = id,
202            _ => unreachable!(),
203        }
204    }
205
206    pub fn item_meta(&mut self) -> &mut ItemMeta {
207        match self {
208            Self::Type(d) => &mut d.item_meta,
209            Self::Fun(d) => &mut d.item_meta,
210            Self::Global(d) => &mut d.item_meta,
211            Self::TraitDecl(d) => &mut d.item_meta,
212            Self::TraitImpl(d) => &mut d.item_meta,
213        }
214    }
215    /// The generic parameters of this item.
216    pub fn generic_params(&mut self) -> &mut GenericParams {
217        match self {
218            ItemRefMut::Type(d) => &mut d.generics,
219            ItemRefMut::Fun(d) => &mut d.generics,
220            ItemRefMut::Global(d) => &mut d.generics,
221            ItemRefMut::TraitDecl(d) => &mut d.generics,
222            ItemRefMut::TraitImpl(d) => &mut d.generics,
223        }
224    }
225
226    /// We can't implement `AstVisitable` because of the `'static` constraint, but it's ok because
227    /// `ItemRefMut` isn't contained in any of our types.
228    pub fn drive_mut<V: VisitAstMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break> {
229        match self {
230            ItemRefMut::Type(d) => visitor.visit(*d),
231            ItemRefMut::Fun(d) => visitor.visit(*d),
232            ItemRefMut::Global(d) => visitor.visit(*d),
233            ItemRefMut::TraitDecl(d) => visitor.visit(*d),
234            ItemRefMut::TraitImpl(d) => visitor.visit(*d),
235        }
236    }
237
238    /// Visit all occurrences of that type inside `self`, in pre-order traversal.
239    pub fn dyn_visit_mut<T: AstVisitable>(&mut self, f: impl FnMut(&mut T)) {
240        match self {
241            ItemRefMut::Type(d) => d.dyn_visit_mut(f),
242            ItemRefMut::Fun(d) => d.dyn_visit_mut(f),
243            ItemRefMut::Global(d) => d.dyn_visit_mut(f),
244            ItemRefMut::TraitDecl(d) => d.dyn_visit_mut(f),
245            ItemRefMut::TraitImpl(d) => d.dyn_visit_mut(f),
246        }
247    }
248}