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