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