1use std::cmp::{Ord, PartialOrd};
2use std::fmt;
3
4use derive_generic_visitor::{ControlFlow, Drive, DriveMut};
5use index_vec::Idx;
6use indexmap::IndexMap;
7use serde::{Deserialize, Serialize};
8use serde_state::{DeserializeState, SerializeState};
9
10use crate::ast::*;
11use crate::common::serialize_map_to_array::IndexMapToArray;
12use crate::formatter::{FmtCtx, IntoFormatter};
13use crate::ids::Vector;
14use crate::pretty::FmtWithCtx;
15use macros::{EnumAsGetters, EnumIsA, VariantIndexArity, VariantName};
16
17generate_index_type!(FunDeclId, "Fun");
18generate_index_type!(TypeDeclId, "Adt");
19generate_index_type!(GlobalDeclId, "Global");
20generate_index_type!(TraitDeclId, "TraitDecl");
21generate_index_type!(TraitImplId, "TraitImpl");
22
23#[derive(
25 Copy,
26 Clone,
27 Debug,
28 PartialOrd,
29 Ord,
30 PartialEq,
31 Eq,
32 Hash,
33 EnumIsA,
34 EnumAsGetters,
35 VariantName,
36 VariantIndexArity,
37 Serialize,
38 Deserialize,
39 SerializeState,
40 DeserializeState,
41 Drive,
42 DriveMut,
43)]
44#[charon::variants_prefix("Id")]
45#[serde_state(stateless)]
46pub enum ItemId {
47 Type(TypeDeclId),
48 Fun(FunDeclId),
49 Global(GlobalDeclId),
50 TraitDecl(TraitDeclId),
51 TraitImpl(TraitImplId),
52}
53
54macro_rules! wrap_unwrap_enum {
56 ($enum:ident::$variant:ident($variant_ty:ident)) => {
57 impl TryFrom<$enum> for $variant_ty {
58 type Error = ();
59 fn try_from(x: $enum) -> Result<Self, Self::Error> {
60 match x {
61 $enum::$variant(x) => Ok(x),
62 _ => Err(()),
63 }
64 }
65 }
66
67 impl From<$variant_ty> for $enum {
68 fn from(x: $variant_ty) -> Self {
69 $enum::$variant(x)
70 }
71 }
72 };
73}
74
75wrap_unwrap_enum!(ItemId::Fun(FunDeclId));
76wrap_unwrap_enum!(ItemId::Global(GlobalDeclId));
77wrap_unwrap_enum!(ItemId::Type(TypeDeclId));
78wrap_unwrap_enum!(ItemId::TraitDecl(TraitDeclId));
79wrap_unwrap_enum!(ItemId::TraitImpl(TraitImplId));
80impl TryFrom<ItemId> for TypeId {
81 type Error = ();
82 fn try_from(x: ItemId) -> Result<Self, Self::Error> {
83 Ok(TypeId::Adt(x.try_into()?))
84 }
85}
86impl TryFrom<ItemId> for FunId {
87 type Error = ();
88 fn try_from(x: ItemId) -> Result<Self, Self::Error> {
89 Ok(FunId::Regular(x.try_into()?))
90 }
91}
92
93#[derive(Debug, EnumIsA, EnumAsGetters, VariantName, VariantIndexArity, Drive, DriveMut)]
95pub enum ItemByVal {
96 Type(TypeDecl),
97 Fun(FunDecl),
98 Global(GlobalDecl),
99 TraitDecl(TraitDecl),
100 TraitImpl(TraitImpl),
101}
102
103#[derive(
105 Debug, Clone, Copy, EnumIsA, EnumAsGetters, VariantName, VariantIndexArity, Drive, DriveMut,
106)]
107pub enum ItemRef<'ctx> {
108 Type(&'ctx TypeDecl),
109 Fun(&'ctx FunDecl),
110 Global(&'ctx GlobalDecl),
111 TraitDecl(&'ctx TraitDecl),
112 TraitImpl(&'ctx TraitImpl),
113}
114
115#[derive(Debug, EnumIsA, EnumAsGetters, VariantName, VariantIndexArity, Drive, DriveMut)]
117pub enum ItemRefMut<'ctx> {
118 Type(&'ctx mut TypeDecl),
119 Fun(&'ctx mut FunDecl),
120 Global(&'ctx mut GlobalDecl),
121 TraitDecl(&'ctx mut TraitDecl),
122 TraitImpl(&'ctx mut TraitImpl),
123}
124
125#[derive(
128 Debug, Clone, VariantIndexArity, VariantName, EnumAsGetters, EnumIsA, Serialize, Deserialize,
129)]
130#[charon::variants_suffix("Group")]
131pub enum GDeclarationGroup<Id> {
132 NonRec(Id),
134 Rec(Vec<Id>),
136}
137
138#[derive(
140 Debug, Clone, VariantIndexArity, VariantName, EnumAsGetters, EnumIsA, Serialize, Deserialize,
141)]
142#[charon::variants_suffix("Group")]
143pub enum DeclarationGroup {
144 Type(GDeclarationGroup<TypeDeclId>),
146 Fun(GDeclarationGroup<FunDeclId>),
148 Global(GDeclarationGroup<GlobalDeclId>),
150 TraitDecl(GDeclarationGroup<TraitDeclId>),
152 TraitImpl(GDeclarationGroup<TraitImplId>),
154 Mixed(GDeclarationGroup<ItemId>),
156}
157
158pub type DeclarationsGroups = Vec<DeclarationGroup>;
159
160#[derive(Default, Clone, Drive, DriveMut, Serialize, Deserialize)]
161pub struct TargetInfo {
162 pub target_pointer_size: types::ByteCount,
164 pub is_little_endian: bool,
166}
167
168#[derive(Default, Clone, Drive, DriveMut, SerializeState, DeserializeState)]
170#[serde_state(state_implements = HashConsSerializerState)]
171pub struct TranslatedCrate {
172 #[drive(skip)]
174 pub crate_name: String,
175
176 #[drive(skip)]
180 #[serde_state(stateless)]
181 pub options: crate::options::CliOpts,
182
183 #[drive(skip)]
185 #[serde_state(stateless)]
186 pub target_information: TargetInfo,
187
188 #[serde(with = "IndexMapToArray::<ItemId, Name>")]
193 pub item_names: IndexMap<ItemId, Name>,
194 #[serde(with = "IndexMapToArray::<ItemId, Name>")]
196 pub short_names: IndexMap<ItemId, Name>,
197
198 #[drive(skip)]
200 #[serde_state(stateless)]
201 pub files: Vector<FileId, File>,
202 pub type_decls: Vector<TypeDeclId, TypeDecl>,
204 pub fun_decls: Vector<FunDeclId, FunDecl>,
206 pub global_decls: Vector<GlobalDeclId, GlobalDecl>,
208 pub trait_decls: Vector<TraitDeclId, TraitDecl>,
210 pub trait_impls: Vector<TraitImplId, TraitImpl>,
212 pub unit_metadata: Option<GlobalDeclRef>,
215 #[drive(skip)]
217 #[serde_state(stateless)]
218 pub ordered_decls: Option<DeclarationsGroups>,
219}
220
221impl TranslatedCrate {
222 pub fn item_name(&self, id: impl Into<ItemId>) -> Option<&Name> {
223 self.item_names.get(&id.into())
224 }
225
226 pub fn item_short_name(&self, id: impl Into<ItemId>) -> Option<&Name> {
227 let id = id.into();
228 self.short_names.get(&id).or_else(|| self.item_name(id))
229 }
230
231 pub fn get_item(&self, trans_id: impl Into<ItemId>) -> Option<ItemRef<'_>> {
232 match trans_id.into() {
233 ItemId::Type(id) => self.type_decls.get(id).map(ItemRef::Type),
234 ItemId::Fun(id) => self.fun_decls.get(id).map(ItemRef::Fun),
235 ItemId::Global(id) => self.global_decls.get(id).map(ItemRef::Global),
236 ItemId::TraitDecl(id) => self.trait_decls.get(id).map(ItemRef::TraitDecl),
237 ItemId::TraitImpl(id) => self.trait_impls.get(id).map(ItemRef::TraitImpl),
238 }
239 }
240 pub fn get_item_mut(&mut self, trans_id: ItemId) -> Option<ItemRefMut<'_>> {
241 match trans_id {
242 ItemId::Type(id) => self.type_decls.get_mut(id).map(ItemRefMut::Type),
243 ItemId::Fun(id) => self.fun_decls.get_mut(id).map(ItemRefMut::Fun),
244 ItemId::Global(id) => self.global_decls.get_mut(id).map(ItemRefMut::Global),
245 ItemId::TraitDecl(id) => self.trait_decls.get_mut(id).map(ItemRefMut::TraitDecl),
246 ItemId::TraitImpl(id) => self.trait_impls.get_mut(id).map(ItemRefMut::TraitImpl),
247 }
248 }
249 pub fn remove_item(&mut self, trans_id: ItemId) -> Option<ItemByVal> {
250 match trans_id {
251 ItemId::Type(id) => self.type_decls.remove(id).map(ItemByVal::Type),
252 ItemId::Fun(id) => self.fun_decls.remove(id).map(ItemByVal::Fun),
253 ItemId::Global(id) => self.global_decls.remove(id).map(ItemByVal::Global),
254 ItemId::TraitDecl(id) => self.trait_decls.remove(id).map(ItemByVal::TraitDecl),
255 ItemId::TraitImpl(id) => self.trait_impls.remove(id).map(ItemByVal::TraitImpl),
256 }
257 }
258 pub fn set_item_slot(&mut self, id: ItemId, item: ItemByVal) {
259 match item {
260 ItemByVal::Type(decl) => self.type_decls.set_slot(*id.as_type().unwrap(), decl),
261 ItemByVal::Fun(decl) => self.fun_decls.set_slot(*id.as_fun().unwrap(), decl),
262 ItemByVal::Global(decl) => self.global_decls.set_slot(*id.as_global().unwrap(), decl),
263 ItemByVal::TraitDecl(decl) => self
264 .trait_decls
265 .set_slot(*id.as_trait_decl().unwrap(), decl),
266 ItemByVal::TraitImpl(decl) => self
267 .trait_impls
268 .set_slot(*id.as_trait_impl().unwrap(), decl),
269 }
270 }
271
272 pub fn all_ids(&self) -> impl Iterator<Item = ItemId> + use<> {
273 self.type_decls
274 .all_indices()
275 .map(ItemId::Type)
276 .chain(self.trait_decls.all_indices().map(ItemId::TraitDecl))
277 .chain(self.trait_impls.all_indices().map(ItemId::TraitImpl))
278 .chain(self.global_decls.all_indices().map(ItemId::Global))
279 .chain(self.fun_decls.all_indices().map(ItemId::Fun))
280 }
281 pub fn all_items(&self) -> impl Iterator<Item = ItemRef<'_>> {
282 self.type_decls
283 .iter()
284 .map(ItemRef::Type)
285 .chain(self.trait_decls.iter().map(ItemRef::TraitDecl))
286 .chain(self.trait_impls.iter().map(ItemRef::TraitImpl))
287 .chain(self.global_decls.iter().map(ItemRef::Global))
288 .chain(self.fun_decls.iter().map(ItemRef::Fun))
289 }
290 pub fn all_items_mut(&mut self) -> impl Iterator<Item = ItemRefMut<'_>> {
291 self.type_decls
292 .iter_mut()
293 .map(ItemRefMut::Type)
294 .chain(self.trait_impls.iter_mut().map(ItemRefMut::TraitImpl))
295 .chain(self.trait_decls.iter_mut().map(ItemRefMut::TraitDecl))
296 .chain(self.fun_decls.iter_mut().map(ItemRefMut::Fun))
297 .chain(self.global_decls.iter_mut().map(ItemRefMut::Global))
298 }
299 pub fn all_items_with_ids(&self) -> impl Iterator<Item = (ItemId, ItemRef<'_>)> {
300 self.all_items().map(|item| (item.id(), item))
301 }
302}
303
304impl ItemByVal {
305 pub fn as_ref(&self) -> ItemRef<'_> {
306 match self {
307 Self::Type(d) => ItemRef::Type(d),
308 Self::Fun(d) => ItemRef::Fun(d),
309 Self::Global(d) => ItemRef::Global(d),
310 Self::TraitDecl(d) => ItemRef::TraitDecl(d),
311 Self::TraitImpl(d) => ItemRef::TraitImpl(d),
312 }
313 }
314 pub fn as_mut(&mut self) -> ItemRefMut<'_> {
315 match self {
316 Self::Type(d) => ItemRefMut::Type(d),
317 Self::Fun(d) => ItemRefMut::Fun(d),
318 Self::Global(d) => ItemRefMut::Global(d),
319 Self::TraitDecl(d) => ItemRefMut::TraitDecl(d),
320 Self::TraitImpl(d) => ItemRefMut::TraitImpl(d),
321 }
322 }
323}
324
325impl<'ctx> ItemRef<'ctx> {
326 pub fn id(&self) -> ItemId {
327 match self {
328 ItemRef::Type(d) => d.def_id.into(),
329 ItemRef::Fun(d) => d.def_id.into(),
330 ItemRef::Global(d) => d.def_id.into(),
331 ItemRef::TraitDecl(d) => d.def_id.into(),
332 ItemRef::TraitImpl(d) => d.def_id.into(),
333 }
334 }
335
336 pub fn clone(&self) -> ItemByVal {
337 match *self {
338 Self::Type(d) => ItemByVal::Type(d.clone()),
339 Self::Fun(d) => ItemByVal::Fun(d.clone()),
340 Self::Global(d) => ItemByVal::Global(d.clone()),
341 Self::TraitDecl(d) => ItemByVal::TraitDecl(d.clone()),
342 Self::TraitImpl(d) => ItemByVal::TraitImpl(d.clone()),
343 }
344 }
345
346 pub fn item_meta(&self) -> &'ctx ItemMeta {
347 match self {
348 Self::Type(d) => &d.item_meta,
349 Self::Fun(d) => &d.item_meta,
350 Self::Global(d) => &d.item_meta,
351 Self::TraitDecl(d) => &d.item_meta,
352 Self::TraitImpl(d) => &d.item_meta,
353 }
354 }
355 pub fn generic_params(&self) -> &'ctx GenericParams {
357 match self {
358 ItemRef::Type(d) => &d.generics,
359 ItemRef::Fun(d) => &d.signature.generics,
360 ItemRef::Global(d) => &d.generics,
361 ItemRef::TraitDecl(d) => &d.generics,
362 ItemRef::TraitImpl(d) => &d.generics,
363 }
364 }
365
366 pub fn parent_info(&self) -> &'ctx ItemSource {
368 match self {
369 ItemRef::Fun(d) => &d.src,
370 ItemRef::Global(d) => &d.src,
371 ItemRef::Type(_) | ItemRef::TraitDecl(_) | ItemRef::TraitImpl(_) => {
372 &ItemSource::TopLevel
373 }
374 }
375 }
376
377 pub fn identity_args(&self) -> GenericArgs {
379 self.generic_params().identity_args()
380 }
381
382 pub fn drive<V: VisitAst>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
385 match *self {
386 ItemRef::Type(d) => visitor.visit(d),
387 ItemRef::Fun(d) => visitor.visit(d),
388 ItemRef::Global(d) => visitor.visit(d),
389 ItemRef::TraitDecl(d) => visitor.visit(d),
390 ItemRef::TraitImpl(d) => visitor.visit(d),
391 }
392 }
393
394 pub fn dyn_visit<T: AstVisitable>(&self, f: impl FnMut(&T)) {
396 match *self {
397 ItemRef::Type(d) => d.dyn_visit(f),
398 ItemRef::Fun(d) => d.dyn_visit(f),
399 ItemRef::Global(d) => d.dyn_visit(f),
400 ItemRef::TraitDecl(d) => d.dyn_visit(f),
401 ItemRef::TraitImpl(d) => d.dyn_visit(f),
402 }
403 }
404}
405
406impl<'ctx> ItemRefMut<'ctx> {
407 pub fn as_ref(&self) -> ItemRef<'_> {
408 match self {
409 ItemRefMut::Type(d) => ItemRef::Type(d),
410 ItemRefMut::Fun(d) => ItemRef::Fun(d),
411 ItemRefMut::Global(d) => ItemRef::Global(d),
412 ItemRefMut::TraitDecl(d) => ItemRef::TraitDecl(d),
413 ItemRefMut::TraitImpl(d) => ItemRef::TraitImpl(d),
414 }
415 }
416 pub fn reborrow(&mut self) -> ItemRefMut<'_> {
417 match self {
418 ItemRefMut::Type(d) => ItemRefMut::Type(d),
419 ItemRefMut::Fun(d) => ItemRefMut::Fun(d),
420 ItemRefMut::Global(d) => ItemRefMut::Global(d),
421 ItemRefMut::TraitDecl(d) => ItemRefMut::TraitDecl(d),
422 ItemRefMut::TraitImpl(d) => ItemRefMut::TraitImpl(d),
423 }
424 }
425
426 pub fn set_id(&mut self, id: ItemId) {
427 match (self, id) {
428 (Self::Type(d), ItemId::Type(id)) => d.def_id = id,
429 (Self::Fun(d), ItemId::Fun(id)) => d.def_id = id,
430 (Self::Global(d), ItemId::Global(id)) => d.def_id = id,
431 (Self::TraitDecl(d), ItemId::TraitDecl(id)) => d.def_id = id,
432 (Self::TraitImpl(d), ItemId::TraitImpl(id)) => d.def_id = id,
433 _ => unreachable!(),
434 }
435 }
436
437 pub fn item_meta(&mut self) -> &mut ItemMeta {
438 match self {
439 Self::Type(d) => &mut d.item_meta,
440 Self::Fun(d) => &mut d.item_meta,
441 Self::Global(d) => &mut d.item_meta,
442 Self::TraitDecl(d) => &mut d.item_meta,
443 Self::TraitImpl(d) => &mut d.item_meta,
444 }
445 }
446 pub fn generic_params(&mut self) -> &mut GenericParams {
448 match self {
449 ItemRefMut::Type(d) => &mut d.generics,
450 ItemRefMut::Fun(d) => &mut d.signature.generics,
451 ItemRefMut::Global(d) => &mut d.generics,
452 ItemRefMut::TraitDecl(d) => &mut d.generics,
453 ItemRefMut::TraitImpl(d) => &mut d.generics,
454 }
455 }
456
457 pub fn drive_mut<V: VisitAstMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break> {
460 match self {
461 ItemRefMut::Type(d) => visitor.visit(*d),
462 ItemRefMut::Fun(d) => visitor.visit(*d),
463 ItemRefMut::Global(d) => visitor.visit(*d),
464 ItemRefMut::TraitDecl(d) => visitor.visit(*d),
465 ItemRefMut::TraitImpl(d) => visitor.visit(*d),
466 }
467 }
468
469 pub fn dyn_visit_mut<T: AstVisitable>(&mut self, f: impl FnMut(&mut T)) {
471 match self {
472 ItemRefMut::Type(d) => d.dyn_visit_mut(f),
473 ItemRefMut::Fun(d) => d.dyn_visit_mut(f),
474 ItemRefMut::Global(d) => d.dyn_visit_mut(f),
475 ItemRefMut::TraitDecl(d) => d.dyn_visit_mut(f),
476 ItemRefMut::TraitImpl(d) => d.dyn_visit_mut(f),
477 }
478 }
479}
480
481impl fmt::Display for TranslatedCrate {
482 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
483 let fmt: &FmtCtx = &self.into_fmt();
484 match &self.ordered_decls {
485 None => {
486 for d in &self.type_decls {
488 writeln!(f, "{}\n", d.with_ctx(fmt))?
489 }
490 for d in &self.global_decls {
491 writeln!(f, "{}\n", d.with_ctx(fmt))?
492 }
493 for d in &self.trait_decls {
494 writeln!(f, "{}\n", d.with_ctx(fmt))?
495 }
496 for d in &self.trait_impls {
497 writeln!(f, "{}\n", d.with_ctx(fmt))?
498 }
499 for d in &self.fun_decls {
500 writeln!(f, "{}\n", d.with_ctx(fmt))?
501 }
502 }
503 Some(ordered_decls) => {
504 for gr in ordered_decls {
505 for id in gr.get_ids() {
506 writeln!(f, "{}\n", fmt.format_decl_id(id))?
507 }
508 }
509 }
510 }
511 fmt::Result::Ok(())
512 }
513}
514
515impl<'tcx, 'ctx, 'a> IntoFormatter for &'a TranslatedCrate {
516 type C = FmtCtx<'a>;
517
518 fn into_fmt(self) -> Self::C {
519 FmtCtx {
520 translated: Some(self),
521 ..Default::default()
522 }
523 }
524}
525
526pub trait HasVectorOf<Id: Idx>: std::ops::Index<Id, Output: Sized> {
527 fn get_vector(&self) -> &Vector<Id, Self::Output>;
528 fn get_vector_mut(&mut self) -> &mut Vector<Id, Self::Output>;
529}
530
531macro_rules! mk_index_impls {
533 ($ty:ident.$field:ident[$idx:ty]: $output:ty) => {
534 impl std::ops::Index<$idx> for $ty {
535 type Output = $output;
536 fn index(&self, index: $idx) -> &Self::Output {
537 &self.$field[index]
538 }
539 }
540 impl std::ops::IndexMut<$idx> for $ty {
541 fn index_mut(&mut self, index: $idx) -> &mut Self::Output {
542 &mut self.$field[index]
543 }
544 }
545 impl HasVectorOf<$idx> for $ty {
546 fn get_vector(&self) -> &Vector<$idx, Self::Output> {
547 &self.$field
548 }
549 fn get_vector_mut(&mut self) -> &mut Vector<$idx, Self::Output> {
550 &mut self.$field
551 }
552 }
553 };
554}
555pub(crate) use mk_index_impls;
556
557mk_index_impls!(TranslatedCrate.type_decls[TypeDeclId]: TypeDecl);
558mk_index_impls!(TranslatedCrate.fun_decls[FunDeclId]: FunDecl);
559mk_index_impls!(TranslatedCrate.global_decls[GlobalDeclId]: GlobalDecl);
560mk_index_impls!(TranslatedCrate.trait_decls[TraitDeclId]: TraitDecl);
561mk_index_impls!(TranslatedCrate.trait_impls[TraitImplId]: TraitImpl);