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, ConstGeneric>,
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)]
288#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
289pub struct GenericParams {
290    #[serde_state(stateless)]
291    pub regions: IndexMap<RegionId, RegionParam>,
292    #[serde_state(stateless)]
293    pub types: IndexMap<TypeVarId, TypeParam>,
294    #[serde_state(stateless)]
295    pub const_generics: IndexMap<ConstGenericVarId, ConstGenericParam>,
296    // TODO: rename to match [GenericArgs]?
297    pub trait_clauses: IndexMap<TraitClauseId, TraitParam>,
298    /// The first region in the pair outlives the second region
299    pub regions_outlive: Vec<RegionBinder<RegionOutlives>>,
300    /// The type outlives the region
301    pub types_outlive: Vec<RegionBinder<TypeOutlives>>,
302    /// Constraints over trait associated types
303    pub trait_type_constraints: IndexMap<TraitTypeConstraintId, RegionBinder<TraitTypeConstraint>>,
304}
305
306/// Where a given predicate came from.
307#[derive(Debug, Clone, PartialEq, Eq, Hash, SerializeState, DeserializeState, Drive, DriveMut)]
308pub enum PredicateOrigin {
309    // Note: we use this for globals too, but that's only available with an unstable feature.
310    // ```
311    // fn function<T: Clone>() {}
312    // fn function<T>() where T: Clone {}
313    // const NONE<T: Copy>: Option<T> = None;
314    // ```
315    WhereClauseOnFn,
316    // ```
317    // struct Struct<T: Clone> {}
318    // struct Struct<T> where T: Clone {}
319    // type TypeAlias<T: Clone> = ...;
320    // ```
321    WhereClauseOnType,
322    // Note: this is both trait impls and inherent impl blocks.
323    // ```
324    // impl<T: Clone> Type<T> {}
325    // impl<T> Type<T> where T: Clone {}
326    // impl<T> Trait for Type<T> where T: Clone {}
327    // ```
328    WhereClauseOnImpl,
329    // The special `Self: Trait` clause which is in scope inside the definition of `Foo` or an
330    // implementation of it.
331    // ```
332    // trait Trait {}
333    // ```
334    TraitSelf,
335    // Note: this also includes supertrait constraints.
336    // ```
337    // trait Trait<T: Clone> {}
338    // trait Trait<T> where T: Clone {}
339    // trait Trait: Clone {}
340    // ```
341    WhereClauseOnTrait,
342    // ```
343    // trait Trait {
344    //     type AssocType: Clone;
345    // }
346    // ```
347    TraitItem(TraitItemName),
348    /// Clauses that are part of a `dyn Trait` type.
349    Dyn,
350}
351
352// rustc counts bytes in layouts as u64
353pub type ByteCount = u64;
354
355/// Simplified layout of a single variant.
356///
357/// Maps fields to their offset within the layout.
358#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Drive, DriveMut)]
359pub struct VariantLayout {
360    /// The offset of each field.
361    #[drive(skip)]
362    pub field_offsets: IndexVec<FieldId, ByteCount>,
363    /// Whether the variant is uninhabited, i.e. has any valid possible value.
364    /// Note that uninhabited types can have arbitrary layouts.
365    #[drive(skip)]
366    pub uninhabited: bool,
367    /// The memory representation of the discriminant corresponding to this
368    /// variant. It must be of the same type as the corresponding [`DiscriminantLayout::tag_ty`].
369    ///
370    /// If it's `None`, then this variant is either:
371    /// - the untagged variant (cf. [`TagEncoding::Niche::untagged_variant`]) of a niched enum;
372    /// - the single variant of a struct;
373    /// - uninhabited.
374    #[drive(skip)]
375    pub tag: Option<ScalarValue>,
376}
377
378/// Describes how we represent the active enum variant in memory.
379#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
380pub enum TagEncoding {
381    /// Represents the direct encoding of the discriminant as the tag via integer casts.
382    Direct,
383    /// Represents the encoding of the discriminant in the niche of variant `untagged_variant`.
384    Niche { untagged_variant: VariantId },
385}
386
387/// Layout of the discriminant.
388/// Describes the offset of the discriminant field as well as its encoding
389/// as `tag` in memory.
390#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
391pub struct DiscriminantLayout {
392    /// The offset of the discriminant in bytes.
393    pub offset: ByteCount,
394    /// The representation type of the discriminant.
395    pub tag_ty: IntegerTy,
396    /// How the tag is encoding in memory.
397    pub encoding: TagEncoding,
398    // FIXME: Should probably contain the valid range of the tag, too.
399}
400
401/// Simplified type layout information.
402///
403/// Does not include information about niches.
404/// If the type does not have a fully known layout (e.g. it is ?Sized)
405/// some of the layout parts are not available.
406#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Drive, DriveMut)]
407pub struct Layout {
408    /// The size of the type in bytes.
409    #[drive(skip)]
410    pub size: Option<ByteCount>,
411    /// The alignment, in bytes.
412    #[drive(skip)]
413    pub align: Option<ByteCount>,
414    /// The discriminant's layout, if any. Only relevant for types with multiple variants.
415    #[drive(skip)]
416    pub discriminant_layout: Option<DiscriminantLayout>,
417    /// Whether the type is uninhabited, i.e. has any valid value at all.
418    /// Note that uninhabited types can have arbitrary layouts: `(u32, !)` has space for the `u32`
419    /// and `enum E2 { A, B(!), C(i32, !) }` may have space for a discriminant.
420    #[drive(skip)]
421    pub uninhabited: bool,
422    /// Map from `VariantId` to the corresponding field layouts. Structs are modeled as having
423    /// exactly one variant, unions as having no variant.
424    pub variant_layouts: IndexVec<VariantId, VariantLayout>,
425}
426
427/// The metadata stored in a pointer. That's the information stored in pointers alongside
428/// their address. It's empty for `Sized` types, and interesting for unsized
429/// aka dynamically-sized types.
430#[derive(Debug, Clone, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut)]
431#[serde_state(default_state = ())]
432pub enum PtrMetadata {
433    /// Types that need no metadata, namely `T: Sized` types.
434    #[charon::rename("NoMetadata")]
435    None,
436    /// Metadata for `[T]` and `str`, and user-defined types
437    /// that directly or indirectly contain one of the two.
438    /// Of type `usize`.
439    /// Notably, length for `[T]` denotes the number of elements in the slice.
440    /// While for `str` it denotes the number of bytes in the string.
441    Length,
442    /// Metadata for `dyn Trait`, referring to the vtable struct,
443    /// also for user-defined types that directly or indirectly contain a `dyn Trait`.
444    /// Of type `&'static vtable`
445    VTable(TypeDeclRef),
446    /// Unknown due to generics, but will inherit from the given type.
447    /// This is consistent with `<Ty as Pointee>::Metadata`.
448    /// Of type `TyKind::Metadata(Ty)`.
449    InheritFrom(Ty),
450}
451
452/// Describes which layout algorithm is used for representing the corresponding type.
453/// Depends on the `#[repr(...)]` used.
454#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
455pub enum ReprAlgorithm {
456    /// The default layout algorithm. Used without an explicit `Ĺ—epr` or for `repr(Rust)`.
457    Rust,
458    /// The C layout algorithm as enforced by `repr(C)`.
459    C,
460}
461
462/// Describes modifiers to the alignment and packing of the corresponding type.
463/// Represents `repr(align(n))` and `repr(packed(n))`.
464#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
465pub enum AlignmentModifier {
466    Align(ByteCount),
467    Pack(ByteCount),
468}
469
470/// The representation options as annotated by the user.
471///
472/// NOTE: This does not include less common/unstable representations such as `#[repr(simd)]`
473/// or the compiler internal `#[repr(linear)]`. Similarly, enum discriminant representations
474/// are encoded in [`Variant::discriminant`] and [`DiscriminantLayout`] instead.
475/// This only stores whether the discriminant type was derived from an explicit annotation.
476#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
477pub struct ReprOptions {
478    pub repr_algo: ReprAlgorithm,
479    pub align_modif: Option<AlignmentModifier>,
480    pub transparent: bool,
481    pub explicit_discr_type: bool,
482}
483
484/// A type declaration.
485///
486/// Types can be opaque or transparent.
487///
488/// Transparent types are local types not marked as opaque.
489/// Opaque types are the others: local types marked as opaque, and non-local
490/// types (coming from external dependencies).
491///
492/// In case the type is transparent, the declaration also contains the
493/// type definition (see [TypeDeclKind]).
494///
495/// A type can only be an ADT (structure or enumeration), as type aliases are
496/// inlined in MIR.
497#[derive(Debug, Clone, SerializeState, DeserializeState, Drive, DriveMut)]
498pub struct TypeDecl {
499    #[drive(skip)]
500    pub def_id: TypeDeclId,
501    /// Meta information associated with the item.
502    pub item_meta: ItemMeta,
503    pub generics: GenericParams,
504    /// The context of the type: distinguishes top-level items from closure-related items.
505    pub src: ItemSource,
506    /// The type kind: enum, struct, or opaque.
507    pub kind: TypeDeclKind,
508    /// The layout of the type. Information may be partial because of generics or dynamically-
509    /// sized types. If rustc cannot compute a layout, it is `None`.
510    #[serde_state(stateless)]
511    pub layout: Option<Layout>,
512    /// The metadata associated with a pointer to the type.
513    pub ptr_metadata: PtrMetadata,
514    /// The representation options of this type declaration as annotated by the user.
515    /// Is `None` for foreign type declarations.
516    #[drive(skip)]
517    #[serde_state(stateless)]
518    pub repr: Option<ReprOptions>,
519}
520
521generate_index_type!(VariantId, "Variant");
522generate_index_type!(FieldId, "Field");
523
524#[derive(
525    Debug, Clone, EnumIsA, EnumAsGetters, SerializeState, DeserializeState, Drive, DriveMut,
526)]
527pub enum TypeDeclKind {
528    Struct(IndexVec<FieldId, Field>),
529    Enum(IndexVec<VariantId, Variant>),
530    Union(IndexVec<FieldId, Field>),
531    /// An opaque type.
532    ///
533    /// Either a local type marked as opaque, or an external type.
534    Opaque,
535    /// An alias to another type. This only shows up in the top-level list of items, as rustc
536    /// inlines uses of type aliases everywhere else.
537    Alias(Ty),
538    /// Used if an error happened during the extraction, and we don't panic
539    /// on error.
540    #[charon::rename("TDeclError")]
541    #[drive(skip)]
542    Error(String),
543}
544
545#[derive(Debug, Clone, SerializeState, DeserializeState, Drive, DriveMut)]
546#[serde_state(stateless)]
547pub struct Variant {
548    pub span: Span,
549    #[drive(skip)]
550    pub attr_info: AttrInfo,
551    #[charon::rename("variant_name")]
552    #[drive(skip)]
553    pub name: String,
554    #[serde_state(stateful)]
555    pub fields: IndexVec<FieldId, Field>,
556    /// The discriminant value outputted by `std::mem::discriminant` for this variant. This can be
557    /// different than the value stored in memory (called `tag`). That one is described by
558    /// [`DiscriminantLayout`] and [`TagEncoding`].
559    pub discriminant: Literal,
560}
561
562#[derive(Debug, Clone, SerializeState, DeserializeState, Drive, DriveMut)]
563#[serde_state(stateless)]
564pub struct Field {
565    pub span: Span,
566    #[drive(skip)]
567    pub attr_info: AttrInfo,
568    #[charon::rename("field_name")]
569    #[drive(skip)]
570    pub name: Option<String>,
571    #[charon::rename("field_ty")]
572    #[serde_state(stateful)]
573    pub ty: Ty,
574}
575
576#[derive(
577    Debug,
578    PartialEq,
579    Eq,
580    Copy,
581    Clone,
582    EnumIsA,
583    VariantName,
584    Serialize,
585    Deserialize,
586    Drive,
587    DriveMut,
588    Hash,
589    Ord,
590    PartialOrd,
591)]
592pub enum IntTy {
593    Isize,
594    I8,
595    I16,
596    I32,
597    I64,
598    I128,
599}
600
601#[derive(
602    Debug,
603    PartialEq,
604    Eq,
605    Copy,
606    Clone,
607    EnumIsA,
608    VariantName,
609    Serialize,
610    Deserialize,
611    Drive,
612    DriveMut,
613    Hash,
614    Ord,
615    PartialOrd,
616)]
617pub enum UIntTy {
618    Usize,
619    U8,
620    U16,
621    U32,
622    U64,
623    U128,
624}
625
626#[derive(
627    Debug,
628    PartialEq,
629    Eq,
630    Copy,
631    Clone,
632    EnumIsA,
633    VariantName,
634    Serialize,
635    Deserialize,
636    Drive,
637    DriveMut,
638    Hash,
639    Ord,
640    PartialOrd,
641)]
642#[charon::rename("IntegerType")]
643pub enum IntegerTy {
644    Signed(IntTy),
645    Unsigned(UIntTy),
646}
647
648#[derive(
649    Debug,
650    PartialEq,
651    Eq,
652    Copy,
653    Clone,
654    EnumIsA,
655    VariantName,
656    Serialize,
657    Deserialize,
658    Drive,
659    DriveMut,
660    Hash,
661    Ord,
662    PartialOrd,
663)]
664#[charon::rename("FloatType")]
665pub enum FloatTy {
666    F16,
667    F32,
668    F64,
669    F128,
670}
671
672#[derive(
673    Debug,
674    PartialEq,
675    Eq,
676    Clone,
677    Copy,
678    Hash,
679    VariantName,
680    EnumIsA,
681    Serialize,
682    Deserialize,
683    SerializeState,
684    DeserializeState,
685    Drive,
686    DriveMut,
687    Ord,
688    PartialOrd,
689)]
690#[charon::variants_prefix("R")]
691#[serde_state(stateless)]
692pub enum RefKind {
693    Mut,
694    Shared,
695}
696
697/// Type identifier.
698///
699/// Allows us to factorize the code for built-in types, adts and tuples
700#[derive(
701    Debug,
702    PartialEq,
703    Eq,
704    Clone,
705    Copy,
706    VariantName,
707    EnumAsGetters,
708    EnumIsA,
709    SerializeState,
710    DeserializeState,
711    Drive,
712    DriveMut,
713    Hash,
714    Ord,
715    PartialOrd,
716)]
717#[charon::variants_prefix("T")]
718pub enum TypeId {
719    /// A "regular" ADT type.
720    ///
721    /// Includes transparent ADTs and opaque ADTs (local ADTs marked as opaque,
722    /// and external ADTs).
723    #[charon::rename("TAdtId")]
724    Adt(TypeDeclId),
725    Tuple,
726    /// Built-in type. Either a primitive type like array or slice, or a
727    /// non-primitive type coming from a standard library
728    /// and that we handle like a primitive type. Types falling into this
729    /// category include: Box, Vec, Cell...
730    /// The Array and Slice types were initially modelled as primitive in
731    /// the [Ty] type. We decided to move them to built-in types as it allows
732    /// for more uniform treatment throughout the codebase.
733    #[charon::rename("TBuiltin")]
734    #[serde_state(stateless)]
735    Builtin(BuiltinTy),
736}
737
738/// Reference to a type declaration or builtin type.
739#[derive(Debug, Clone, PartialEq, Eq, Hash, SerializeState, DeserializeState, Drive, DriveMut)]
740pub struct TypeDeclRef {
741    pub id: TypeId,
742    pub generics: BoxedArgs,
743}
744
745/// Types of primitive values. Either an integer, bool, char
746#[derive(
747    Debug,
748    PartialEq,
749    Eq,
750    Clone,
751    Copy,
752    VariantName,
753    EnumIsA,
754    EnumAsGetters,
755    VariantIndexArity,
756    Serialize,
757    Deserialize,
758    SerializeState,
759    DeserializeState,
760    Drive,
761    DriveMut,
762    Hash,
763    Ord,
764    PartialOrd,
765)]
766#[charon::rename("LiteralType")]
767#[charon::variants_prefix("T")]
768#[serde_state(stateless)]
769pub enum LiteralTy {
770    Int(IntTy),
771    UInt(UIntTy),
772    Float(FloatTy),
773    Bool,
774    Char,
775}
776
777/// Const Generic Values. Either a primitive value, or a variable corresponding to a primitve value
778#[derive(
779    Debug,
780    PartialEq,
781    Eq,
782    Clone,
783    VariantName,
784    EnumIsA,
785    EnumAsGetters,
786    VariantIndexArity,
787    SerializeState,
788    DeserializeState,
789    Drive,
790    DriveMut,
791    Hash,
792)]
793#[charon::variants_prefix("Cg")]
794pub enum ConstGeneric {
795    /// A global constant
796    Global(GlobalDeclId),
797    /// A const generic variable
798    Var(ConstGenericDbVar),
799    /// A concrete value
800    #[serde_state(stateless)]
801    Value(Literal),
802}
803
804/// A type.
805///
806/// Warning: the `DriveMut` impls of `Ty` needs to clone and re-hash the modified type to maintain
807/// the hash-consing invariant. This is expensive, avoid visiting types mutably when not needed.
808#[derive(Debug, Clone, Hash, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut)]
809#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
810pub struct Ty(pub HashConsed<TyKind>);
811
812#[derive(
813    Debug,
814    Clone,
815    PartialEq,
816    Eq,
817    Hash,
818    VariantName,
819    EnumIsA,
820    EnumAsGetters,
821    EnumToGetters,
822    VariantIndexArity,
823    SerializeState,
824    DeserializeState,
825    Drive,
826    DriveMut,
827)]
828#[charon::variants_prefix("T")]
829pub enum TyKind {
830    /// An ADT.
831    /// Note that here ADTs are very general. They can be:
832    /// - user-defined ADTs
833    /// - tuples (including `unit`, which is a 0-tuple)
834    /// - built-in types (includes some primitive types, e.g., arrays or slices)
835    /// The information on the nature of the ADT is stored in (`TypeId`)[TypeId].
836    /// The last list is used encode const generics, e.g., the size of an array
837    ///
838    /// Note: this is incorrectly named: this can refer to any valid `TypeDecl` including extern
839    /// types.
840    Adt(TypeDeclRef),
841    #[charon::rename("TVar")]
842    TypeVar(TypeDbVar),
843    Literal(LiteralTy),
844    /// The never type, for computations which don't return. It is sometimes
845    /// necessary for intermediate variables. For instance, if we do (coming
846    /// from the rust documentation):
847    /// ```text
848    /// let num: u32 = match get_a_number() {
849    ///     Some(num) => num,
850    ///     None => break,
851    /// };
852    /// ```
853    /// the second branch will have type `Never`. Also note that `Never`
854    /// can be coerced to any type.
855    ///
856    /// Note that we eliminate the variables which have this type in a micro-pass.
857    /// As statements don't have types, this type disappears eventually disappears
858    /// from the AST.
859    Never,
860    // We don't support floating point numbers on purpose (for now)
861    /// A borrow
862    Ref(Region, Ty, RefKind),
863    /// A raw pointer.
864    RawPtr(Ty, RefKind),
865    /// A trait associated type
866    ///
867    /// Ex.:
868    /// ```text
869    /// trait Foo {
870    ///   type Bar; // type associated to the trait Foo
871    /// }
872    /// ```
873    TraitType(TraitRef, TraitItemName),
874    /// `dyn Trait`
875    DynTrait(DynPredicate),
876    /// Function pointer type. This is a literal pointer to a region of memory that
877    /// contains a callable function.
878    /// This is a function signature with limited generics: it only supports lifetime generics, not
879    /// other kinds of generics.
880    FnPtr(RegionBinder<(Vec<Ty>, Ty)>),
881    /// The unique type associated with each function item. Each function item is given
882    /// a unique generic type that takes as input the function's early-bound generics. This type
883    /// is not generally nameable in Rust; it's a ZST (there's a unique value), and a value of that type
884    /// can be cast to a function pointer or passed to functions that expect `FnOnce`/`FnMut`/`Fn` parameters.
885    /// There's a binder here because charon function items take both early and late-bound
886    /// lifetimes as arguments; given that the type here is polymorpohic in the late-bound
887    /// variables (those that could appear in a function pointer type like `for<'a> fn(&'a u32)`),
888    /// we need to bind them here.
889    FnDef(RegionBinder<FnPtr>),
890    /// As a marker of taking out metadata from a given type
891    /// The internal type is assumed to be a type variable
892    PtrMetadata(Ty),
893    /// A type that could not be computed or was incorrect.
894    #[drive(skip)]
895    Error(String),
896}
897
898/// Builtin types identifiers.
899///
900/// WARNING: for now, all the built-in types are covariant in the generic
901/// parameters (if there are). Adding types which don't satisfy this
902/// will require to update the code abstracting the signatures (to properly
903/// take into account the lifetime constraints).
904///
905/// TODO: update to not hardcode the types (except `Box` maybe) and be more
906/// modular.
907/// TODO: move to builtins.rs?
908#[derive(
909    Debug,
910    PartialEq,
911    Eq,
912    Clone,
913    Copy,
914    EnumIsA,
915    EnumAsGetters,
916    VariantName,
917    Serialize,
918    Deserialize,
919    Drive,
920    DriveMut,
921    Hash,
922    Ord,
923    PartialOrd,
924)]
925#[charon::variants_prefix("T")]
926pub enum BuiltinTy {
927    /// Boxes are de facto a primitive type.
928    Box,
929    /// Primitive type
930    Array,
931    /// Primitive type
932    Slice,
933    /// Primitive type
934    Str,
935}
936
937#[derive(
938    Debug,
939    Copy,
940    Clone,
941    PartialEq,
942    Eq,
943    PartialOrd,
944    Ord,
945    Hash,
946    Serialize,
947    Deserialize,
948    Drive,
949    DriveMut,
950)]
951pub enum ClosureKind {
952    Fn,
953    FnMut,
954    FnOnce,
955}
956
957impl ClosureKind {
958    // pub fn trait_name(self) -> &'static str {}
959    pub fn method_name(self) -> &'static str {
960        match self {
961            ClosureKind::FnOnce => "call_once",
962            ClosureKind::FnMut => "call_mut",
963            ClosureKind::Fn => "call",
964        }
965    }
966}
967
968/// Additional information for closures.
969#[derive(Debug, Clone, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut)]
970pub struct ClosureInfo {
971    #[serde_state(stateless)]
972    pub kind: ClosureKind,
973    /// The `FnOnce` implementation of this closure -- always exists.
974    pub fn_once_impl: RegionBinder<TraitImplRef>,
975    /// The `FnMut` implementation of this closure, if any.
976    pub fn_mut_impl: Option<RegionBinder<TraitImplRef>>,
977    /// The `Fn` implementation of this closure, if any.
978    pub fn_impl: Option<RegionBinder<TraitImplRef>>,
979    /// The signature of the function that this closure represents.
980    pub signature: RegionBinder<(Vec<Ty>, Ty)>,
981}
982
983/// A function signature.
984#[derive(Debug, Clone, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut)]
985pub struct FunSig {
986    /// Is the function unsafe or not
987    #[drive(skip)]
988    pub is_unsafe: bool,
989    pub generics: GenericParams,
990    pub inputs: Vec<Ty>,
991    pub output: Ty,
992}
993
994/// The contents of a `dyn Trait` type.
995#[derive(Debug, Clone, Hash, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut)]
996pub struct DynPredicate {
997    /// This binder binds a single type `T`, which is considered existentially quantified. The
998    /// predicates in the binder apply to `T` and represent the `dyn Trait` constraints.
999    /// E.g. `dyn Iterator<Item=u32> + Send` is represented as `exists<T: Iterator<Item=u32> + Send> T`.
1000    ///
1001    /// Only the first trait clause may have methods. We use the vtable of this trait in the `dyn
1002    /// Trait` pointer metadata.
1003    pub binder: Binder<Ty>,
1004}