charon_lib/ast/
types.rs

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