1use std::cmp::{Ord, PartialOrd};
2use std::fmt;
3
4use derive_generic_visitor::{ControlFlow, Drive, DriveMut};
5use index_vec::Idx;
6use itertools::Itertools;
7use serde::{Deserialize, Serialize};
8use serde_state::{DeserializeState, SerializeState};
9
10use crate::ast::*;
11use crate::common::serialize_map_to_array::SeqHashMapToArray;
12use crate::formatter::{FmtCtx, IntoFormatter};
13use crate::ids::{IndexMap, IndexVec};
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 TraitDecl(TraitDeclId),
49 TraitImpl(TraitImplId),
50 Fun(FunDeclId),
51 Global(GlobalDeclId),
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(
95 Debug, PartialEq, Eq, EnumIsA, EnumAsGetters, VariantName, VariantIndexArity, Drive, DriveMut,
96)]
97pub enum ItemByVal {
98 Type(TypeDecl),
99 Fun(FunDecl),
100 Global(GlobalDecl),
101 TraitDecl(TraitDecl),
102 TraitImpl(TraitImpl),
103}
104
105#[derive(
107 Debug, Clone, Copy, EnumIsA, EnumAsGetters, VariantName, VariantIndexArity, Drive, DriveMut,
108)]
109pub enum ItemRef<'ctx> {
110 Type(&'ctx TypeDecl),
111 Fun(&'ctx FunDecl),
112 Global(&'ctx GlobalDecl),
113 TraitDecl(&'ctx TraitDecl),
114 TraitImpl(&'ctx TraitImpl),
115}
116
117#[derive(
119 Debug, PartialEq, Eq, EnumIsA, EnumAsGetters, VariantName, VariantIndexArity, Drive, DriveMut,
120)]
121pub enum ItemRefMut<'ctx> {
122 Type(&'ctx mut TypeDecl),
123 Fun(&'ctx mut FunDecl),
124 Global(&'ctx mut GlobalDecl),
125 TraitDecl(&'ctx mut TraitDecl),
126 TraitImpl(&'ctx mut TraitImpl),
127}
128
129#[derive(
132 Debug, Clone, VariantIndexArity, VariantName, EnumAsGetters, EnumIsA, Serialize, Deserialize,
133)]
134#[charon::variants_suffix("Group")]
135pub enum GDeclarationGroup<Id> {
136 NonRec(Id),
138 Rec(Vec<Id>),
140}
141
142#[derive(
144 Debug, Clone, VariantIndexArity, VariantName, EnumAsGetters, EnumIsA, Serialize, Deserialize,
145)]
146#[charon::variants_suffix("Group")]
147pub enum DeclarationGroup {
148 Type(GDeclarationGroup<TypeDeclId>),
150 Fun(GDeclarationGroup<FunDeclId>),
152 Global(GDeclarationGroup<GlobalDeclId>),
154 TraitDecl(GDeclarationGroup<TraitDeclId>),
155 TraitImpl(GDeclarationGroup<TraitImplId>),
156 Mixed(GDeclarationGroup<ItemId>),
158}
159
160pub type DeclarationsGroups = Vec<DeclarationGroup>;
161
162pub type TargetTriple = String;
164
165#[derive(Clone, Drive, DriveMut, SerializeState, DeserializeState)]
166#[serde_state(stateless)]
167pub struct TargetInfo {
168 pub target_pointer_size: types::ByteCount,
170 pub is_little_endian: bool,
172}
173
174#[derive(Default, Clone, Drive, DriveMut, SerializeState, DeserializeState)]
176#[serde_state(state_implements = HashConsSerializerState)]
177pub struct TranslatedCrate {
178 #[drive(skip)]
180 pub crate_name: String,
181
182 #[drive(skip)]
186 #[serde_state(stateless)]
187 pub options: crate::options::CliOpts,
188
189 #[drive(skip)]
192 #[serde(with = "SeqHashMapToArray::<TargetTriple, TargetInfo>")]
193 pub target_information: SeqHashMap<TargetTriple, TargetInfo>,
194
195 #[serde(with = "SeqHashMapToArray::<ItemId, Name>")]
200 pub item_names: SeqHashMap<ItemId, Name>,
201 #[serde(with = "SeqHashMapToArray::<ItemId, Name>")]
203 pub short_names: SeqHashMap<ItemId, Name>,
204
205 #[drive(skip)]
207 #[serde_state(stateless)]
208 pub files: IndexVec<FileId, File>,
209 pub type_decls: IndexMap<TypeDeclId, TypeDecl>,
211 pub fun_decls: IndexMap<FunDeclId, FunDecl>,
213 pub global_decls: IndexMap<GlobalDeclId, GlobalDecl>,
215 pub trait_decls: IndexMap<TraitDeclId, TraitDecl>,
217 pub trait_impls: IndexMap<TraitImplId, TraitImpl>,
219 pub unit_metadata: Option<GlobalDeclRef>,
222 #[drive(skip)]
224 #[serde_state(stateless)]
225 pub ordered_decls: Option<DeclarationsGroups>,
226}
227
228impl TranslatedCrate {
229 pub fn item_name(&self, id: impl Into<ItemId>) -> Option<&Name> {
230 self.item_names.get(&id.into())
231 }
232
233 pub fn item_short_name(&self, id: impl Into<ItemId>) -> Option<&Name> {
234 let id = id.into();
235 self.short_names.get(&id).or_else(|| self.item_name(id))
236 }
237
238 pub fn get_item(&self, trans_id: impl Into<ItemId>) -> Option<ItemRef<'_>> {
239 match trans_id.into() {
240 ItemId::Type(id) => self.type_decls.get(id).map(ItemRef::Type),
241 ItemId::Fun(id) => self.fun_decls.get(id).map(ItemRef::Fun),
242 ItemId::Global(id) => self.global_decls.get(id).map(ItemRef::Global),
243 ItemId::TraitDecl(id) => self.trait_decls.get(id).map(ItemRef::TraitDecl),
244 ItemId::TraitImpl(id) => self.trait_impls.get(id).map(ItemRef::TraitImpl),
245 }
246 }
247 pub fn get_item_mut(&mut self, trans_id: ItemId) -> Option<ItemRefMut<'_>> {
248 match trans_id {
249 ItemId::Type(id) => self.type_decls.get_mut(id).map(ItemRefMut::Type),
250 ItemId::Fun(id) => self.fun_decls.get_mut(id).map(ItemRefMut::Fun),
251 ItemId::Global(id) => self.global_decls.get_mut(id).map(ItemRefMut::Global),
252 ItemId::TraitDecl(id) => self.trait_decls.get_mut(id).map(ItemRefMut::TraitDecl),
253 ItemId::TraitImpl(id) => self.trait_impls.get_mut(id).map(ItemRefMut::TraitImpl),
254 }
255 }
256 pub fn remove_item(&mut self, trans_id: ItemId) -> Option<ItemByVal> {
257 self.short_names.swap_remove(&trans_id);
258 self.item_names.swap_remove(&trans_id);
259 self.remove_item_temporarily(trans_id)
260 }
261 pub fn remove_item_temporarily(&mut self, trans_id: ItemId) -> Option<ItemByVal> {
263 match trans_id {
264 ItemId::Type(id) => self.type_decls.remove(id).map(ItemByVal::Type),
265 ItemId::Fun(id) => self.fun_decls.remove(id).map(ItemByVal::Fun),
266 ItemId::Global(id) => self.global_decls.remove(id).map(ItemByVal::Global),
267 ItemId::TraitDecl(id) => self.trait_decls.remove(id).map(ItemByVal::TraitDecl),
268 ItemId::TraitImpl(id) => self.trait_impls.remove(id).map(ItemByVal::TraitImpl),
269 }
270 }
271 pub fn set_new_item_slot(&mut self, id: ItemId, item: impl Into<ItemByVal>) {
273 let item = item.into();
274 self.item_names
275 .insert(id, item.as_ref().item_meta().name.clone());
276 self.set_item_slot(id, item);
277 }
278 pub fn set_item_slot(&mut self, id: ItemId, item: impl Into<ItemByVal>) {
280 match item.into() {
281 ItemByVal::Type(decl) => self.type_decls.set_slot(*id.as_type().unwrap(), decl),
282 ItemByVal::Fun(decl) => self.fun_decls.set_slot(*id.as_fun().unwrap(), decl),
283 ItemByVal::Global(decl) => self.global_decls.set_slot(*id.as_global().unwrap(), decl),
284 ItemByVal::TraitDecl(decl) => self
285 .trait_decls
286 .set_slot(*id.as_trait_decl().unwrap(), decl),
287 ItemByVal::TraitImpl(decl) => self
288 .trait_impls
289 .set_slot(*id.as_trait_impl().unwrap(), decl),
290 }
291 }
292
293 pub fn all_ids(&self) -> impl Iterator<Item = ItemId> + use<> {
294 self.type_decls
295 .all_indices()
296 .map(ItemId::Type)
297 .chain(self.trait_decls.all_indices().map(ItemId::TraitDecl))
298 .chain(self.trait_impls.all_indices().map(ItemId::TraitImpl))
299 .chain(self.global_decls.all_indices().map(ItemId::Global))
300 .chain(self.fun_decls.all_indices().map(ItemId::Fun))
301 }
302 pub fn all_items(&self) -> impl Iterator<Item = ItemRef<'_>> {
303 self.type_decls
304 .iter()
305 .map(ItemRef::Type)
306 .chain(self.trait_decls.iter().map(ItemRef::TraitDecl))
307 .chain(self.trait_impls.iter().map(ItemRef::TraitImpl))
308 .chain(self.global_decls.iter().map(ItemRef::Global))
309 .chain(self.fun_decls.iter().map(ItemRef::Fun))
310 }
311 pub fn all_items_mut(&mut self) -> impl Iterator<Item = ItemRefMut<'_>> {
312 self.type_decls
313 .iter_mut()
314 .map(ItemRefMut::Type)
315 .chain(self.trait_impls.iter_mut().map(ItemRefMut::TraitImpl))
316 .chain(self.trait_decls.iter_mut().map(ItemRefMut::TraitDecl))
317 .chain(self.fun_decls.iter_mut().map(ItemRefMut::Fun))
318 .chain(self.global_decls.iter_mut().map(ItemRefMut::Global))
319 }
320 pub fn all_items_with_ids(&self) -> impl Iterator<Item = (ItemId, ItemRef<'_>)> {
321 self.all_items().map(|item| (item.id(), item))
322 }
323
324 pub fn the_target_information(&self) -> &TargetInfo {
327 self.target_information
328 .values()
329 .exactly_one()
330 .ok()
331 .expect("called `the_target_information` on a multi-target crate")
332 }
333}
334
335impl ItemByVal {
336 pub fn as_ref(&self) -> ItemRef<'_> {
337 match self {
338 Self::Type(d) => ItemRef::Type(d),
339 Self::Fun(d) => ItemRef::Fun(d),
340 Self::Global(d) => ItemRef::Global(d),
341 Self::TraitDecl(d) => ItemRef::TraitDecl(d),
342 Self::TraitImpl(d) => ItemRef::TraitImpl(d),
343 }
344 }
345 pub fn as_mut(&mut self) -> ItemRefMut<'_> {
346 match self {
347 Self::Type(d) => ItemRefMut::Type(d),
348 Self::Fun(d) => ItemRefMut::Fun(d),
349 Self::Global(d) => ItemRefMut::Global(d),
350 Self::TraitDecl(d) => ItemRefMut::TraitDecl(d),
351 Self::TraitImpl(d) => ItemRefMut::TraitImpl(d),
352 }
353 }
354}
355
356impl<'ctx> ItemRef<'ctx> {
357 pub fn id(&self) -> ItemId {
358 match self {
359 ItemRef::Type(d) => d.def_id.into(),
360 ItemRef::Fun(d) => d.def_id.into(),
361 ItemRef::Global(d) => d.def_id.into(),
362 ItemRef::TraitDecl(d) => d.def_id.into(),
363 ItemRef::TraitImpl(d) => d.def_id.into(),
364 }
365 }
366
367 pub fn to_owned(&self) -> ItemByVal {
368 match *self {
369 Self::Type(d) => ItemByVal::Type(d.clone()),
370 Self::Fun(d) => ItemByVal::Fun(d.clone()),
371 Self::Global(d) => ItemByVal::Global(d.clone()),
372 Self::TraitDecl(d) => ItemByVal::TraitDecl(d.clone()),
373 Self::TraitImpl(d) => ItemByVal::TraitImpl(d.clone()),
374 }
375 }
376
377 pub fn item_meta(&self) -> &'ctx ItemMeta {
378 match self {
379 Self::Type(d) => &d.item_meta,
380 Self::Fun(d) => &d.item_meta,
381 Self::Global(d) => &d.item_meta,
382 Self::TraitDecl(d) => &d.item_meta,
383 Self::TraitImpl(d) => &d.item_meta,
384 }
385 }
386 pub fn generic_params(&self) -> &'ctx GenericParams {
388 match self {
389 ItemRef::Type(d) => &d.generics,
390 ItemRef::Fun(d) => &d.generics,
391 ItemRef::Global(d) => &d.generics,
392 ItemRef::TraitDecl(d) => &d.generics,
393 ItemRef::TraitImpl(d) => &d.generics,
394 }
395 }
396
397 pub fn parent_info(&self) -> &'ctx ItemSource {
399 match self {
400 ItemRef::Fun(d) => &d.src,
401 ItemRef::Global(d) => &d.src,
402 ItemRef::Type(_) | ItemRef::TraitDecl(_) | ItemRef::TraitImpl(_) => {
403 &ItemSource::TopLevel
404 }
405 }
406 }
407
408 pub fn identity_args(&self) -> GenericArgs {
410 self.generic_params().identity_args()
411 }
412
413 pub fn drive<V: VisitAst>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
416 match *self {
417 ItemRef::Type(d) => visitor.visit(d),
418 ItemRef::Fun(d) => visitor.visit(d),
419 ItemRef::Global(d) => visitor.visit(d),
420 ItemRef::TraitDecl(d) => visitor.visit(d),
421 ItemRef::TraitImpl(d) => visitor.visit(d),
422 }
423 }
424
425 pub fn dyn_visit<T: AstVisitable>(&self, f: impl FnMut(&T)) {
427 match *self {
428 ItemRef::Type(d) => d.dyn_visit(f),
429 ItemRef::Fun(d) => d.dyn_visit(f),
430 ItemRef::Global(d) => d.dyn_visit(f),
431 ItemRef::TraitDecl(d) => d.dyn_visit(f),
432 ItemRef::TraitImpl(d) => d.dyn_visit(f),
433 }
434 }
435}
436
437impl<'ctx> ItemRefMut<'ctx> {
438 pub fn as_ref(&self) -> ItemRef<'_> {
439 match self {
440 ItemRefMut::Type(d) => ItemRef::Type(d),
441 ItemRefMut::Fun(d) => ItemRef::Fun(d),
442 ItemRefMut::Global(d) => ItemRef::Global(d),
443 ItemRefMut::TraitDecl(d) => ItemRef::TraitDecl(d),
444 ItemRefMut::TraitImpl(d) => ItemRef::TraitImpl(d),
445 }
446 }
447 pub fn reborrow(&mut self) -> ItemRefMut<'_> {
448 match self {
449 ItemRefMut::Type(d) => ItemRefMut::Type(d),
450 ItemRefMut::Fun(d) => ItemRefMut::Fun(d),
451 ItemRefMut::Global(d) => ItemRefMut::Global(d),
452 ItemRefMut::TraitDecl(d) => ItemRefMut::TraitDecl(d),
453 ItemRefMut::TraitImpl(d) => ItemRefMut::TraitImpl(d),
454 }
455 }
456
457 pub fn set_id(&mut self, id: ItemId) {
458 match (self, id) {
459 (Self::Type(d), ItemId::Type(id)) => d.def_id = id,
460 (Self::Fun(d), ItemId::Fun(id)) => d.def_id = id,
461 (Self::Global(d), ItemId::Global(id)) => d.def_id = id,
462 (Self::TraitDecl(d), ItemId::TraitDecl(id)) => d.def_id = id,
463 (Self::TraitImpl(d), ItemId::TraitImpl(id)) => d.def_id = id,
464 _ => unreachable!(),
465 }
466 }
467
468 pub fn item_meta(&mut self) -> &mut ItemMeta {
469 match self {
470 Self::Type(d) => &mut d.item_meta,
471 Self::Fun(d) => &mut d.item_meta,
472 Self::Global(d) => &mut d.item_meta,
473 Self::TraitDecl(d) => &mut d.item_meta,
474 Self::TraitImpl(d) => &mut d.item_meta,
475 }
476 }
477 pub fn generic_params(&mut self) -> &mut GenericParams {
479 match self {
480 ItemRefMut::Type(d) => &mut d.generics,
481 ItemRefMut::Fun(d) => &mut d.generics,
482 ItemRefMut::Global(d) => &mut d.generics,
483 ItemRefMut::TraitDecl(d) => &mut d.generics,
484 ItemRefMut::TraitImpl(d) => &mut d.generics,
485 }
486 }
487
488 pub fn drive_mut<V: VisitAstMut>(&mut self, visitor: &mut V) -> ControlFlow<V::Break> {
491 match self {
492 ItemRefMut::Type(d) => visitor.visit(*d),
493 ItemRefMut::Fun(d) => visitor.visit(*d),
494 ItemRefMut::Global(d) => visitor.visit(*d),
495 ItemRefMut::TraitDecl(d) => visitor.visit(*d),
496 ItemRefMut::TraitImpl(d) => visitor.visit(*d),
497 }
498 }
499
500 pub fn dyn_visit_mut<T: AstVisitable>(&mut self, f: impl FnMut(&mut T)) {
502 match self {
503 ItemRefMut::Type(d) => d.dyn_visit_mut(f),
504 ItemRefMut::Fun(d) => d.dyn_visit_mut(f),
505 ItemRefMut::Global(d) => d.dyn_visit_mut(f),
506 ItemRefMut::TraitDecl(d) => d.dyn_visit_mut(f),
507 ItemRefMut::TraitImpl(d) => d.dyn_visit_mut(f),
508 }
509 }
510}
511
512impl fmt::Display for TranslatedCrate {
513 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
514 let fmt: &FmtCtx = &self.into_fmt();
515 match &self.ordered_decls {
516 None => {
517 for d in &self.type_decls {
519 writeln!(f, "{}\n", d.with_ctx(fmt))?
520 }
521 for d in &self.global_decls {
522 writeln!(f, "{}\n", d.with_ctx(fmt))?
523 }
524 for d in &self.trait_decls {
525 writeln!(f, "{}\n", d.with_ctx(fmt))?
526 }
527 for d in &self.trait_impls {
528 writeln!(f, "{}\n", d.with_ctx(fmt))?
529 }
530 for d in &self.fun_decls {
531 writeln!(f, "{}\n", d.with_ctx(fmt))?
532 }
533 }
534 Some(ordered_decls) => {
535 for gr in ordered_decls {
536 for id in gr.get_ids() {
537 writeln!(f, "{}\n", fmt.format_decl_id(id))?
538 }
539 }
540 }
541 }
542 fmt::Result::Ok(())
543 }
544}
545
546impl<'a> IntoFormatter for &'a TranslatedCrate {
547 type C = FmtCtx<'a>;
548
549 fn into_fmt(self) -> Self::C {
550 FmtCtx {
551 translated: Some(self),
552 ..Default::default()
553 }
554 }
555}
556
557pub trait HasIdxMapOf<Id: Idx>: std::ops::Index<Id, Output: Sized> {
558 fn get_idx_map(&self) -> &IndexMap<Id, Self::Output>;
559 fn get_idx_map_mut(&mut self) -> &mut IndexMap<Id, Self::Output>;
560}
561
562macro_rules! mk_index_impls {
564 ($ty:ident.$field:ident[$idx:ty]: $output:ty) => {
565 impl std::ops::Index<$idx> for $ty {
566 type Output = $output;
567 fn index(&self, index: $idx) -> &Self::Output {
568 &self.$field[index]
569 }
570 }
571 impl std::ops::IndexMut<$idx> for $ty {
572 fn index_mut(&mut self, index: $idx) -> &mut Self::Output {
573 &mut self.$field[index]
574 }
575 }
576 impl HasIdxMapOf<$idx> for $ty {
577 fn get_idx_map(&self) -> &IndexMap<$idx, Self::Output> {
578 &self.$field
579 }
580 fn get_idx_map_mut(&mut self) -> &mut IndexMap<$idx, Self::Output> {
581 &mut self.$field
582 }
583 }
584 };
585}
586pub(crate) use mk_index_impls;
587
588mk_index_impls!(TranslatedCrate.type_decls[TypeDeclId]: TypeDecl);
589mk_index_impls!(TranslatedCrate.fun_decls[FunDeclId]: FunDecl);
590mk_index_impls!(TranslatedCrate.global_decls[GlobalDeclId]: GlobalDecl);
591mk_index_impls!(TranslatedCrate.trait_decls[TraitDeclId]: TraitDecl);
592mk_index_impls!(TranslatedCrate.trait_impls[TraitImplId]: TraitImpl);