Skip to main content

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, Hash)]
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/// The nature of locations where a given lifetime parameter is used. If this lifetime ever flows
696/// to be used as the lifetime of a mutable reference `&'a mut` then we consider it mutable.
697#[derive(
698    Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumIsA,
699)]
700#[charon::variants_prefix("Lt")]
701pub enum LifetimeMutability {
702    /// A lifetime that is used for a mutable reference.
703    Mutable,
704    /// A lifetime used only in shared references.
705    Shared,
706    /// A lifetime for which we couldn't/didn't compute mutability.
707    Unknown,
708}
709
710/// Type identifier.
711///
712/// Allows us to factorize the code for built-in types, adts and tuples
713#[derive(
714    Debug,
715    PartialEq,
716    Eq,
717    Clone,
718    Copy,
719    VariantName,
720    EnumAsGetters,
721    EnumIsA,
722    SerializeState,
723    DeserializeState,
724    Drive,
725    DriveMut,
726    Hash,
727    Ord,
728    PartialOrd,
729)]
730#[charon::variants_prefix("T")]
731pub enum TypeId {
732    /// A "regular" ADT type.
733    ///
734    /// Includes transparent ADTs and opaque ADTs (local ADTs marked as opaque,
735    /// and external ADTs).
736    #[charon::rename("TAdtId")]
737    Adt(TypeDeclId),
738    Tuple,
739    /// Built-in type. Either a primitive type like array or slice, or a
740    /// non-primitive type coming from a standard library
741    /// and that we handle like a primitive type. Types falling into this
742    /// category include: Box, Vec, Cell...
743    /// The Array and Slice types were initially modelled as primitive in
744    /// the [Ty] type. We decided to move them to built-in types as it allows
745    /// for more uniform treatment throughout the codebase.
746    #[charon::rename("TBuiltin")]
747    #[serde_state(stateless)]
748    Builtin(BuiltinTy),
749}
750
751/// Reference to a type declaration or builtin type.
752#[derive(Debug, Clone, PartialEq, Eq, Hash, SerializeState, DeserializeState, Drive, DriveMut)]
753pub struct TypeDeclRef {
754    pub id: TypeId,
755    pub generics: BoxedArgs,
756}
757
758/// Types of primitive values. Either an integer, bool, char
759#[derive(
760    Debug,
761    PartialEq,
762    Eq,
763    Clone,
764    Copy,
765    VariantName,
766    EnumIsA,
767    EnumAsGetters,
768    VariantIndexArity,
769    Serialize,
770    Deserialize,
771    SerializeState,
772    DeserializeState,
773    Drive,
774    DriveMut,
775    Hash,
776    Ord,
777    PartialOrd,
778)]
779#[charon::rename("LiteralType")]
780#[charon::variants_prefix("T")]
781#[serde_state(stateless)]
782pub enum LiteralTy {
783    Int(IntTy),
784    UInt(UIntTy),
785    Float(FloatTy),
786    Bool,
787    Char,
788}
789
790/// A type.
791///
792/// Warning: the `DriveMut` impls of `Ty` needs to clone and re-hash the modified type to maintain
793/// the hash-consing invariant. This is expensive, avoid visiting types mutably when not needed.
794#[derive(Debug, Clone, Hash, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut)]
795#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
796pub struct Ty(pub HashConsed<TyKind>);
797
798#[derive(
799    Debug,
800    Clone,
801    PartialEq,
802    Eq,
803    Hash,
804    VariantName,
805    EnumIsA,
806    EnumAsGetters,
807    EnumToGetters,
808    VariantIndexArity,
809    SerializeState,
810    DeserializeState,
811    Drive,
812    DriveMut,
813)]
814#[charon::variants_prefix("T")]
815pub enum TyKind {
816    /// An ADT.
817    /// Note that here ADTs are very general. They can be:
818    /// - user-defined ADTs
819    /// - tuples (including `unit`, which is a 0-tuple)
820    /// - built-in types (includes some primitive types, e.g., arrays or slices)
821    /// The information on the nature of the ADT is stored in (`TypeId`)[TypeId].
822    /// The last list is used encode const generics, e.g., the size of an array
823    ///
824    /// Note: this is incorrectly named: this can refer to any valid `TypeDecl` including extern
825    /// types.
826    Adt(TypeDeclRef),
827    #[charon::rename("TVar")]
828    TypeVar(TypeDbVar),
829    Literal(LiteralTy),
830    /// The never type, for computations which don't return. It is sometimes
831    /// necessary for intermediate variables. For instance, if we do (coming
832    /// from the rust documentation):
833    /// ```text
834    /// let num: u32 = match get_a_number() {
835    ///     Some(num) => num,
836    ///     None => break,
837    /// };
838    /// ```
839    /// the second branch will have type `Never`. Also note that `Never`
840    /// can be coerced to any type.
841    ///
842    /// Note that we eliminate the variables which have this type in a micro-pass.
843    /// As statements don't have types, this type disappears eventually disappears
844    /// from the AST.
845    Never,
846    // We don't support floating point numbers on purpose (for now)
847    /// A borrow
848    Ref(Region, Ty, RefKind),
849    /// A raw pointer.
850    RawPtr(Ty, RefKind),
851    /// A trait associated type
852    ///
853    /// Ex.:
854    /// ```text
855    /// trait Foo {
856    ///   type Bar; // type associated to the trait Foo
857    /// }
858    /// ```
859    TraitType(TraitRef, TraitItemName),
860    /// `dyn Trait`
861    DynTrait(DynPredicate),
862    /// Function pointer type. This is a literal pointer to a region of memory that
863    /// contains a callable function.
864    /// This is a function signature with limited generics: it only supports lifetime generics, not
865    /// other kinds of generics.
866    FnPtr(RegionBinder<FunSig>),
867    /// The unique type associated with each function item. Each function item is given
868    /// a unique generic type that takes as input the function's early-bound generics. This type
869    /// is not generally nameable in Rust; it's a ZST (there's a unique value), and a value of that type
870    /// can be cast to a function pointer or passed to functions that expect `FnOnce`/`FnMut`/`Fn` parameters.
871    /// There's a binder here because charon function items take both early and late-bound
872    /// lifetimes as arguments; given that the type here is polymorpohic in the late-bound
873    /// variables (those that could appear in a function pointer type like `for<'a> fn(&'a u32)`),
874    /// we need to bind them here.
875    FnDef(RegionBinder<FnPtr>),
876    /// As a marker of taking out metadata from a given type
877    /// The internal type is assumed to be a type variable
878    PtrMetadata(Ty),
879    /// An array type `[T; N]`
880    Array(Ty, Box<ConstantExpr>),
881    /// A slice type `[T]`
882    Slice(Ty),
883    /// A type that could not be computed or was incorrect.
884    #[drive(skip)]
885    Error(String),
886}
887
888/// Builtin types identifiers.
889///
890/// WARNING: for now, all the built-in types are covariant in the generic
891/// parameters (if there are). Adding types which don't satisfy this
892/// will require to update the code abstracting the signatures (to properly
893/// take into account the lifetime constraints).
894///
895/// TODO: update to not hardcode the types (except `Box` maybe) and be more
896/// modular.
897/// TODO: move to builtins.rs?
898#[derive(
899    Debug,
900    PartialEq,
901    Eq,
902    Clone,
903    Copy,
904    EnumIsA,
905    EnumAsGetters,
906    VariantName,
907    Serialize,
908    Deserialize,
909    Drive,
910    DriveMut,
911    Hash,
912    Ord,
913    PartialOrd,
914)]
915#[charon::variants_prefix("T")]
916pub enum BuiltinTy {
917    /// Boxes are de facto a primitive type.
918    Box,
919    /// Primitive type
920    Str,
921}
922
923#[derive(
924    Debug,
925    Copy,
926    Clone,
927    PartialEq,
928    Eq,
929    PartialOrd,
930    Ord,
931    Hash,
932    Serialize,
933    Deserialize,
934    Drive,
935    DriveMut,
936)]
937pub enum ClosureKind {
938    Fn,
939    FnMut,
940    FnOnce,
941}
942
943impl ClosureKind {
944    // pub fn trait_name(self) -> &'static str {}
945    pub fn method_name(self) -> &'static str {
946        match self {
947            ClosureKind::FnOnce => "call_once",
948            ClosureKind::FnMut => "call_mut",
949            ClosureKind::Fn => "call",
950        }
951    }
952}
953
954/// Additional information for closures.
955#[derive(Debug, Clone, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut)]
956pub struct ClosureInfo {
957    #[serde_state(stateless)]
958    pub kind: ClosureKind,
959    /// The `FnOnce` implementation of this closure -- always exists.
960    pub fn_once_impl: RegionBinder<TraitImplRef>,
961    /// The `FnMut` implementation of this closure, if any.
962    pub fn_mut_impl: Option<RegionBinder<TraitImplRef>>,
963    /// The `Fn` implementation of this closure, if any.
964    pub fn_impl: Option<RegionBinder<TraitImplRef>>,
965    /// The signature of the function that this closure represents.
966    pub signature: RegionBinder<FunSig>,
967}
968
969/// A function signature.
970#[derive(Debug, Clone, PartialEq, Eq, Hash, SerializeState, DeserializeState, Drive, DriveMut)]
971pub struct FunSig {
972    /// Is the function unsafe or not
973    #[drive(skip)]
974    pub is_unsafe: bool,
975    pub inputs: Vec<Ty>,
976    pub output: Ty,
977}
978
979/// The contents of a `dyn Trait` type.
980#[derive(Debug, Clone, Hash, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut)]
981pub struct DynPredicate {
982    /// This binder binds a single type `T`, which is considered existentially quantified. The
983    /// predicates in the binder apply to `T` and represent the `dyn Trait` constraints.
984    /// E.g. `dyn Iterator<Item=u32> + Send` is represented as `exists<T: Iterator<Item=u32> + Send> T`.
985    ///
986    /// Only the first trait clause may have methods. We use the vtable of this trait in the `dyn
987    /// Trait` pointer metadata.
988    pub binder: Binder<Ty>,
989}