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#[cfg_attr(feature = "charon_on_charon", 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(
48    Debug,
49    Clone,
50    PartialEq,
51    Eq,
52    PartialOrd,
53    Ord,
54    Hash,
55    SerializeState,
56    DeserializeState,
57    EnumIsA,
58    EnumAsGetters,
59    Drive,
60    DriveMut,
61)]
62pub enum TraitRefKind {
63    /// A specific top-level implementation item.
64    TraitImpl(TraitImplRef),
65
66    /// One of the local clauses.
67    ///
68    /// Example:
69    /// ```text
70    /// fn f<T>(...) where T : Foo
71    ///                    ^^^^^^^
72    ///                    Clause(0)
73    /// ```
74    Clause(ClauseDbVar),
75
76    /// A parent clause
77    ///
78    /// Example:
79    /// ```text
80    /// trait Foo1 {}
81    /// trait Foo2 { fn f(); }
82    ///
83    /// trait Bar : Foo1 + Foo2 {}
84    ///             ^^^^   ^^^^
85    ///                    parent clause 1
86    ///     parent clause 0
87    ///
88    /// fn g<T : Bar>(x : T) {
89    ///   x.f()
90    ///   ^^^^^
91    ///   Parent(Clause(0), 1)::f(x)
92    ///                     ^
93    ///                     parent clause 1 of clause 0
94    /// }
95    /// ```
96    ParentClause(Box<TraitRef>, TraitClauseId),
97
98    /// A clause defined on an associated type. This variant is only used during translation; after
99    /// the `lift_associated_item_clauses` pass, clauses on items become `ParentClause`s.
100    ///
101    /// Example:
102    /// ```text
103    /// trait Foo {
104    ///   type W: Bar0 + Bar1 // Bar1 contains a method bar1
105    ///                  ^^^^
106    ///               this is the clause 1 applying to W
107    /// }
108    ///
109    /// fn f<T : Foo>(x : T::W) {
110    ///   x.bar1();
111    ///   ^^^^^^^
112    ///   ItemClause(Clause(0), W, 1)
113    ///                         ^^^^
114    ///                         clause 1 from item W (from local clause 0)
115    /// }
116    /// ```
117    ItemClause(Box<TraitRef>, AssocTypeId, TraitClauseId),
118
119    /// The implicit `Self: Trait` clause. Present inside trait declarations, including trait
120    /// method declarations. Not present in trait implementations as we can use `TraitImpl` intead.
121    #[cfg_attr(feature = "charon_on_charon", charon::rename("Self"))]
122    SelfId,
123
124    /// A trait implementation that is computed by the compiler, such as for built-in trait
125    /// `Sized`. This morally points to an invisible `impl` block; as such it contains
126    /// the information we may need from one.
127    ///
128    /// Also used as a placeholder for trait clauses that were stripped by the
129    /// `--remove-adt-clauses` pass: the original `Clause` reference is replaced with a
130    /// `BuiltinOrAuto { builtin_data: RemovedAdtClause, .. }`. See
131    /// [`BuiltinImplData::RemovedAdtClause`].
132    BuiltinOrAuto {
133        #[drive(skip)]
134        builtin_data: BuiltinImplData,
135        /// Exactly like the same field on `TraitImpl`: the `TraitRef`s required to satisfy the
136        /// implied predicates on the trait declaration. E.g. since `FnMut: FnOnce`, a built-in `T:
137        /// FnMut` impl would have a `TraitRef` for `T: FnOnce`.
138        parent_trait_refs: IndexVec<TraitClauseId, TraitRef>,
139        /// The values of the associated types for this trait.
140        types: IndexMap<AssocTypeId, TraitAssocTyImpl>,
141    },
142
143    /// The automatically-generated implementation for `dyn Trait`.
144    Dyn,
145
146    /// For error reporting.
147    #[cfg_attr(feature = "charon_on_charon", charon::rename("UnknownTrait"))]
148    #[drive(skip)]
149    Unknown(String),
150}
151
152/// Describes a built-in impl. Mostly lists the implemented trait, sometimes with more details
153/// about the contents of the implementation.
154#[derive(
155    Debug,
156    Clone,
157    PartialEq,
158    Eq,
159    PartialOrd,
160    Ord,
161    Hash,
162    SerializeState,
163    DeserializeState,
164    Drive,
165    DriveMut,
166)]
167#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Builtin"))]
168pub enum BuiltinImplData {
169    /// Auto traits (defined with `auto trait ...`, also `Unpin`).
170    Auto,
171
172    Sized,
173    MetaSized,
174    PointeeSized,
175
176    Copy,
177    Clone,
178
179    Tuple,
180    Transmute,
181    Unsize,
182
183    Pointee,
184    DiscriminantKind,
185
186    Fn,
187    FnMut,
188    FnOnce,
189    FnPtr,
190    AsyncFn,
191    AsyncFnMut,
192    AsyncFnOnce,
193    Coroutine,
194    Future,
195
196    /// An impl of `Destruct` for a type with no drop glue.
197    NoopDestruct,
198    /// An impl of `Destruct` for a type parameter, which we could not resolve because
199    /// `--add-drop-bounds` was not set.
200    UntrackedDestruct,
201
202    /// Placeholder used by the `--remove-adt-clauses` pass when it strips a trait clause from a
203    /// type declaration. References to the removed clause are rewritten as
204    /// `BuiltinOrAuto { builtin_data: RemovedAdtClause, .. }`.
205    RemovedAdtClause,
206}
207
208/// A reference to a trait.
209///
210/// This type is hash-consed, `TraitRefContents` contains the actual data.
211#[derive(
212    Debug,
213    Clone,
214    PartialEq,
215    Eq,
216    PartialOrd,
217    Ord,
218    Hash,
219    SerializeState,
220    DeserializeState,
221    Drive,
222    DriveMut,
223)]
224#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
225pub struct TraitRef(pub HashConsed<TraitRefContents>);
226
227#[derive(
228    Debug,
229    Clone,
230    PartialEq,
231    Eq,
232    PartialOrd,
233    Ord,
234    Hash,
235    SerializeState,
236    DeserializeState,
237    Drive,
238    DriveMut,
239)]
240pub struct TraitRefContents {
241    pub kind: TraitRefKind,
242    /// Not necessary, but useful
243    pub trait_decl_ref: PolyTraitDeclRef,
244}
245
246/// A predicate of the form `Type: Trait<Args>`.
247///
248/// About the generics, if we write:
249/// ```text
250/// impl Foo<bool> for String { ... }
251/// ```
252///
253/// The substitution is: `[String, bool]`.
254#[derive(
255    Debug,
256    Clone,
257    PartialEq,
258    Eq,
259    PartialOrd,
260    Ord,
261    Hash,
262    SerializeState,
263    DeserializeState,
264    Drive,
265    DriveMut,
266)]
267pub struct TraitDeclRef {
268    pub id: TraitDeclId,
269    pub generics: BoxedArgs,
270}
271
272/// A quantified trait predicate, e.g. `for<'a> Type<'a>: Trait<'a, Args>`.
273pub type PolyTraitDeclRef = RegionBinder<TraitDeclRef>;
274
275/// A reference to a tait impl, using the provided arguments.
276#[derive(
277    Debug,
278    Clone,
279    PartialEq,
280    Eq,
281    PartialOrd,
282    Ord,
283    Hash,
284    SerializeState,
285    DeserializeState,
286    Drive,
287    DriveMut,
288)]
289pub struct TraitImplRef {
290    pub id: TraitImplId,
291    pub generics: BoxedArgs,
292}
293
294/// .0 outlives .1
295#[derive(
296    Debug,
297    Clone,
298    PartialEq,
299    Eq,
300    PartialOrd,
301    Ord,
302    Hash,
303    SerializeState,
304    DeserializeState,
305    Drive,
306    DriveMut,
307)]
308pub struct OutlivesPred<T, U>(pub T, pub U);
309
310pub type RegionOutlives = OutlivesPred<Region, Region>;
311pub type TypeOutlives = OutlivesPred<Ty, Region>;
312
313/// A constraint over a trait associated type.
314///
315/// Example:
316/// ```text
317/// T : Foo<S = String>
318///         ^^^^^^^^^^
319/// ```
320#[derive(
321    Debug,
322    Clone,
323    PartialEq,
324    Eq,
325    PartialOrd,
326    Ord,
327    Hash,
328    SerializeState,
329    DeserializeState,
330    Drive,
331    DriveMut,
332)]
333pub struct TraitTypeConstraint {
334    pub trait_ref: TraitRef,
335    pub type_id: AssocTypeId,
336    pub ty: Ty,
337}
338
339/// A set of generic arguments.
340#[derive(
341    Clone, PartialEq, Eq, PartialOrd, Ord, Hash, SerializeState, DeserializeState, Drive, DriveMut,
342)]
343pub struct GenericArgs {
344    pub regions: IndexVec<RegionId, Region>,
345    pub types: IndexVec<TypeVarId, Ty>,
346    pub const_generics: IndexVec<ConstGenericVarId, ConstantExpr>,
347    pub trait_refs: IndexVec<TraitClauseId, TraitRef>,
348}
349
350pub type BoxedArgs = Box<GenericArgs>;
351
352/// A value of type `T` bound by regions. We should use `binder` instead but this causes name clash
353/// issues in the derived ocaml visitors.
354#[derive(
355    Debug,
356    Clone,
357    PartialEq,
358    Eq,
359    PartialOrd,
360    Ord,
361    Hash,
362    SerializeState,
363    DeserializeState,
364    Drive,
365    DriveMut,
366)]
367pub struct RegionBinder<T> {
368    #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_regions"))]
369    #[serde_state(stateless)]
370    pub regions: IndexVec<RegionId, RegionParam>,
371    /// Named this way to highlight accesses to the inner value that might be handling parameters
372    /// incorrectly. Prefer using helper methods.
373    #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_value"))]
374    pub skip_binder: T,
375}
376
377#[derive(
378    Debug,
379    Clone,
380    PartialEq,
381    Eq,
382    PartialOrd,
383    Ord,
384    Hash,
385    SerializeState,
386    DeserializeState,
387    Drive,
388    DriveMut,
389)]
390#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("BK"))]
391pub enum BinderKind {
392    /// The parameters of a generic associated type.
393    TraitType(TraitDeclId, AssocTypeId),
394    /// The parameters of a trait method. Used in the `methods` lists in trait decls and trait
395    /// impls.
396    TraitMethod(TraitDeclId, TraitMethodId),
397    /// The parameters bound in a non-trait `impl` block. Used in the `Name`s of inherent methods.
398    InherentImplBlock,
399    /// Binder used for `dyn Trait` existential predicates.
400    Dyn,
401    /// Some other use of a binder outside the main Charon ast.
402    Other,
403}
404
405/// A value of type `T` bound by generic parameters. Used in any context where we're adding generic
406/// parameters that aren't on the top-level item, e.g. `for<'a>` clauses (uses `RegionBinder` for
407/// now), trait methods, GATs (TODO).
408#[derive(
409    Debug,
410    Clone,
411    PartialEq,
412    Eq,
413    PartialOrd,
414    Ord,
415    Hash,
416    SerializeState,
417    DeserializeState,
418    Drive,
419    DriveMut,
420)]
421pub struct Binder<T> {
422    #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_params"))]
423    pub params: GenericParams,
424    /// Named this way to highlight accesses to the inner value that might be handling parameters
425    /// incorrectly. Prefer using helper methods.
426    #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_value"))]
427    pub skip_binder: T,
428    /// The kind of binder this is.
429    #[cfg_attr(feature = "charon_on_charon", charon::opaque)]
430    pub kind: BinderKind,
431}
432
433/// Generic parameters for a declaration, including predicates.
434#[derive(
435    Default,
436    Clone,
437    PartialEq,
438    Eq,
439    PartialOrd,
440    Ord,
441    Hash,
442    SerializeState,
443    DeserializeState,
444    Drive,
445    DriveMut,
446)]
447pub struct GenericParams {
448    #[serde_state(stateless)]
449    pub regions: IndexVec<RegionId, RegionParam>,
450    #[serde_state(stateless)]
451    pub types: IndexVec<TypeVarId, TypeParam>,
452    pub const_generics: IndexVec<ConstGenericVarId, ConstGenericParam>,
453    // TODO: rename to match [GenericArgs]?
454    pub trait_clauses: IndexVec<TraitClauseId, TraitParam>,
455    /// The first region in the pair outlives the second region
456    pub regions_outlive: Vec<RegionBinder<RegionOutlives>>,
457    /// The type outlives the region
458    pub types_outlive: Vec<RegionBinder<TypeOutlives>>,
459    /// Constraints over trait associated types
460    pub trait_type_constraints: IndexVec<TraitTypeConstraintId, RegionBinder<TraitTypeConstraint>>,
461}
462
463/// Where a given predicate came from.
464#[derive(
465    Debug,
466    Clone,
467    PartialEq,
468    Eq,
469    PartialOrd,
470    Ord,
471    Hash,
472    SerializeState,
473    DeserializeState,
474    Drive,
475    DriveMut,
476)]
477pub enum PredicateOrigin {
478    // Note: we use this for globals too, but that's only available with an unstable feature.
479    // ```
480    // fn function<T: Clone>() {}
481    // fn function<T>() where T: Clone {}
482    // const NONE<T: Copy>: Option<T> = None;
483    // ```
484    WhereClauseOnFn,
485    // ```
486    // struct Struct<T: Clone> {}
487    // struct Struct<T> where T: Clone {}
488    // type TypeAlias<T: Clone> = ...;
489    // ```
490    WhereClauseOnType,
491    // Note: this is both trait impls and inherent impl blocks.
492    // ```
493    // impl<T: Clone> Type<T> {}
494    // impl<T> Type<T> where T: Clone {}
495    // impl<T> Trait for Type<T> where T: Clone {}
496    // ```
497    WhereClauseOnImpl,
498    // The special `Self: Trait` clause which is in scope inside the definition of `Foo` or an
499    // implementation of it.
500    // ```
501    // trait Trait {}
502    // ```
503    TraitSelf,
504    // Note: this also includes supertrait constraints.
505    // ```
506    // trait Trait<T: Clone> {}
507    // trait Trait<T> where T: Clone {}
508    // trait Trait: Clone {}
509    // ```
510    WhereClauseOnTrait,
511    // ```
512    // trait Trait {
513    //     type AssocType: Clone;
514    // }
515    // ```
516    TraitItem(AssocTypeId),
517    /// Clauses that are part of a `dyn Trait` type.
518    #[cfg_attr(feature = "charon_on_charon", charon::rename("OriginDyn"))]
519    Dyn,
520}
521
522// rustc counts bytes in layouts as u64
523pub type ByteCount = u64;
524
525/// Simplified layout of a single variant.
526///
527/// Maps fields to their offset within the layout.
528#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Drive, DriveMut)]
529pub struct VariantLayout {
530    /// The offset of each field.
531    #[drive(skip)]
532    pub field_offsets: IndexVec<FieldId, ByteCount>,
533    /// Whether the variant is uninhabited, i.e. has any valid possible value.
534    /// Note that uninhabited types can have arbitrary layouts.
535    #[drive(skip)]
536    pub uninhabited: bool,
537    /// How to write the tag when constructing this variant. Each entry means: write `value` at
538    /// byte `offset`. Mirrors MiniRust's `Variant::tagger`.
539    #[drive(skip)]
540    pub tagger: Vec<(ByteCount, ScalarValue)>,
541}
542
543/// Decision tree used to determine the active variant by reading memory. Mirrors MiniRust's
544/// `Discriminator`.
545#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
546pub enum Discriminator {
547    /// The variant is known.
548    Known(VariantId),
549    /// No valid variant (e.g., invalid tag value).
550    Invalid,
551    /// Branch on an integer value read from memory at `offset`.
552    Branch {
553        /// Byte offset to read from.
554        offset: ByteCount,
555        /// Integer type to read.
556        int_ty: IntegerTy,
557        /// If the integer is in one of these ranges, continue with the given `Discriminator`. The
558        /// ranges are sorted.
559        children: Vec<(std::ops::RangeInclusive<ScalarValue>, Discriminator)>,
560        /// Fallback if no range in `children` matches.
561        fallback: Box<Discriminator>,
562    },
563}
564
565/// Simplified type layout information.
566///
567/// Does not include information about niches.
568/// If the type does not have a fully known layout (e.g. it is ?Sized)
569/// some of the layout parts are not available.
570#[derive(Debug, Clone, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut)]
571pub struct Layout {
572    /// The size of the type in bytes.
573    #[drive(skip)]
574    pub size: Option<ByteCount>,
575    /// The alignment, in bytes.
576    #[drive(skip)]
577    pub align: Option<ByteCount>,
578    /// Decision tree that determines the active variant by reading memory. Only `Some` for enums.
579    #[drive(skip)]
580    #[serde_state(stateless)]
581    pub discriminator: Option<Discriminator>,
582    /// Whether the type is uninhabited, i.e. has any valid value at all.
583    /// Note that uninhabited types can have arbitrary layouts: `(u32, !)` has space for the `u32`
584    /// and `enum E2 { A, B(!), C(i32, !) }` may have space for a discriminant.
585    #[drive(skip)]
586    pub uninhabited: bool,
587    /// Map from `VariantId` to the corresponding field layouts. Some variants don't have a
588    /// meaningful layout due to being uninhabited (though an uninhabited variant may have a
589    /// layout). Structs and unions are modeled as having exactly one variant.
590    #[serde_state(stateless)]
591    pub variant_layouts: IndexVec<VariantId, Option<VariantLayout>>,
592    /// The representation options of this type declaration as annotated by the user.
593    #[drive(skip)]
594    #[serde_state(stateless)]
595    pub repr: ReprOptions,
596}
597
598/// The metadata stored in a pointer. That's the information stored in pointers alongside
599/// their address. It's empty for `Sized` types, and interesting for unsized
600/// aka dynamically-sized types.
601#[derive(
602    Debug,
603    Clone,
604    PartialEq,
605    Eq,
606    PartialOrd,
607    Ord,
608    Hash,
609    SerializeState,
610    DeserializeState,
611    Drive,
612    DriveMut,
613)]
614#[serde_state(default_state = ())]
615pub enum PtrMetadata {
616    /// Types that need no metadata, namely `T: Sized` types.
617    #[cfg_attr(feature = "charon_on_charon", charon::rename("NoMetadata"))]
618    None,
619    /// Metadata for `[T]` and `str`, and user-defined types
620    /// that directly or indirectly contain one of the two.
621    /// Of type `usize`.
622    /// Notably, length for `[T]` denotes the number of elements in the slice.
623    /// While for `str` it denotes the number of bytes in the string.
624    Length,
625    /// Metadata for `dyn Trait`, referring to the vtable struct. Has type `&'static vtable`
626    VTable(TypeDeclRef),
627    /// Unknown due to generics, but will inherit from the given type.
628    /// This is consistent with `<Ty as Pointee>::Metadata`.
629    /// Of type `TyKind::Metadata(Ty)`.
630    InheritFrom(Ty),
631}
632
633/// Describes which layout algorithm is used for representing the corresponding type.
634/// Depends on the `#[repr(...)]` used.
635#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
636pub enum ReprAlgorithm {
637    /// The default layout algorithm. Used without an explicit `Ĺ—epr` or for `repr(Rust)`.
638    #[default]
639    Rust,
640    /// The C layout algorithm as enforced by `repr(C)`.
641    C,
642}
643
644/// Describes modifiers to the alignment and packing of the corresponding type.
645/// Represents `repr(align(n))` and `repr(packed(n))`.
646#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
647pub enum AlignmentModifier {
648    Align(ByteCount),
649    Pack(ByteCount),
650}
651
652/// The representation options as annotated by the user.
653///
654/// NOTE: This does not include less common/unstable representations such as `#[repr(simd)]`
655/// or the compiler internal `#[repr(linear)]`. Similarly, enum discriminant representations
656/// are encoded in [`Variant::discriminant`] and [`Discriminator`] instead.
657/// This only stores whether the discriminant type was derived from an explicit annotation.
658#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
659pub struct ReprOptions {
660    pub repr_algo: ReprAlgorithm,
661    pub align_modif: Option<AlignmentModifier>,
662    pub transparent: bool,
663    pub explicit_discr_type: bool,
664}
665
666/// A type declaration.
667///
668/// Types can be opaque or transparent.
669///
670/// Transparent types are local types not marked as opaque.
671/// Opaque types are the others: local types marked as opaque, and non-local
672/// types (coming from external dependencies).
673///
674/// In case the type is transparent, the declaration also contains the
675/// type definition (see [TypeDeclKind]).
676///
677/// A type can only be an ADT (structure or enumeration), as type aliases are
678/// inlined in MIR.
679#[derive(Debug, PartialEq, Eq, Clone, SerializeState, DeserializeState, Drive, DriveMut)]
680#[serde_state(state_implements = HashConsSerializerState)]
681pub struct TypeDecl {
682    pub def_id: TypeDeclId,
683    /// Meta information associated with the item.
684    pub item_meta: ItemMeta,
685    pub generics: GenericParams,
686    /// The context of the type: distinguishes top-level items from closure-related items.
687    pub src: ItemSource,
688    /// The type kind: enum, struct, or opaque.
689    pub kind: TypeDeclKind,
690    /// The layout of the type for each target. Information may be partial because of generics or
691    /// dynamically-sized types. If we cannot compute a layout, the target has no entry.
692    #[serde(with = "SeqHashMapToArray::<TargetTriple, Layout>")]
693    pub layout: SeqHashMap<TargetTriple, Layout>,
694    /// The metadata associated with a pointer to the type.
695    pub ptr_metadata: PtrMetadata,
696}
697
698generate_index_type!(VariantId, "Variant");
699generate_index_type!(FieldId, "Field");
700
701#[derive(
702    Debug,
703    PartialEq,
704    Eq,
705    Clone,
706    EnumIsA,
707    EnumAsGetters,
708    SerializeState,
709    DeserializeState,
710    Drive,
711    DriveMut,
712)]
713pub enum TypeDeclKind {
714    Struct(IndexVec<FieldId, Field>),
715    Enum(IndexVec<VariantId, Variant>),
716    Union(IndexVec<FieldId, Field>),
717    /// An opaque type.
718    ///
719    /// Either a local type marked as opaque, or an external type.
720    Opaque,
721    /// An alias to another type. This only shows up in the top-level list of items, as rustc
722    /// inlines uses of type aliases everywhere else.
723    Alias(Ty),
724    /// Used if an error happened during the extraction, and we don't panic
725    /// on error.
726    #[cfg_attr(feature = "charon_on_charon", charon::rename("TDeclError"))]
727    #[drive(skip)]
728    Error(String),
729}
730
731#[derive(Debug, PartialEq, Eq, Clone, SerializeState, DeserializeState, Drive, DriveMut)]
732#[serde_state(stateless)]
733pub struct Variant {
734    pub id: VariantId,
735    pub span: Span,
736    #[drive(skip)]
737    pub attr_info: AttrInfo,
738    #[cfg_attr(feature = "charon_on_charon", charon::rename("variant_name"))]
739    #[drive(skip)]
740    pub name: String,
741    #[serde_state(stateful)]
742    pub fields: IndexVec<FieldId, Field>,
743    /// The discriminant value outputted by `std::mem::discriminant` for this variant. This can be
744    /// different than the value stored in memory (called `tag`); that one is described by
745    /// [`Discriminator`] and [`VariantLayout::tagger`].
746    pub discriminant: Literal,
747}
748
749#[derive(Debug, PartialEq, Eq, Clone, SerializeState, DeserializeState, Drive, DriveMut)]
750#[serde_state(stateless)]
751pub struct Field {
752    pub span: Span,
753    #[drive(skip)]
754    pub attr_info: AttrInfo,
755    #[cfg_attr(feature = "charon_on_charon", charon::rename("field_name"))]
756    #[drive(skip)]
757    pub name: Option<String>,
758    #[cfg_attr(feature = "charon_on_charon", charon::rename("field_ty"))]
759    #[serde_state(stateful)]
760    pub ty: Ty,
761}
762
763#[derive(
764    Debug,
765    PartialEq,
766    Eq,
767    Copy,
768    Clone,
769    EnumIsA,
770    VariantName,
771    Serialize,
772    Deserialize,
773    Drive,
774    DriveMut,
775    Hash,
776    Ord,
777    PartialOrd,
778)]
779pub enum IntTy {
780    Isize,
781    I8,
782    I16,
783    I32,
784    I64,
785    I128,
786}
787
788#[derive(
789    Debug,
790    PartialEq,
791    Eq,
792    Copy,
793    Clone,
794    EnumIsA,
795    VariantName,
796    Serialize,
797    Deserialize,
798    Drive,
799    DriveMut,
800    Hash,
801    Ord,
802    PartialOrd,
803)]
804pub enum UIntTy {
805    Usize,
806    U8,
807    U16,
808    U32,
809    U64,
810    U128,
811}
812
813#[derive(
814    Debug,
815    PartialEq,
816    Eq,
817    Copy,
818    Clone,
819    EnumIsA,
820    VariantName,
821    Serialize,
822    Deserialize,
823    Drive,
824    DriveMut,
825    Hash,
826    Ord,
827    PartialOrd,
828)]
829#[cfg_attr(feature = "charon_on_charon", charon::rename("IntegerType"))]
830pub enum IntegerTy {
831    Signed(IntTy),
832    Unsigned(UIntTy),
833}
834
835#[derive(
836    Debug,
837    PartialEq,
838    Eq,
839    Copy,
840    Clone,
841    EnumIsA,
842    VariantName,
843    Serialize,
844    Deserialize,
845    Drive,
846    DriveMut,
847    Hash,
848    Ord,
849    PartialOrd,
850)]
851#[cfg_attr(feature = "charon_on_charon", charon::rename("FloatType"))]
852pub enum FloatTy {
853    F16,
854    F32,
855    F64,
856    F128,
857}
858
859#[derive(
860    Debug,
861    PartialEq,
862    Eq,
863    Clone,
864    Copy,
865    Hash,
866    VariantName,
867    EnumIsA,
868    Serialize,
869    Deserialize,
870    SerializeState,
871    DeserializeState,
872    Drive,
873    DriveMut,
874    Ord,
875    PartialOrd,
876)]
877#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("R"))]
878#[serde_state(stateless)]
879pub enum RefKind {
880    Mut,
881    Shared,
882}
883
884/// The nature of locations where a given lifetime parameter is used. If this lifetime ever flows
885/// to be used as the lifetime of a mutable reference `&'a mut` then we consider it mutable.
886#[derive(
887    Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumIsA,
888)]
889#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Lt"))]
890pub enum LifetimeMutability {
891    /// A lifetime that is used for a mutable reference.
892    Mutable,
893    /// A lifetime used only in shared references.
894    Shared,
895    /// A lifetime for which we couldn't/didn't compute mutability.
896    Unknown,
897}
898
899/// Type identifier.
900///
901/// Allows us to factorize the code for built-in types, adts and tuples
902#[derive(
903    Debug,
904    PartialEq,
905    Eq,
906    Clone,
907    Copy,
908    VariantName,
909    EnumAsGetters,
910    EnumIsA,
911    SerializeState,
912    DeserializeState,
913    Drive,
914    DriveMut,
915    Hash,
916    Ord,
917    PartialOrd,
918)]
919#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
920pub enum TypeId {
921    /// A "regular" ADT type.
922    ///
923    /// Includes transparent ADTs and opaque ADTs (local ADTs marked as opaque,
924    /// and external ADTs).
925    #[cfg_attr(feature = "charon_on_charon", charon::rename("TAdtId"))]
926    Adt(TypeDeclId),
927    Tuple,
928    /// Built-in type. Either a primitive type like array or slice, or a
929    /// non-primitive type coming from a standard library
930    /// and that we handle like a primitive type. Types falling into this
931    /// category include: Box, Vec, Cell...
932    /// The Array and Slice types were initially modelled as primitive in
933    /// the [Ty] type. We decided to move them to built-in types as it allows
934    /// for more uniform treatment throughout the codebase.
935    #[cfg_attr(feature = "charon_on_charon", charon::rename("TBuiltin"))]
936    #[serde_state(stateless)]
937    Builtin(BuiltinTy),
938}
939
940/// Reference to a type declaration or builtin type.
941#[derive(
942    Debug,
943    Clone,
944    PartialEq,
945    Eq,
946    PartialOrd,
947    Ord,
948    Hash,
949    SerializeState,
950    DeserializeState,
951    Drive,
952    DriveMut,
953)]
954pub struct TypeDeclRef {
955    pub id: TypeId,
956    pub generics: BoxedArgs,
957}
958
959/// Types of primitive values. Either an integer, bool, char
960#[derive(
961    Debug,
962    PartialEq,
963    Eq,
964    Clone,
965    Copy,
966    VariantName,
967    EnumIsA,
968    EnumAsGetters,
969    VariantIndexArity,
970    Serialize,
971    Deserialize,
972    SerializeState,
973    DeserializeState,
974    Drive,
975    DriveMut,
976    Hash,
977    Ord,
978    PartialOrd,
979)]
980#[cfg_attr(feature = "charon_on_charon", charon::rename("LiteralType"))]
981#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
982#[serde_state(stateless)]
983pub enum LiteralTy {
984    Int(IntTy),
985    UInt(UIntTy),
986    Float(FloatTy),
987    Bool,
988    Char,
989}
990
991/// A type.
992///
993/// Warning: the `DriveMut` impls of `Ty` needs to clone and re-hash the modified type to maintain
994/// the hash-consing invariant. This is expensive, avoid visiting types mutably when not needed.
995#[derive(
996    Debug,
997    Clone,
998    PartialEq,
999    Eq,
1000    PartialOrd,
1001    Ord,
1002    Hash,
1003    SerializeState,
1004    DeserializeState,
1005    Drive,
1006    DriveMut,
1007)]
1008#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
1009pub struct Ty(pub HashConsed<TyKind>);
1010
1011#[derive(
1012    Debug,
1013    Clone,
1014    PartialEq,
1015    Eq,
1016    PartialOrd,
1017    Ord,
1018    Hash,
1019    VariantName,
1020    EnumIsA,
1021    EnumAsGetters,
1022    EnumToGetters,
1023    VariantIndexArity,
1024    SerializeState,
1025    DeserializeState,
1026    Drive,
1027    DriveMut,
1028)]
1029#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
1030pub enum TyKind {
1031    /// An ADT.
1032    /// Note that here ADTs are very general. They can be:
1033    /// - user-defined ADTs
1034    /// - tuples (including `unit`, which is a 0-tuple)
1035    /// - built-in types (includes some primitive types, e.g., arrays or slices)
1036    ///
1037    /// The information on the nature of the ADT is stored in (`TypeId`)[TypeId].
1038    /// The last list is used encode const generics, e.g., the size of an array
1039    ///
1040    /// Note: this is incorrectly named: this can refer to any valid `TypeDecl` including extern
1041    /// types.
1042    Adt(TypeDeclRef),
1043    #[cfg_attr(feature = "charon_on_charon", charon::rename("TVar"))]
1044    TypeVar(TypeDbVar),
1045    Literal(LiteralTy),
1046    /// The never type, for computations which don't return. It is sometimes
1047    /// necessary for intermediate variables. For instance, if we do (coming
1048    /// from the rust documentation):
1049    /// ```text
1050    /// let num: u32 = match get_a_number() {
1051    ///     Some(num) => num,
1052    ///     None => break,
1053    /// };
1054    /// ```
1055    /// the second branch will have type `Never`. Also note that `Never`
1056    /// can be coerced to any type.
1057    ///
1058    /// Note that we eliminate the variables which have this type in a micro-pass.
1059    /// As statements don't have types, this type disappears eventually disappears
1060    /// from the AST.
1061    Never,
1062    // We don't support floating point numbers on purpose (for now)
1063    /// A borrow
1064    Ref(Region, Ty, RefKind),
1065    /// A raw pointer.
1066    RawPtr(Ty, RefKind),
1067    /// A trait associated type
1068    ///
1069    /// Ex.:
1070    /// ```text
1071    /// trait Foo {
1072    ///   type Bar; // type associated to the trait Foo
1073    /// }
1074    /// ```
1075    TraitType(TraitRef, AssocTypeId, GenericArgs),
1076    /// `dyn Trait`
1077    DynTrait(DynPredicate),
1078    /// Function pointer type. This is a literal pointer to a region of memory that
1079    /// contains a callable function.
1080    /// This is a function signature with limited generics: it only supports lifetime generics, not
1081    /// other kinds of generics.
1082    FnPtr(RegionBinder<FunSig>),
1083    /// The unique type associated with each function item. Each function item is given
1084    /// a unique generic type that takes as input the function's early-bound generics. This type
1085    /// is not generally nameable in Rust; it's a ZST (there's a unique value), and a value of that type
1086    /// can be cast to a function pointer or passed to functions that expect `FnOnce`/`FnMut`/`Fn` parameters.
1087    /// There's a binder here because charon function items take both early and late-bound
1088    /// lifetimes as arguments; given that the type here is polymorpohic in the late-bound
1089    /// variables (those that could appear in a function pointer type like `for<'a> fn(&'a u32)`),
1090    /// we need to bind them here.
1091    FnDef(RegionBinder<FnPtr>),
1092    /// As a marker of taking out metadata from a given type
1093    /// The internal type is assumed to be a type variable
1094    PtrMetadata(Ty),
1095    /// An array type `[T; N]`
1096    Array(Ty, Box<ConstantExpr>),
1097    /// A slice type `[T]`
1098    Slice(Ty),
1099    /// A pattern type. This is a newtype over the first type whose valid values are restricted by
1100    /// the pattern.
1101    Pattern(Ty, TypePattern),
1102    /// A type that could not be computed or was incorrect.
1103    #[drive(skip)]
1104    Error(String),
1105}
1106
1107/// Builtin types identifiers.
1108///
1109/// WARNING: for now, all the built-in types are covariant in the generic
1110/// parameters (if there are). Adding types which don't satisfy this
1111/// will require to update the code abstracting the signatures (to properly
1112/// take into account the lifetime constraints).
1113///
1114/// TODO: update to not hardcode the types (except `Box` maybe) and be more
1115/// modular.
1116/// TODO: move to builtins.rs?
1117#[derive(
1118    Debug,
1119    PartialEq,
1120    Eq,
1121    Clone,
1122    Copy,
1123    EnumIsA,
1124    EnumAsGetters,
1125    VariantName,
1126    Serialize,
1127    Deserialize,
1128    Drive,
1129    DriveMut,
1130    Hash,
1131    Ord,
1132    PartialOrd,
1133)]
1134#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
1135pub enum BuiltinTy {
1136    /// Boxes are de facto a primitive type.
1137    Box,
1138    /// Primitive type
1139    Str,
1140}
1141
1142#[derive(
1143    Debug,
1144    Copy,
1145    Clone,
1146    PartialEq,
1147    Eq,
1148    PartialOrd,
1149    Ord,
1150    Hash,
1151    Serialize,
1152    Deserialize,
1153    Drive,
1154    DriveMut,
1155)]
1156pub enum ClosureKind {
1157    Fn,
1158    FnMut,
1159    FnOnce,
1160}
1161
1162impl ClosureKind {
1163    // pub fn trait_name(self) -> &'static str {}
1164    pub fn method_name(self) -> &'static str {
1165        match self {
1166            ClosureKind::FnOnce => "call_once",
1167            ClosureKind::FnMut => "call_mut",
1168            ClosureKind::Fn => "call",
1169        }
1170    }
1171}
1172
1173/// Additional information for closures.
1174#[derive(
1175    Debug, Clone, PartialEq, Eq, PartialOrd, Ord, SerializeState, DeserializeState, Drive, DriveMut,
1176)]
1177pub struct ClosureInfo {
1178    #[serde_state(stateless)]
1179    pub kind: ClosureKind,
1180    /// The `FnOnce` implementation of this closure -- always exists.
1181    pub fn_once_impl: RegionBinder<TraitImplRef>,
1182    /// The `FnMut` implementation of this closure, if any.
1183    pub fn_mut_impl: Option<RegionBinder<TraitImplRef>>,
1184    /// The `Fn` implementation of this closure, if any.
1185    pub fn_impl: Option<RegionBinder<TraitImplRef>>,
1186    /// The signature of the function that this closure represents.
1187    pub signature: RegionBinder<FunSig>,
1188}
1189
1190/// A function signature.
1191#[derive(
1192    Debug,
1193    Clone,
1194    PartialEq,
1195    Eq,
1196    PartialOrd,
1197    Ord,
1198    Hash,
1199    SerializeState,
1200    DeserializeState,
1201    Drive,
1202    DriveMut,
1203)]
1204pub struct FunSig {
1205    /// Is the function unsafe or not
1206    #[drive(skip)]
1207    pub is_unsafe: bool,
1208    /// The calling convention of this function.
1209    #[drive(skip)]
1210    pub abi: Abi,
1211    /// Whether this is a C-variadic function (its last parameter is `...`).
1212    #[drive(skip)]
1213    pub is_variadic: bool,
1214    pub inputs: Vec<Ty>,
1215    pub output: Ty,
1216}
1217
1218#[derive(
1219    Debug,
1220    Clone,
1221    PartialEq,
1222    Eq,
1223    PartialOrd,
1224    Ord,
1225    Hash,
1226    VariantName,
1227    EnumIsA,
1228    SerializeState,
1229    DeserializeState,
1230    Drive,
1231    DriveMut,
1232)]
1233#[serde_state(stateless)]
1234#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Abi"))]
1235pub enum Abi {
1236    Rust,
1237    C,
1238    /// Rust's spelling for the ABI, e.g. "C-unwind" or "system".
1239    Other(#[drive(skip)] ustr::Ustr),
1240}
1241
1242impl Abi {
1243    pub fn rust() -> Self {
1244        Self::Rust
1245    }
1246
1247    pub fn rust_name(&self) -> &str {
1248        match self {
1249            Self::Rust => "Rust",
1250            Self::C => "C",
1251            Self::Other(name) => name.as_str(),
1252        }
1253    }
1254}
1255
1256/// The contents of a `dyn Trait` type.
1257#[derive(
1258    Debug,
1259    Clone,
1260    PartialEq,
1261    Eq,
1262    PartialOrd,
1263    Ord,
1264    Hash,
1265    SerializeState,
1266    DeserializeState,
1267    Drive,
1268    DriveMut,
1269)]
1270pub struct DynPredicate {
1271    /// This binder binds a single type `T`, which is considered existentially quantified. The
1272    /// predicates in the binder apply to `T` and represent the `dyn Trait` constraints.
1273    /// E.g. `dyn Iterator<Item=u32> + Send` is represented as `exists<T: Iterator<Item=u32> + Send> T`.
1274    ///
1275    /// Only the first trait clause may have methods. We use the vtable of this trait in the `dyn
1276    /// Trait` pointer metadata.
1277    pub binder: Binder<Ty>,
1278}
1279
1280/// A type-level pattern used by [`TyKind::Pattern`].
1281#[derive(
1282    Debug,
1283    Clone,
1284    PartialEq,
1285    Eq,
1286    PartialOrd,
1287    Ord,
1288    Hash,
1289    VariantName,
1290    EnumIsA,
1291    SerializeState,
1292    DeserializeState,
1293    Drive,
1294    DriveMut,
1295)]
1296#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
1297pub enum TypePattern {
1298    Range(Box<ConstantExpr>, Box<ConstantExpr>),
1299    OrPattern(Vec<TypePattern>),
1300    NotNull,
1301}