charon_lib/ast/
types.rs

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