charon_lib/ast/
types.rs

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