charon_lib/ast/
types.rs

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