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