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