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