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