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