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