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