Skip to main content

charon_lib/ast/
types.rs

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