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