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(Debug)]
25#[derive(EnumIsA, EnumAsGetters, VariantName, VariantIndexArity)]
26#[derive(Drive, DriveMut, DriveTwo)]
27#[expect(clippy::large_enum_variant)]
28pub enum ItemByVal {
29 Type(TypeDecl),
30 Fun(FunDecl),
31 Global(GlobalDecl),
32 TraitDecl(TraitDecl),
33 TraitImpl(TraitImpl),
34}
35
36#[derive(Debug, Copy, Clone)]
38#[derive(EnumIsA, EnumAsGetters, VariantName, VariantIndexArity)]
39#[derive(Drive, DriveMut, DriveTwo)]
40pub enum ItemRef<'ctx> {
41 Type(&'ctx TypeDecl),
42 Fun(&'ctx FunDecl),
43 Global(&'ctx GlobalDecl),
44 TraitDecl(&'ctx TraitDecl),
45 TraitImpl(&'ctx TraitImpl),
46}
47
48#[derive(Debug)]
50#[derive(EnumIsA, EnumAsGetters, VariantName, VariantIndexArity)]
51#[derive(Drive, DriveMut, DriveTwo)]
52pub enum ItemRefMut<'ctx> {
53 Type(&'ctx mut TypeDecl),
54 Fun(&'ctx mut FunDecl),
55 Global(&'ctx mut GlobalDecl),
56 TraitDecl(&'ctx mut TraitDecl),
57 TraitImpl(&'ctx mut TraitImpl),
58}
59
60impl ItemByVal {
61 pub fn as_ref(&self) -> ItemRef<'_> {
62 match self {
63 Self::Type(d) => ItemRef::Type(d),
64 Self::Fun(d) => ItemRef::Fun(d),
65 Self::Global(d) => ItemRef::Global(d),
66 Self::TraitDecl(d) => ItemRef::TraitDecl(d),
67 Self::TraitImpl(d) => ItemRef::TraitImpl(d),
68 }
69 }
70 pub fn as_mut(&mut self) -> ItemRefMut<'_> {
71 match self {
72 Self::Type(d) => ItemRefMut::Type(d),
73 Self::Fun(d) => ItemRefMut::Fun(d),
74 Self::Global(d) => ItemRefMut::Global(d),
75 Self::TraitDecl(d) => ItemRefMut::TraitDecl(d),
76 Self::TraitImpl(d) => ItemRefMut::TraitImpl(d),
77 }
78 }
79}
80
81impl<'ctx> ItemRef<'ctx> {
82 pub fn id(&self) -> ItemId {
83 match self {
84 ItemRef::Type(d) => d.def_id.into(),
85 ItemRef::Fun(d) => d.def_id.into(),
86 ItemRef::Global(d) => d.def_id.into(),
87 ItemRef::TraitDecl(d) => d.def_id.into(),
88 ItemRef::TraitImpl(d) => d.def_id.into(),
89 }
90 }
91
92 pub fn to_owned(&self) -> ItemByVal {
93 match *self {
94 Self::Type(d) => ItemByVal::Type(d.clone()),
95 Self::Fun(d) => ItemByVal::Fun(d.clone()),
96 Self::Global(d) => ItemByVal::Global(d.clone()),
97 Self::TraitDecl(d) => ItemByVal::TraitDecl(d.clone()),
98 Self::TraitImpl(d) => ItemByVal::TraitImpl(d.clone()),
99 }
100 }
101
102 pub fn item_meta(&self) -> &'ctx ItemMeta {
103 match self {
104 Self::Type(d) => &d.item_meta,
105 Self::Fun(d) => &d.item_meta,
106 Self::Global(d) => &d.item_meta,
107 Self::TraitDecl(d) => &d.item_meta,
108 Self::TraitImpl(d) => &d.item_meta,
109 }
110 }
111 pub fn generic_params(&self) -> &'ctx GenericParams {
113 match self {
114 ItemRef::Type(d) => &d.generics,
115 ItemRef::Fun(d) => &d.generics,
116 ItemRef::Global(d) => &d.generics,
117 ItemRef::TraitDecl(d) => &d.generics,
118 ItemRef::TraitImpl(d) => &d.generics,
119 }
120 }
121
122 pub fn identity_args(&self) -> GenericArgs {
124 self.generic_params().identity_args()
125 }
126
127 pub fn drive<V: VisitAst>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
130 match *self {
131 ItemRef::Type(d) => visitor.visit(d),
132 ItemRef::Fun(d) => visitor.visit(d),
133 ItemRef::Global(d) => visitor.visit(d),
134 ItemRef::TraitDecl(d) => visitor.visit(d),
135 ItemRef::TraitImpl(d) => visitor.visit(d),
136 }
137 }
138
139 pub fn drive_two<V: ZipAst>(&self, other: &Self, visitor: &mut V) -> ControlFlow<V::Break> {
141 struct ItemRefZipVisitor<'a, V>(&'a mut V);
143
144 impl<V: Visitor> Visitor for ItemRefZipVisitor<'_, V> {
145 type Break = V::Break;
146 }
147
148 impl<'s, 'ctx, T: AstVisitable, V: ZipAst> VisitTwo<'s, &'ctx T> for ItemRefZipVisitor<'_, V> {
149 fn visit(&mut self, left: &'s &'ctx T, right: &'s &'ctx T) -> ControlFlow<Self::Break> {
150 self.0.visit(*left, *right)
151 }
152 }
153
154 DriveTwo::drive_two_inner(self, other, &mut ItemRefZipVisitor(visitor))
155 }
156
157 pub fn dyn_visit<T: AstVisitable>(&self, f: impl FnMut(&T)) {
159 match *self {
160 ItemRef::Type(d) => d.dyn_visit(f),
161 ItemRef::Fun(d) => d.dyn_visit(f),
162 ItemRef::Global(d) => d.dyn_visit(f),
163 ItemRef::TraitDecl(d) => d.dyn_visit(f),
164 ItemRef::TraitImpl(d) => d.dyn_visit(f),
165 }
166 }
167
168 pub fn is_unsafe_to_declare(&self, krate: &TranslatedCrate) -> bool {
172 match self {
173 ItemRef::Fun(decl) => decl.is_unsafe_to_declare(krate),
174 ItemRef::Global(decl) => decl.is_unsafe_to_declare(krate),
175 ItemRef::TraitImpl(decl) => decl.is_unsafe_to_declare(krate),
176 ItemRef::Type(_) | ItemRef::TraitDecl(_) => self.item_meta().is_unsafe_to_declare(),
177 }
178 }
179}
180
181impl<'ctx> ItemRefMut<'ctx> {
182 pub fn as_ref(&self) -> ItemRef<'_> {
183 match self {
184 ItemRefMut::Type(d) => ItemRef::Type(d),
185 ItemRefMut::Fun(d) => ItemRef::Fun(d),
186 ItemRefMut::Global(d) => ItemRef::Global(d),
187 ItemRefMut::TraitDecl(d) => ItemRef::TraitDecl(d),
188 ItemRefMut::TraitImpl(d) => ItemRef::TraitImpl(d),
189 }
190 }
191 pub fn reborrow(&mut self) -> ItemRefMut<'_> {
192 match self {
193 ItemRefMut::Type(d) => ItemRefMut::Type(d),
194 ItemRefMut::Fun(d) => ItemRefMut::Fun(d),
195 ItemRefMut::Global(d) => ItemRefMut::Global(d),
196 ItemRefMut::TraitDecl(d) => ItemRefMut::TraitDecl(d),
197 ItemRefMut::TraitImpl(d) => ItemRefMut::TraitImpl(d),
198 }
199 }
200
201 pub fn set_id(&mut self, id: ItemId) {
202 match (self, id) {
203 (Self::Type(d), ItemId::Type(id)) => d.def_id = id,
204 (Self::Fun(d), ItemId::Fun(id)) => d.def_id = id,
205 (Self::Global(d), ItemId::Global(id)) => d.def_id = id,
206 (Self::TraitDecl(d), ItemId::TraitDecl(id)) => d.def_id = id,
207 (Self::TraitImpl(d), ItemId::TraitImpl(id)) => d.def_id = id,
208 _ => unreachable!(),
209 }
210 }
211
212 pub fn item_meta(&mut self) -> &mut ItemMeta {
213 match self {
214 Self::Type(d) => &mut d.item_meta,
215 Self::Fun(d) => &mut d.item_meta,
216 Self::Global(d) => &mut d.item_meta,
217 Self::TraitDecl(d) => &mut d.item_meta,
218 Self::TraitImpl(d) => &mut d.item_meta,
219 }
220 }
221 pub fn generic_params(&mut self) -> &mut GenericParams {
223 match self {
224 ItemRefMut::Type(d) => &mut d.generics,
225 ItemRefMut::Fun(d) => &mut d.generics,
226 ItemRefMut::Global(d) => &mut d.generics,
227 ItemRefMut::TraitDecl(d) => &mut d.generics,
228 ItemRefMut::TraitImpl(d) => &mut d.generics,
229 }
230 }
231
232 pub fn drive_mut<V: VisitAstMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break> {
235 match self {
236 ItemRefMut::Type(d) => visitor.visit(*d),
237 ItemRefMut::Fun(d) => visitor.visit(*d),
238 ItemRefMut::Global(d) => visitor.visit(*d),
239 ItemRefMut::TraitDecl(d) => visitor.visit(*d),
240 ItemRefMut::TraitImpl(d) => visitor.visit(*d),
241 }
242 }
243
244 pub fn dyn_visit_mut<T: AstVisitable>(&mut self, f: impl FnMut(&mut T)) {
246 match self {
247 ItemRefMut::Type(d) => d.dyn_visit_mut(f),
248 ItemRefMut::Fun(d) => d.dyn_visit_mut(f),
249 ItemRefMut::Global(d) => d.dyn_visit_mut(f),
250 ItemRefMut::TraitDecl(d) => d.dyn_visit_mut(f),
251 ItemRefMut::TraitImpl(d) => d.dyn_visit_mut(f),
252 }
253 }
254}