Skip to main content

charon_lib/ast/
types.rs

1use crate::ast::*;
2use crate::common::serialize_map_to_array::SeqHashMapToArray;
3use crate::ids::IndexVec;
4use derive_generic_visitor::*;
5use macros::{EnumAsGetters, EnumIsA, EnumToGetters, VariantIndexArity, VariantName};
6use serde::{Deserialize, Serialize};
7use serde_state::{DeserializeState, SerializeState};
8
9mod vars;
10pub use vars::*;
11
12#[derive(
13    Debug,
14    PartialEq,
15    Eq,
16    Copy,
17    Clone,
18    Hash,
19    PartialOrd,
20    Ord,
21    EnumIsA,
22    EnumAsGetters,
23    SerializeState,
24    DeserializeState,
25    Drive,
26    DriveMut,
27    DriveTwo,
28)]
29#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("R"))]
30pub enum Region {
31    /// Region variable. See `DeBruijnVar` for details.
32    Var(RegionDbVar),
33    /// Static region
34    Static,
35    /// Body-local region, considered existentially-bound at the level of a body.
36    Body(RegionId),
37    /// Erased region
38    Erased,
39}
40
41/// Identifier of a trait instance.
42/// This is derived from the trait resolution.
43///
44/// Should be read as a path inside the trait clauses which apply to the current
45/// definition. Note that every path designated by `TraitInstanceId` refers
46/// to a *trait instance*, which is why the [`TraitRefKind::Clause`] variant may seem redundant
47/// with some of the other variants.
48#[derive(
49    Debug,
50    Clone,
51    PartialEq,
52    Eq,
53    PartialOrd,
54    Ord,
55    Hash,
56    SerializeState,
57    DeserializeState,
58    EnumIsA,
59    EnumAsGetters,
60    Drive,
61    DriveMut,
62    DriveTwo,
63)]
64pub enum TraitRefKind {
65    /// A specific top-level implementation item.
66    TraitImpl(TraitImplRef),
67
68    /// One of the local clauses.
69    ///
70    /// Example:
71    /// ```text
72    /// fn f<T>(...) where T : Foo
73    ///                    ^^^^^^^
74    ///                    Clause(0)
75    /// ```
76    Clause(ClauseDbVar),
77
78    /// A parent clause
79    ///
80    /// Example:
81    /// ```text
82    /// trait Foo1 {}
83    /// trait Foo2 { fn f(); }
84    ///
85    /// trait Bar : Foo1 + Foo2 {}
86    ///             ^^^^   ^^^^
87    ///                    parent clause 1
88    ///     parent clause 0
89    ///
90    /// fn g<T : Bar>(x : T) {
91    ///   x.f()
92    ///   ^^^^^
93    ///   Parent(Clause(0), 1)::f(x)
94    ///                     ^
95    ///                     parent clause 1 of clause 0
96    /// }
97    /// ```
98    ParentClause(Box<TraitRef>, TraitClauseId),
99
100    /// A clause defined on an associated type. This variant is only used during translation; after
101    /// the `lift_associated_item_clauses` pass, clauses on items become `ParentClause`s.
102    ///
103    /// Example:
104    /// ```text
105    /// trait Foo {
106    ///   type W: Bar0 + Bar1 // Bar1 contains a method bar1
107    ///                  ^^^^
108    ///               this is the clause 1 applying to W
109    /// }
110    ///
111    /// fn f<T : Foo>(x : T::W) {
112    ///   x.bar1();
113    ///   ^^^^^^^
114    ///   ItemClause(Clause(0), W, 1)
115    ///                         ^^^^
116    ///                         clause 1 from item W (from local clause 0)
117    /// }
118    /// ```
119    ItemClause(Box<TraitRef>, AssocTypeId, TraitClauseId),
120
121    /// The implicit `Self: Trait` clause. Present inside trait declarations, including trait
122    /// method declarations. Not present in trait implementations as we can use `TraitImpl` intead.
123    #[cfg_attr(feature = "charon_on_charon", charon::rename("Self"))]
124    SelfId,
125
126    /// A trait implementation that is computed by the compiler, such as for built-in trait
127    /// `Sized`. This morally points to an invisible `impl` block; as such it contains
128    /// the information we may need from one.
129    ///
130    /// Also used as a placeholder for trait clauses that were stripped by the
131    /// `--remove-adt-clauses` pass: the original `Clause` reference is replaced with a
132    /// `BuiltinOrAuto { builtin_data: RemovedAdtClause, .. }`. See
133    /// [`BuiltinImplData::RemovedAdtClause`].
134    BuiltinOrAuto {
135        #[drive(skip)]
136        builtin_data: BuiltinImplData,
137        /// Exactly like the same field on `TraitImpl`: the `TraitRef`s required to satisfy the
138        /// implied predicates on the trait declaration. E.g. since `FnMut: FnOnce`, a built-in `T:
139        /// FnMut` impl would have a `TraitRef` for `T: FnOnce`.
140        parent_trait_refs: IndexVec<TraitClauseId, TraitRef>,
141        /// The values of the associated types for this trait.
142        types: IndexMap<AssocTypeId, TraitAssocTyImpl>,
143    },
144
145    /// The automatically-generated implementation for `dyn Trait`.
146    Dyn,
147
148    /// For error reporting.
149    #[cfg_attr(feature = "charon_on_charon", charon::rename("UnknownTrait"))]
150    #[drive(skip)]
151    Unknown(String),
152}
153
154/// Describes a built-in impl. Mostly lists the implemented trait, sometimes with more details
155/// about the contents of the implementation.
156#[derive(
157    Debug,
158    Clone,
159    PartialEq,
160    Eq,
161    PartialOrd,
162    Ord,
163    Hash,
164    SerializeState,
165    DeserializeState,
166    Drive,
167    DriveMut,
168    DriveTwo,
169)]
170#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Builtin"))]
171pub enum BuiltinImplData {
172    /// Auto traits (defined with `auto trait ...`, also `Unpin`).
173    Auto,
174
175    Sized,
176    MetaSized,
177    PointeeSized,
178
179    Copy,
180    Clone,
181
182    Tuple,
183    Transmute,
184    Unsize,
185
186    Pointee,
187    DiscriminantKind,
188
189    Fn,
190    FnMut,
191    FnOnce,
192    FnPtr,
193    AsyncFn,
194    AsyncFnMut,
195    AsyncFnOnce,
196    Coroutine,
197    Future,
198
199    /// An impl of `Destruct` for a type with no drop glue.
200    NoopDestruct,
201    /// An impl of `Destruct` for a type parameter, which we could not resolve because
202    /// `--add-drop-bounds` was not set.
203    UntrackedDestruct,
204
205    /// Placeholder used by the `--remove-adt-clauses` pass when it strips a trait clause from a
206    /// type declaration. References to the removed clause are rewritten as
207    /// `BuiltinOrAuto { builtin_data: RemovedAdtClause, .. }`.
208    RemovedAdtClause,
209}
210
211/// A reference to a trait.
212///
213/// This type is hash-consed, `TraitRefContents` contains the actual data.
214#[derive(
215    Debug,
216    Clone,
217    PartialEq,
218    Eq,
219    PartialOrd,
220    Ord,
221    Hash,
222    SerializeState,
223    DeserializeState,
224    Drive,
225    DriveMut,
226    DriveTwo,
227)]
228#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
229pub struct TraitRef(pub HashConsed<TraitRefContents>);
230
231#[derive(
232    Debug,
233    Clone,
234    PartialEq,
235    Eq,
236    PartialOrd,
237    Ord,
238    Hash,
239    SerializeState,
240    DeserializeState,
241    Drive,
242    DriveMut,
243    DriveTwo,
244)]
245pub struct TraitRefContents {
246    pub kind: TraitRefKind,
247    /// Not necessary, but useful
248    pub trait_decl_ref: PolyTraitDeclRef,
249}
250
251/// A predicate of the form `Type: Trait<Args>`.
252///
253/// About the generics, if we write:
254/// ```text
255/// impl Foo<bool> for String { ... }
256/// ```
257///
258/// The substitution is: `[String, bool]`.
259#[derive(
260    Debug,
261    Clone,
262    PartialEq,
263    Eq,
264    PartialOrd,
265    Ord,
266    Hash,
267    SerializeState,
268    DeserializeState,
269    Drive,
270    DriveMut,
271    DriveTwo,
272)]
273pub struct TraitDeclRef {
274    pub id: TraitDeclId,
275    pub generics: BoxedArgs,
276}
277
278/// A quantified trait predicate, e.g. `for<'a> Type<'a>: Trait<'a, Args>`.
279pub type PolyTraitDeclRef = RegionBinder<TraitDeclRef>;
280
281/// A reference to a tait impl, using the provided arguments.
282#[derive(
283    Debug,
284    Clone,
285    PartialEq,
286    Eq,
287    PartialOrd,
288    Ord,
289    Hash,
290    SerializeState,
291    DeserializeState,
292    Drive,
293    DriveMut,
294    DriveTwo,
295)]
296pub struct TraitImplRef {
297    pub id: TraitImplId,
298    pub generics: BoxedArgs,
299}
300
301/// .0 outlives .1
302#[derive(
303    Debug,
304    Clone,
305    PartialEq,
306    Eq,
307    PartialOrd,
308    Ord,
309    Hash,
310    SerializeState,
311    DeserializeState,
312    Drive,
313    DriveMut,
314    DriveTwo,
315)]
316pub struct OutlivesPred<T, U>(pub T, pub U);
317
318pub type RegionOutlives = OutlivesPred<Region, Region>;
319pub type TypeOutlives = OutlivesPred<Ty, Region>;
320
321/// A constraint over a trait associated type.
322///
323/// Example:
324/// ```text
325/// T : Foo<S = String>
326///         ^^^^^^^^^^
327/// ```
328#[derive(
329    Debug,
330    Clone,
331    PartialEq,
332    Eq,
333    PartialOrd,
334    Ord,
335    Hash,
336    SerializeState,
337    DeserializeState,
338    Drive,
339    DriveMut,
340    DriveTwo,
341)]
342pub struct TraitTypeConstraint {
343    pub trait_ref: TraitRef,
344    pub type_id: AssocTypeId,
345    pub ty: Ty,
346}
347
348/// A set of generic arguments.
349#[derive(
350    Clone,
351    PartialEq,
352    Eq,
353    PartialOrd,
354    Ord,
355    Hash,
356    SerializeState,
357    DeserializeState,
358    Drive,
359    DriveMut,
360    DriveTwo,
361)]
362pub struct GenericArgs {
363    pub regions: IndexVec<RegionId, Region>,
364    pub types: IndexVec<TypeVarId, Ty>,
365    pub const_generics: IndexVec<ConstGenericVarId, ConstantExpr>,
366    pub trait_refs: IndexVec<TraitClauseId, TraitRef>,
367}
368
369pub type BoxedArgs = Box<GenericArgs>;
370
371/// A value of type `T` bound by regions. We should use `binder` instead but this causes name clash
372/// issues in the derived ocaml visitors.
373#[derive(
374    Debug,
375    Clone,
376    PartialEq,
377    Eq,
378    PartialOrd,
379    Ord,
380    Hash,
381    SerializeState,
382    DeserializeState,
383    Drive,
384    DriveMut,
385    DriveTwo,
386)]
387pub struct RegionBinder<T> {
388    #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_regions"))]
389    #[serde_state(stateless)]
390    pub regions: IndexVec<RegionId, RegionParam>,
391    /// Named this way to highlight accesses to the inner value that might be handling parameters
392    /// incorrectly. Prefer using helper methods.
393    #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_value"))]
394    pub skip_binder: T,
395}
396
397#[derive(
398    Debug,
399    Clone,
400    PartialEq,
401    Eq,
402    PartialOrd,
403    Ord,
404    Hash,
405    SerializeState,
406    DeserializeState,
407    Drive,
408    DriveMut,
409    DriveTwo,
410)]
411#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("BK"))]
412pub enum BinderKind {
413    /// The parameters of a generic associated type.
414    TraitType(TraitDeclId, AssocTypeId),
415    /// The parameters of a trait method. Used in the `methods` lists in trait decls and trait
416    /// impls.
417    TraitMethod(TraitDeclId, TraitMethodId),
418    /// The parameters bound in a non-trait `impl` block. Used in the `Name`s of inherent methods.
419    InherentImplBlock,
420    /// Binder used for `dyn Trait` existential predicates.
421    Dyn,
422    /// Some other use of a binder outside the main Charon ast.
423    Other,
424}
425
426/// A value of type `T` bound by generic parameters. Used in any context where we're adding generic
427/// parameters that aren't on the top-level item, e.g. `for<'a>` clauses (uses `RegionBinder` for
428/// now), trait methods, GATs (TODO).
429#[derive(
430    Debug,
431    Clone,
432    PartialEq,
433    Eq,
434    PartialOrd,
435    Ord,
436    Hash,
437    SerializeState,
438    DeserializeState,
439    Drive,
440    DriveMut,
441    DriveTwo,
442)]
443pub struct Binder<T> {
444    #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_params"))]
445    pub params: GenericParams,
446    /// Named this way to highlight accesses to the inner value that might be handling parameters
447    /// incorrectly. Prefer using helper methods.
448    #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_value"))]
449    pub skip_binder: T,
450    /// The kind of binder this is.
451    #[cfg_attr(feature = "charon_on_charon", charon::opaque)]
452    pub kind: BinderKind,
453}
454
455/// Generic parameters for a declaration, including predicates.
456#[derive(
457    Default,
458    Clone,
459    PartialEq,
460    Eq,
461    PartialOrd,
462    Ord,
463    Hash,
464    SerializeState,
465    DeserializeState,
466    Drive,
467    DriveMut,
468    DriveTwo,
469)]
470pub struct GenericParams {
471    #[serde_state(stateless)]
472    pub regions: IndexVec<RegionId, RegionParam>,
473    #[serde_state(stateless)]
474    pub types: IndexVec<TypeVarId, TypeParam>,
475    pub const_generics: IndexVec<ConstGenericVarId, ConstGenericParam>,
476    // TODO: rename to match [GenericArgs]?
477    pub trait_clauses: IndexVec<TraitClauseId, TraitParam>,
478    /// The first region in the pair outlives the second region
479    pub regions_outlive: Vec<RegionBinder<RegionOutlives>>,
480    /// The type outlives the region
481    pub types_outlive: Vec<RegionBinder<TypeOutlives>>,
482    /// Constraints over trait associated types
483    pub trait_type_constraints: IndexVec<TraitTypeConstraintId, RegionBinder<TraitTypeConstraint>>,
484}
485
486/// Where a given predicate came from.
487#[derive(
488    Debug,
489    Clone,
490    PartialEq,
491    Eq,
492    PartialOrd,
493    Ord,
494    Hash,
495    SerializeState,
496    DeserializeState,
497    Drive,
498    DriveMut,
499    DriveTwo,
500)]
501pub enum PredicateOrigin {
502    // Note: we use this for globals too, but that's only available with an unstable feature.
503    // ```
504    // fn function<T: Clone>() {}
505    // fn function<T>() where T: Clone {}
506    // const NONE<T: Copy>: Option<T> = None;
507    // ```
508    WhereClauseOnFn,
509    // ```
510    // struct Struct<T: Clone> {}
511    // struct Struct<T> where T: Clone {}
512    // type TypeAlias<T: Clone> = ...;
513    // ```
514    WhereClauseOnType,
515    // Note: this is both trait impls and inherent impl blocks.
516    // ```
517    // impl<T: Clone> Type<T> {}
518    // impl<T> Type<T> where T: Clone {}
519    // impl<T> Trait for Type<T> where T: Clone {}
520    // ```
521    WhereClauseOnImpl,
522    // The special `Self: Trait` clause which is in scope inside the definition of `Foo` or an
523    // implementation of it.
524    // ```
525    // trait Trait {}
526    // ```
527    TraitSelf,
528    // Note: this also includes supertrait constraints.
529    // ```
530    // trait Trait<T: Clone> {}
531    // trait Trait<T> where T: Clone {}
532    // trait Trait: Clone {}
533    // ```
534    WhereClauseOnTrait,
535    // ```
536    // trait Trait {
537    //     type AssocType: Clone;
538    // }
539    // ```
540    TraitItem(AssocTypeId),
541    /// Clauses that are part of a `dyn Trait` type.
542    #[cfg_attr(feature = "charon_on_charon", charon::rename("OriginDyn"))]
543    Dyn,
544}
545
546// rustc counts bytes in layouts as u64
547pub type ByteCount = u64;
548
549/// Simplified layout of a single variant.
550///
551/// Maps fields to their offset within the layout.
552#[derive(
553    Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Drive, DriveMut, DriveTwo,
554)]
555pub struct VariantLayout {
556    /// The offset of each field.
557    #[drive(skip)]
558    pub field_offsets: IndexVec<FieldId, ByteCount>,
559    /// Whether the variant is uninhabited, i.e. has any valid possible value.
560    /// Note that uninhabited types can have arbitrary layouts.
561    #[drive(skip)]
562    pub uninhabited: bool,
563    /// How to write the tag when constructing this variant. Each entry means: write `value` at
564    /// byte `offset`. Mirrors MiniRust's `Variant::tagger`.
565    #[drive(skip)]
566    pub tagger: Vec<(ByteCount, ScalarValue)>,
567}
568
569/// Decision tree used to determine the active variant by reading memory. Mirrors MiniRust's
570/// `Discriminator`.
571#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
572pub enum Discriminator {
573    /// The variant is known.
574    Known(VariantId),
575    /// No valid variant (e.g., invalid tag value).
576    Invalid,
577    /// Branch on an integer value read from memory at `offset`.
578    Branch {
579        /// Byte offset to read from.
580        offset: ByteCount,
581        /// Integer type to read.
582        int_ty: IntegerTy,
583        /// If the integer is in one of these ranges, continue with the given `Discriminator`. The
584        /// ranges are sorted.
585        children: Vec<(std::ops::RangeInclusive<ScalarValue>, Discriminator)>,
586        /// Fallback if no range in `children` matches.
587        fallback: Box<Discriminator>,
588    },
589}
590
591/// Simplified type layout information.
592///
593/// Does not include information about niches.
594/// If the type does not have a fully known layout (e.g. it is ?Sized)
595/// some of the layout parts are not available.
596#[derive(
597    Debug, Clone, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut, DriveTwo,
598)]
599pub struct Layout {
600    /// The size of the type in bytes.
601    #[drive(skip)]
602    pub size: Option<ByteCount>,
603    /// The alignment, in bytes.
604    #[drive(skip)]
605    pub align: Option<ByteCount>,
606    /// Decision tree that determines the active variant by reading memory. Only `Some` for enums.
607    #[drive(skip)]
608    #[serde_state(stateless)]
609    pub discriminator: Option<Discriminator>,
610    /// Whether the type is uninhabited, i.e. has any valid value at all.
611    /// Note that uninhabited types can have arbitrary layouts: `(u32, !)` has space for the `u32`
612    /// and `enum E2 { A, B(!), C(i32, !) }` may have space for a discriminant.
613    #[drive(skip)]
614    pub uninhabited: bool,
615    /// Map from `VariantId` to the corresponding field layouts. Some variants don't have a
616    /// meaningful layout due to being uninhabited (though an uninhabited variant may have a
617    /// layout). Structs and unions are modeled as having exactly one variant.
618    #[serde_state(stateless)]
619    pub variant_layouts: IndexVec<VariantId, Option<VariantLayout>>,
620    /// The representation options of this type declaration as annotated by the user.
621    #[drive(skip)]
622    #[serde_state(stateless)]
623    pub repr: ReprOptions,
624}
625
626/// The metadata stored in a pointer. That's the information stored in pointers alongside
627/// their address. It's empty for `Sized` types, and interesting for unsized
628/// aka dynamically-sized types.
629#[derive(
630    Debug,
631    Clone,
632    PartialEq,
633    Eq,
634    PartialOrd,
635    Ord,
636    Hash,
637    SerializeState,
638    DeserializeState,
639    Drive,
640    DriveMut,
641    DriveTwo,
642)]
643#[serde_state(default_state = ())]
644pub enum PtrMetadata {
645    /// Types that need no metadata, namely `T: Sized` types.
646    #[cfg_attr(feature = "charon_on_charon", charon::rename("NoMetadata"))]
647    None,
648    /// Metadata for `[T]` and `str`, and user-defined types
649    /// that directly or indirectly contain one of the two.
650    /// Of type `usize`.
651    /// Notably, length for `[T]` denotes the number of elements in the slice.
652    /// While for `str` it denotes the number of bytes in the string.
653    Length,
654    /// Metadata for `dyn Trait`, referring to the vtable struct. Has type `&'static vtable`
655    VTable(TypeDeclRef),
656    /// Unknown due to generics, but will inherit from the given type.
657    /// This is consistent with `<Ty as Pointee>::Metadata`.
658    /// Of type `TyKind::Metadata(Ty)`.
659    InheritFrom(Ty),
660}
661
662/// Describes which layout algorithm is used for representing the corresponding type.
663/// Depends on the `#[repr(...)]` used.
664#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
665pub enum ReprAlgorithm {
666    /// The default layout algorithm. Used without an explicit `Ĺ—epr` or for `repr(Rust)`.
667    #[default]
668    Rust,
669    /// The C layout algorithm as enforced by `repr(C)`.
670    C,
671}
672
673/// Describes modifiers to the alignment and packing of the corresponding type.
674/// Represents `repr(align(n))` and `repr(packed(n))`.
675#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
676pub enum AlignmentModifier {
677    Align(ByteCount),
678    Pack(ByteCount),
679}
680
681/// The representation options as annotated by the user.
682///
683/// NOTE: This does not include less common/unstable representations such as `#[repr(simd)]`
684/// or the compiler internal `#[repr(linear)]`. Similarly, enum discriminant representations
685/// are encoded in [`Variant::discriminant`] and [`Discriminator`] instead.
686/// This only stores whether the discriminant type was derived from an explicit annotation.
687#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
688pub struct ReprOptions {
689    pub repr_algo: ReprAlgorithm,
690    pub align_modif: Option<AlignmentModifier>,
691    pub transparent: bool,
692    pub explicit_discr_type: bool,
693}
694
695/// A type declaration.
696///
697/// Types can be opaque or transparent.
698///
699/// Transparent types are local types not marked as opaque.
700/// Opaque types are the others: local types marked as opaque, and non-local
701/// types (coming from external dependencies).
702///
703/// In case the type is transparent, the declaration also contains the
704/// type definition (see [TypeDeclKind]).
705///
706/// A type can only be an ADT (structure or enumeration), as type aliases are
707/// inlined in MIR.
708#[derive(
709    Debug, PartialEq, Eq, Clone, SerializeState, DeserializeState, Drive, DriveMut, DriveTwo,
710)]
711#[serde_state(state_implements = HashConsSerializerState)]
712pub struct TypeDecl {
713    pub def_id: TypeDeclId,
714    /// Meta information associated with the item.
715    pub item_meta: ItemMeta,
716    pub generics: GenericParams,
717    /// The context of the type: distinguishes top-level items from closure-related items.
718    pub src: ItemSource,
719    /// The type kind: enum, struct, or opaque.
720    pub kind: TypeDeclKind,
721    /// The layout of the type for each target. Information may be partial because of generics or
722    /// dynamically-sized types. If we cannot compute a layout, the target has no entry.
723    #[serde(with = "SeqHashMapToArray::<TargetTriple, Layout>")]
724    pub layout: SeqHashMap<TargetTriple, Layout>,
725    /// The metadata associated with a pointer to the type.
726    pub ptr_metadata: PtrMetadata,
727}
728
729generate_index_type!(VariantId, "Variant");
730generate_index_type!(FieldId, "Field");
731
732#[derive(
733    Debug,
734    PartialEq,
735    Eq,
736    Clone,
737    EnumIsA,
738    EnumAsGetters,
739    SerializeState,
740    DeserializeState,
741    Drive,
742    DriveMut,
743    DriveTwo,
744)]
745pub enum TypeDeclKind {
746    Struct(IndexVec<FieldId, Field>),
747    Enum(IndexVec<VariantId, Variant>),
748    Union(IndexVec<FieldId, Field>),
749    /// An opaque type.
750    ///
751    /// Either a local type marked as opaque, or an external type.
752    Opaque,
753    /// An alias to another type. This only shows up in the top-level list of items, as rustc
754    /// inlines uses of type aliases everywhere else.
755    Alias(Ty),
756    /// Used if an error happened during the extraction, and we don't panic
757    /// on error.
758    #[cfg_attr(feature = "charon_on_charon", charon::rename("TDeclError"))]
759    #[drive(skip)]
760    Error(String),
761}
762
763#[derive(
764    Debug, PartialEq, Eq, Clone, SerializeState, DeserializeState, Drive, DriveMut, DriveTwo,
765)]
766#[serde_state(stateless)]
767pub struct Variant {
768    pub id: VariantId,
769    pub span: Span,
770    pub attr_info: AttrInfo,
771    #[cfg_attr(feature = "charon_on_charon", charon::rename("variant_name"))]
772    #[drive(skip)]
773    pub name: String,
774    #[serde_state(stateful)]
775    pub fields: IndexVec<FieldId, Field>,
776    /// The discriminant value outputted by `std::mem::discriminant` for this variant. This can be
777    /// different than the value stored in memory (called `tag`); that one is described by
778    /// [`Discriminator`] and [`VariantLayout::tagger`].
779    pub discriminant: Literal,
780}
781
782#[derive(
783    Debug, PartialEq, Eq, Clone, SerializeState, DeserializeState, Drive, DriveMut, DriveTwo,
784)]
785#[serde_state(stateless)]
786pub struct Field {
787    pub span: Span,
788    pub attr_info: AttrInfo,
789    #[cfg_attr(feature = "charon_on_charon", charon::rename("field_name"))]
790    #[drive(skip)]
791    pub name: Option<String>,
792    #[cfg_attr(feature = "charon_on_charon", charon::rename("field_ty"))]
793    #[serde_state(stateful)]
794    pub ty: Ty,
795}
796
797#[derive(
798    Debug,
799    PartialEq,
800    Eq,
801    Copy,
802    Clone,
803    EnumIsA,
804    VariantName,
805    Serialize,
806    Deserialize,
807    Drive,
808    DriveMut,
809    DriveTwo,
810    Hash,
811    Ord,
812    PartialOrd,
813)]
814pub enum IntTy {
815    Isize,
816    I8,
817    I16,
818    I32,
819    I64,
820    I128,
821}
822
823#[derive(
824    Debug,
825    PartialEq,
826    Eq,
827    Copy,
828    Clone,
829    EnumIsA,
830    VariantName,
831    Serialize,
832    Deserialize,
833    Drive,
834    DriveMut,
835    DriveTwo,
836    Hash,
837    Ord,
838    PartialOrd,
839)]
840pub enum UIntTy {
841    Usize,
842    U8,
843    U16,
844    U32,
845    U64,
846    U128,
847}
848
849#[derive(
850    Debug,
851    PartialEq,
852    Eq,
853    Copy,
854    Clone,
855    EnumIsA,
856    VariantName,
857    Serialize,
858    Deserialize,
859    Drive,
860    DriveMut,
861    DriveTwo,
862    Hash,
863    Ord,
864    PartialOrd,
865)]
866#[cfg_attr(feature = "charon_on_charon", charon::rename("IntegerType"))]
867pub enum IntegerTy {
868    Signed(IntTy),
869    Unsigned(UIntTy),
870}
871
872#[derive(
873    Debug,
874    PartialEq,
875    Eq,
876    Copy,
877    Clone,
878    EnumIsA,
879    VariantName,
880    Serialize,
881    Deserialize,
882    Drive,
883    DriveMut,
884    DriveTwo,
885    Hash,
886    Ord,
887    PartialOrd,
888)]
889#[cfg_attr(feature = "charon_on_charon", charon::rename("FloatType"))]
890pub enum FloatTy {
891    F16,
892    F32,
893    F64,
894    F128,
895}
896
897#[derive(
898    Debug,
899    PartialEq,
900    Eq,
901    Clone,
902    Copy,
903    Hash,
904    VariantName,
905    EnumIsA,
906    Serialize,
907    Deserialize,
908    SerializeState,
909    DeserializeState,
910    Drive,
911    DriveMut,
912    DriveTwo,
913    Ord,
914    PartialOrd,
915)]
916#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("R"))]
917#[serde_state(stateless)]
918pub enum RefKind {
919    Mut,
920    Shared,
921}
922
923/// The nature of locations where a given lifetime parameter is used. If this lifetime ever flows
924/// to be used as the lifetime of a mutable reference `&'a mut` then we consider it mutable.
925#[derive(
926    Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumIsA,
927)]
928#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Lt"))]
929pub enum LifetimeMutability {
930    /// A lifetime that is used for a mutable reference.
931    Mutable,
932    /// A lifetime used only in shared references.
933    Shared,
934    /// A lifetime for which we couldn't/didn't compute mutability.
935    Unknown,
936}
937
938/// Type identifier.
939///
940/// Allows us to factorize the code for built-in types, adts and tuples
941#[derive(
942    Debug,
943    PartialEq,
944    Eq,
945    Clone,
946    Copy,
947    VariantName,
948    EnumAsGetters,
949    EnumIsA,
950    SerializeState,
951    DeserializeState,
952    Drive,
953    DriveMut,
954    DriveTwo,
955    Hash,
956    Ord,
957    PartialOrd,
958)]
959#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
960pub enum TypeId {
961    /// A "regular" ADT type.
962    ///
963    /// Includes transparent ADTs and opaque ADTs (local ADTs marked as opaque,
964    /// and external ADTs).
965    #[cfg_attr(feature = "charon_on_charon", charon::rename("TAdtId"))]
966    Adt(TypeDeclId),
967    Tuple,
968    /// Built-in type. Either a primitive type like array or slice, or a
969    /// non-primitive type coming from a standard library
970    /// and that we handle like a primitive type. Types falling into this
971    /// category include: Box, Vec, Cell...
972    /// The Array and Slice types were initially modelled as primitive in
973    /// the [Ty] type. We decided to move them to built-in types as it allows
974    /// for more uniform treatment throughout the codebase.
975    #[cfg_attr(feature = "charon_on_charon", charon::rename("TBuiltin"))]
976    #[serde_state(stateless)]
977    Builtin(BuiltinTy),
978}
979
980/// Reference to a type declaration or builtin type.
981#[derive(
982    Debug,
983    Clone,
984    PartialEq,
985    Eq,
986    PartialOrd,
987    Ord,
988    Hash,
989    SerializeState,
990    DeserializeState,
991    Drive,
992    DriveMut,
993    DriveTwo,
994)]
995pub struct TypeDeclRef {
996    pub id: TypeId,
997    pub generics: BoxedArgs,
998}
999
1000/// Types of primitive values. Either an integer, bool, char
1001#[derive(
1002    Debug,
1003    PartialEq,
1004    Eq,
1005    Clone,
1006    Copy,
1007    VariantName,
1008    EnumIsA,
1009    EnumAsGetters,
1010    VariantIndexArity,
1011    Serialize,
1012    Deserialize,
1013    SerializeState,
1014    DeserializeState,
1015    Drive,
1016    DriveMut,
1017    DriveTwo,
1018    Hash,
1019    Ord,
1020    PartialOrd,
1021)]
1022#[cfg_attr(feature = "charon_on_charon", charon::rename("LiteralType"))]
1023#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
1024#[serde_state(stateless)]
1025pub enum LiteralTy {
1026    Int(IntTy),
1027    UInt(UIntTy),
1028    Float(FloatTy),
1029    Bool,
1030    Char,
1031}
1032
1033/// A type.
1034///
1035/// Warning: the `DriveMut` impls of `Ty` needs to clone and re-hash the modified type to maintain
1036/// the hash-consing invariant. This is expensive, avoid visiting types mutably when not needed.
1037#[derive(
1038    Debug,
1039    Clone,
1040    PartialEq,
1041    Eq,
1042    PartialOrd,
1043    Ord,
1044    Hash,
1045    SerializeState,
1046    DeserializeState,
1047    Drive,
1048    DriveMut,
1049    DriveTwo,
1050)]
1051#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
1052pub struct Ty(pub HashConsed<TyKind>);
1053
1054#[derive(
1055    Debug,
1056    Clone,
1057    PartialEq,
1058    Eq,
1059    PartialOrd,
1060    Ord,
1061    Hash,
1062    VariantName,
1063    EnumIsA,
1064    EnumAsGetters,
1065    EnumToGetters,
1066    VariantIndexArity,
1067    SerializeState,
1068    DeserializeState,
1069    Drive,
1070    DriveMut,
1071    DriveTwo,
1072)]
1073#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
1074pub enum TyKind {
1075    /// An ADT.
1076    /// Note that here ADTs are very general. They can be:
1077    /// - user-defined ADTs
1078    /// - tuples (including `unit`, which is a 0-tuple)
1079    /// - built-in types (includes some primitive types, e.g., arrays or slices)
1080    ///
1081    /// The information on the nature of the ADT is stored in (`TypeId`)[TypeId].
1082    /// The last list is used encode const generics, e.g., the size of an array
1083    ///
1084    /// Note: this is incorrectly named: this can refer to any valid `TypeDecl` including extern
1085    /// types.
1086    Adt(TypeDeclRef),
1087    #[cfg_attr(feature = "charon_on_charon", charon::rename("TVar"))]
1088    TypeVar(TypeDbVar),
1089    Literal(LiteralTy),
1090    /// The never type, for computations which don't return. It is sometimes
1091    /// necessary for intermediate variables. For instance, if we do (coming
1092    /// from the rust documentation):
1093    /// ```text
1094    /// let num: u32 = match get_a_number() {
1095    ///     Some(num) => num,
1096    ///     None => break,
1097    /// };
1098    /// ```
1099    /// the second branch will have type `Never`. Also note that `Never`
1100    /// can be coerced to any type.
1101    ///
1102    /// Note that we eliminate the variables which have this type in a micro-pass.
1103    /// As statements don't have types, this type disappears eventually disappears
1104    /// from the AST.
1105    Never,
1106    // We don't support floating point numbers on purpose (for now)
1107    /// A borrow
1108    Ref(Region, Ty, RefKind),
1109    /// A raw pointer.
1110    RawPtr(Ty, RefKind),
1111    /// A trait associated type
1112    ///
1113    /// Ex.:
1114    /// ```text
1115    /// trait Foo {
1116    ///   type Bar; // type associated to the trait Foo
1117    /// }
1118    /// ```
1119    TraitType(TraitRef, AssocTypeId, GenericArgs),
1120    /// `dyn Trait`
1121    DynTrait(DynPredicate),
1122    /// Function pointer type. This is a literal pointer to a region of memory that
1123    /// contains a callable function.
1124    /// This is a function signature with limited generics: it only supports lifetime generics, not
1125    /// other kinds of generics.
1126    FnPtr(RegionBinder<FunSig>),
1127    /// The unique type associated with each function item. Each function item is given
1128    /// a unique generic type that takes as input the function's early-bound generics. This type
1129    /// is not generally nameable in Rust; it's a ZST (there's a unique value), and a value of that type
1130    /// can be cast to a function pointer or passed to functions that expect `FnOnce`/`FnMut`/`Fn` parameters.
1131    /// There's a binder here because charon function items take both early and late-bound
1132    /// lifetimes as arguments; given that the type here is polymorpohic in the late-bound
1133    /// variables (those that could appear in a function pointer type like `for<'a> fn(&'a u32)`),
1134    /// we need to bind them here.
1135    FnDef(RegionBinder<FnPtr>),
1136    /// As a marker of taking out metadata from a given type
1137    /// The internal type is assumed to be a type variable
1138    PtrMetadata(Ty),
1139    /// An array type `[T; N]`
1140    Array(Ty, Box<ConstantExpr>),
1141    /// A slice type `[T]`
1142    Slice(Ty),
1143    /// A pattern type. This is a newtype over the first type whose valid values are restricted by
1144    /// the pattern.
1145    Pattern(Ty, TypePattern),
1146    /// A type that could not be computed or was incorrect.
1147    #[drive(skip)]
1148    Error(String),
1149}
1150
1151/// Builtin types identifiers.
1152///
1153/// WARNING: for now, all the built-in types are covariant in the generic
1154/// parameters (if there are). Adding types which don't satisfy this
1155/// will require to update the code abstracting the signatures (to properly
1156/// take into account the lifetime constraints).
1157///
1158/// TODO: update to not hardcode the types (except `Box` maybe) and be more
1159/// modular.
1160/// TODO: move to builtins.rs?
1161#[derive(
1162    Debug,
1163    PartialEq,
1164    Eq,
1165    Clone,
1166    Copy,
1167    EnumIsA,
1168    EnumAsGetters,
1169    VariantName,
1170    Serialize,
1171    Deserialize,
1172    Drive,
1173    DriveMut,
1174    DriveTwo,
1175    Hash,
1176    Ord,
1177    PartialOrd,
1178)]
1179#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
1180pub enum BuiltinTy {
1181    /// Boxes are de facto a primitive type.
1182    Box,
1183    /// Primitive type
1184    Str,
1185}
1186
1187#[derive(
1188    Debug,
1189    Copy,
1190    Clone,
1191    PartialEq,
1192    Eq,
1193    PartialOrd,
1194    Ord,
1195    Hash,
1196    Serialize,
1197    Deserialize,
1198    Drive,
1199    DriveMut,
1200    DriveTwo,
1201)]
1202pub enum ClosureKind {
1203    Fn,
1204    FnMut,
1205    FnOnce,
1206}
1207
1208impl ClosureKind {
1209    // pub fn trait_name(self) -> &'static str {}
1210    pub fn method_name(self) -> &'static str {
1211        match self {
1212            ClosureKind::FnOnce => "call_once",
1213            ClosureKind::FnMut => "call_mut",
1214            ClosureKind::Fn => "call",
1215        }
1216    }
1217}
1218
1219/// Additional information for closures.
1220#[derive(
1221    Debug,
1222    Clone,
1223    PartialEq,
1224    Eq,
1225    PartialOrd,
1226    Ord,
1227    SerializeState,
1228    DeserializeState,
1229    Drive,
1230    DriveMut,
1231    DriveTwo,
1232)]
1233pub struct ClosureInfo {
1234    #[serde_state(stateless)]
1235    pub kind: ClosureKind,
1236    /// The `FnOnce` implementation of this closure -- always exists.
1237    pub fn_once_impl: RegionBinder<TraitImplRef>,
1238    /// The `FnMut` implementation of this closure, if any.
1239    pub fn_mut_impl: Option<RegionBinder<TraitImplRef>>,
1240    /// The `Fn` implementation of this closure, if any.
1241    pub fn_impl: Option<RegionBinder<TraitImplRef>>,
1242    /// The signature of the function that this closure represents.
1243    pub signature: RegionBinder<FunSig>,
1244}
1245
1246/// A function signature.
1247#[derive(
1248    Debug,
1249    Clone,
1250    PartialEq,
1251    Eq,
1252    PartialOrd,
1253    Ord,
1254    Hash,
1255    SerializeState,
1256    DeserializeState,
1257    Drive,
1258    DriveMut,
1259    DriveTwo,
1260)]
1261pub struct FunSig {
1262    /// Is the function unsafe or not
1263    #[drive(skip)]
1264    pub is_unsafe: bool,
1265    /// The calling convention of this function.
1266    #[drive(skip)]
1267    pub abi: Abi,
1268    /// Whether this is a C-variadic function (its last parameter is `...`).
1269    #[drive(skip)]
1270    pub is_variadic: bool,
1271    pub inputs: Vec<Ty>,
1272    pub output: Ty,
1273}
1274
1275#[derive(
1276    Debug,
1277    Clone,
1278    PartialEq,
1279    Eq,
1280    PartialOrd,
1281    Ord,
1282    Hash,
1283    VariantName,
1284    EnumIsA,
1285    SerializeState,
1286    DeserializeState,
1287    Drive,
1288    DriveMut,
1289    DriveTwo,
1290)]
1291#[serde_state(stateless)]
1292#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Abi"))]
1293pub enum Abi {
1294    Rust,
1295    C,
1296    /// Rust's spelling for the ABI, e.g. "C-unwind" or "system".
1297    Other(#[drive(skip)] ustr::Ustr),
1298}
1299
1300impl Abi {
1301    pub fn rust() -> Self {
1302        Self::Rust
1303    }
1304
1305    pub fn rust_name(&self) -> &str {
1306        match self {
1307            Self::Rust => "Rust",
1308            Self::C => "C",
1309            Self::Other(name) => name.as_str(),
1310        }
1311    }
1312}
1313
1314/// The contents of a `dyn Trait` type.
1315#[derive(
1316    Debug,
1317    Clone,
1318    PartialEq,
1319    Eq,
1320    PartialOrd,
1321    Ord,
1322    Hash,
1323    SerializeState,
1324    DeserializeState,
1325    Drive,
1326    DriveMut,
1327    DriveTwo,
1328)]
1329pub struct DynPredicate {
1330    /// This binder binds a single type `T`, which is considered existentially quantified. The
1331    /// predicates in the binder apply to `T` and represent the `dyn Trait` constraints.
1332    /// E.g. `dyn Iterator<Item=u32> + Send` is represented as `exists<T: Iterator<Item=u32> + Send> T`.
1333    ///
1334    /// Only the first trait clause may have methods. We use the vtable of this trait in the `dyn
1335    /// Trait` pointer metadata.
1336    pub binder: Binder<Ty>,
1337}
1338
1339/// A type-level pattern used by [`TyKind::Pattern`].
1340#[derive(
1341    Debug,
1342    Clone,
1343    PartialEq,
1344    Eq,
1345    PartialOrd,
1346    Ord,
1347    Hash,
1348    VariantName,
1349    EnumIsA,
1350    SerializeState,
1351    DeserializeState,
1352    Drive,
1353    DriveMut,
1354    DriveTwo,
1355)]
1356#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
1357pub enum TypePattern {
1358    Range(Box<ConstantExpr>, Box<ConstantExpr>),
1359    OrPattern(Vec<TypePattern>),
1360    NotNull,
1361}