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