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