Skip to main content

charon_lib/ast/
krate.rs

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/// The id of a translated item.
24#[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
54/// Implement `TryFrom`  and `From` to convert between an enum and its variants.
55macro_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/// A translated item.
94#[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/// A reference to a translated item.
106#[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/// A mutable reference to a translated item.
118#[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/// A (group of) top-level declaration(s), properly reordered.
130/// "G" stands for "generic"
131#[derive(
132    Debug, Clone, VariantIndexArity, VariantName, EnumAsGetters, EnumIsA, Serialize, Deserialize,
133)]
134#[charon::variants_suffix("Group")]
135pub enum GDeclarationGroup<Id> {
136    /// A non-recursive declaration
137    NonRec(Id),
138    /// A (group of mutually) recursive declaration(s)
139    Rec(Vec<Id>),
140}
141
142/// A (group of) top-level declaration(s), properly reordered.
143#[derive(
144    Debug, Clone, VariantIndexArity, VariantName, EnumAsGetters, EnumIsA, Serialize, Deserialize,
145)]
146#[charon::variants_suffix("Group")]
147pub enum DeclarationGroup {
148    /// A type declaration group
149    Type(GDeclarationGroup<TypeDeclId>),
150    /// A function declaration group
151    Fun(GDeclarationGroup<FunDeclId>),
152    /// A global declaration group
153    Global(GDeclarationGroup<GlobalDeclId>),
154    TraitDecl(GDeclarationGroup<TraitDeclId>),
155    TraitImpl(GDeclarationGroup<TraitImplId>),
156    /// Anything that doesn't fit into these categories.
157    Mixed(GDeclarationGroup<ItemId>),
158}
159
160pub type DeclarationsGroups = Vec<DeclarationGroup>;
161
162/// A target triple, e.g. `x86_64-unknown-linux-gnu`.
163pub type TargetTriple = String;
164
165#[derive(Clone, Drive, DriveMut, SerializeState, DeserializeState)]
166#[serde_state(stateless)]
167pub struct TargetInfo {
168    /// The pointer size of the target in bytes.
169    pub target_pointer_size: types::ByteCount,
170    /// Whether the target platform uses little endian byte order.
171    pub is_little_endian: bool,
172}
173
174/// The data of a translated crate.
175#[derive(Default, Clone, Drive, DriveMut, SerializeState, DeserializeState)]
176#[serde_state(state_implements = HashConsSerializerState)]
177pub struct TranslatedCrate {
178    /// The name of the crate.
179    #[drive(skip)]
180    pub crate_name: String,
181
182    /// The options used when calling Charon. It is useful for the applications
183    /// which consumed the serialized code, to check that Charon was called with
184    /// the proper options.
185    #[drive(skip)]
186    #[serde_state(stateless)]
187    pub options: crate::options::CliOpts,
188
189    /// Information about each target platform. When translating a crate normally this will have a
190    /// single entry; when using `--targets` this will have one entry per chosen target.
191    #[drive(skip)]
192    #[serde(with = "SeqHashMapToArray::<TargetTriple, TargetInfo>")]
193    pub target_information: SeqHashMap<TargetTriple, TargetInfo>,
194
195    /// The names of all registered items. Available so we can know the names even of items that
196    /// failed to translate.
197    /// Invariant: after translation, any existing `ItemId` must have an associated name, even
198    /// if the corresponding item wasn't translated.
199    #[serde(with = "SeqHashMapToArray::<ItemId, Name>")]
200    pub item_names: SeqHashMap<ItemId, Name>,
201    /// Short names, for items whose last PathElem is unique.
202    #[serde(with = "SeqHashMapToArray::<ItemId, Name>")]
203    pub short_names: SeqHashMap<ItemId, Name>,
204
205    /// The translated files.
206    #[drive(skip)]
207    #[serde_state(stateless)]
208    pub files: IndexVec<FileId, File>,
209    /// The translated type definitions
210    pub type_decls: IndexMap<TypeDeclId, TypeDecl>,
211    /// The translated function definitions
212    pub fun_decls: IndexMap<FunDeclId, FunDecl>,
213    /// The translated global definitions
214    pub global_decls: IndexMap<GlobalDeclId, GlobalDecl>,
215    /// The translated trait declarations
216    pub trait_decls: IndexMap<TraitDeclId, TraitDecl>,
217    /// The translated trait declarations
218    pub trait_impls: IndexMap<TraitImplId, TraitImpl>,
219    /// A `const UNIT: () = ();` used whenever we make a thin pointer/reference to avoid creating a
220    /// local `let unit = ();` variable. It is always `Some`.
221    pub unit_metadata: Option<GlobalDeclRef>,
222    /// The re-ordered groups of declarations, initialized as empty.
223    #[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    /// Remove the item without touching the name maps.
262    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    /// Set the item to the corresponding slot, and record its name in the name map.
272    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    /// Set the item to the corresponding slot.
279    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    /// When translating without `--target`, there's only one target information; this method
325    /// retrieves it.
326    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    /// The generic parameters of this item.
387    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    /// Get information about the parent of this item, if any.
398    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    /// See [`GenericParams::identity_args`].
409    pub fn identity_args(&self) -> GenericArgs {
410        self.generic_params().identity_args()
411    }
412
413    /// We can't implement `AstVisitable` because of the `'static` constraint, but it's ok because
414    /// `ItemRef` isn't contained in any of our types.
415    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    /// Visit all occurrences of that type inside `self`, in pre-order traversal.
426    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    /// The generic parameters of this item.
478    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    /// We can't implement `AstVisitable` because of the `'static` constraint, but it's ok because
489    /// `ItemRefMut` isn't contained in any of our types.
490    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    /// Visit all occurrences of that type inside `self`, in pre-order traversal.
501    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                // We do simple: types, globals, traits, functions
518                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
562/// Delegate `Index` implementations to subfields.
563macro_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);