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#[cfg_attr(feature = "charon_on_charon", 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(
48 Debug,
49 Clone,
50 PartialEq,
51 Eq,
52 PartialOrd,
53 Ord,
54 Hash,
55 SerializeState,
56 DeserializeState,
57 EnumIsA,
58 EnumAsGetters,
59 Drive,
60 DriveMut,
61)]
62pub enum TraitRefKind {
63 /// A specific top-level implementation item.
64 TraitImpl(TraitImplRef),
65
66 /// One of the local clauses.
67 ///
68 /// Example:
69 /// ```text
70 /// fn f<T>(...) where T : Foo
71 /// ^^^^^^^
72 /// Clause(0)
73 /// ```
74 Clause(ClauseDbVar),
75
76 /// A parent clause
77 ///
78 /// Example:
79 /// ```text
80 /// trait Foo1 {}
81 /// trait Foo2 { fn f(); }
82 ///
83 /// trait Bar : Foo1 + Foo2 {}
84 /// ^^^^ ^^^^
85 /// parent clause 1
86 /// parent clause 0
87 ///
88 /// fn g<T : Bar>(x : T) {
89 /// x.f()
90 /// ^^^^^
91 /// Parent(Clause(0), 1)::f(x)
92 /// ^
93 /// parent clause 1 of clause 0
94 /// }
95 /// ```
96 ParentClause(Box<TraitRef>, TraitClauseId),
97
98 /// A clause defined on an associated type. This variant is only used during translation; after
99 /// the `lift_associated_item_clauses` pass, clauses on items become `ParentClause`s.
100 ///
101 /// Example:
102 /// ```text
103 /// trait Foo {
104 /// type W: Bar0 + Bar1 // Bar1 contains a method bar1
105 /// ^^^^
106 /// this is the clause 1 applying to W
107 /// }
108 ///
109 /// fn f<T : Foo>(x : T::W) {
110 /// x.bar1();
111 /// ^^^^^^^
112 /// ItemClause(Clause(0), W, 1)
113 /// ^^^^
114 /// clause 1 from item W (from local clause 0)
115 /// }
116 /// ```
117 ItemClause(Box<TraitRef>, AssocTypeId, TraitClauseId),
118
119 /// The implicit `Self: Trait` clause. Present inside trait declarations, including trait
120 /// method declarations. Not present in trait implementations as we can use `TraitImpl` intead.
121 #[cfg_attr(feature = "charon_on_charon", charon::rename("Self"))]
122 SelfId,
123
124 /// A trait implementation that is computed by the compiler, such as for built-in trait
125 /// `Sized`. This morally points to an invisible `impl` block; as such it contains
126 /// the information we may need from one.
127 ///
128 /// Also used as a placeholder for trait clauses that were stripped by the
129 /// `--remove-adt-clauses` pass: the original `Clause` reference is replaced with a
130 /// `BuiltinOrAuto { builtin_data: RemovedAdtClause, .. }`. See
131 /// [`BuiltinImplData::RemovedAdtClause`].
132 BuiltinOrAuto {
133 #[drive(skip)]
134 builtin_data: BuiltinImplData,
135 /// Exactly like the same field on `TraitImpl`: the `TraitRef`s required to satisfy the
136 /// implied predicates on the trait declaration. E.g. since `FnMut: FnOnce`, a built-in `T:
137 /// FnMut` impl would have a `TraitRef` for `T: FnOnce`.
138 parent_trait_refs: IndexVec<TraitClauseId, TraitRef>,
139 /// The values of the associated types for this trait.
140 types: IndexMap<AssocTypeId, TraitAssocTyImpl>,
141 },
142
143 /// The automatically-generated implementation for `dyn Trait`.
144 Dyn,
145
146 /// For error reporting.
147 #[cfg_attr(feature = "charon_on_charon", charon::rename("UnknownTrait"))]
148 #[drive(skip)]
149 Unknown(String),
150}
151
152/// Describes a built-in impl. Mostly lists the implemented trait, sometimes with more details
153/// about the contents of the implementation.
154#[derive(
155 Debug,
156 Clone,
157 PartialEq,
158 Eq,
159 PartialOrd,
160 Ord,
161 Hash,
162 SerializeState,
163 DeserializeState,
164 Drive,
165 DriveMut,
166)]
167#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Builtin"))]
168pub enum BuiltinImplData {
169 /// Auto traits (defined with `auto trait ...`, also `Unpin`).
170 Auto,
171
172 Sized,
173 MetaSized,
174 PointeeSized,
175
176 Copy,
177 Clone,
178
179 Tuple,
180 Transmute,
181 Unsize,
182
183 Pointee,
184 DiscriminantKind,
185
186 Fn,
187 FnMut,
188 FnOnce,
189 FnPtr,
190 AsyncFn,
191 AsyncFnMut,
192 AsyncFnOnce,
193 Coroutine,
194 Future,
195
196 /// An impl of `Destruct` for a type with no drop glue.
197 NoopDestruct,
198 /// An impl of `Destruct` for a type parameter, which we could not resolve because
199 /// `--add-drop-bounds` was not set.
200 UntrackedDestruct,
201
202 /// Placeholder used by the `--remove-adt-clauses` pass when it strips a trait clause from a
203 /// type declaration. References to the removed clause are rewritten as
204 /// `BuiltinOrAuto { builtin_data: RemovedAdtClause, .. }`.
205 RemovedAdtClause,
206}
207
208/// A reference to a trait.
209///
210/// This type is hash-consed, `TraitRefContents` contains the actual data.
211#[derive(
212 Debug,
213 Clone,
214 PartialEq,
215 Eq,
216 PartialOrd,
217 Ord,
218 Hash,
219 SerializeState,
220 DeserializeState,
221 Drive,
222 DriveMut,
223)]
224#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
225pub struct TraitRef(pub HashConsed<TraitRefContents>);
226
227#[derive(
228 Debug,
229 Clone,
230 PartialEq,
231 Eq,
232 PartialOrd,
233 Ord,
234 Hash,
235 SerializeState,
236 DeserializeState,
237 Drive,
238 DriveMut,
239)]
240pub struct TraitRefContents {
241 pub kind: TraitRefKind,
242 /// Not necessary, but useful
243 pub trait_decl_ref: PolyTraitDeclRef,
244}
245
246/// A predicate of the form `Type: Trait<Args>`.
247///
248/// About the generics, if we write:
249/// ```text
250/// impl Foo<bool> for String { ... }
251/// ```
252///
253/// The substitution is: `[String, bool]`.
254#[derive(
255 Debug,
256 Clone,
257 PartialEq,
258 Eq,
259 PartialOrd,
260 Ord,
261 Hash,
262 SerializeState,
263 DeserializeState,
264 Drive,
265 DriveMut,
266)]
267pub struct TraitDeclRef {
268 pub id: TraitDeclId,
269 pub generics: BoxedArgs,
270}
271
272/// A quantified trait predicate, e.g. `for<'a> Type<'a>: Trait<'a, Args>`.
273pub type PolyTraitDeclRef = RegionBinder<TraitDeclRef>;
274
275/// A reference to a tait impl, using the provided arguments.
276#[derive(
277 Debug,
278 Clone,
279 PartialEq,
280 Eq,
281 PartialOrd,
282 Ord,
283 Hash,
284 SerializeState,
285 DeserializeState,
286 Drive,
287 DriveMut,
288)]
289pub struct TraitImplRef {
290 pub id: TraitImplId,
291 pub generics: BoxedArgs,
292}
293
294/// .0 outlives .1
295#[derive(
296 Debug,
297 Clone,
298 PartialEq,
299 Eq,
300 PartialOrd,
301 Ord,
302 Hash,
303 SerializeState,
304 DeserializeState,
305 Drive,
306 DriveMut,
307)]
308pub struct OutlivesPred<T, U>(pub T, pub U);
309
310pub type RegionOutlives = OutlivesPred<Region, Region>;
311pub type TypeOutlives = OutlivesPred<Ty, Region>;
312
313/// A constraint over a trait associated type.
314///
315/// Example:
316/// ```text
317/// T : Foo<S = String>
318/// ^^^^^^^^^^
319/// ```
320#[derive(
321 Debug,
322 Clone,
323 PartialEq,
324 Eq,
325 PartialOrd,
326 Ord,
327 Hash,
328 SerializeState,
329 DeserializeState,
330 Drive,
331 DriveMut,
332)]
333pub struct TraitTypeConstraint {
334 pub trait_ref: TraitRef,
335 pub type_id: AssocTypeId,
336 pub ty: Ty,
337}
338
339/// A set of generic arguments.
340#[derive(
341 Clone, PartialEq, Eq, PartialOrd, Ord, Hash, SerializeState, DeserializeState, Drive, DriveMut,
342)]
343pub struct GenericArgs {
344 pub regions: IndexVec<RegionId, Region>,
345 pub types: IndexVec<TypeVarId, Ty>,
346 pub const_generics: IndexVec<ConstGenericVarId, ConstantExpr>,
347 pub trait_refs: IndexVec<TraitClauseId, TraitRef>,
348}
349
350pub type BoxedArgs = Box<GenericArgs>;
351
352/// A value of type `T` bound by regions. We should use `binder` instead but this causes name clash
353/// issues in the derived ocaml visitors.
354#[derive(
355 Debug,
356 Clone,
357 PartialEq,
358 Eq,
359 PartialOrd,
360 Ord,
361 Hash,
362 SerializeState,
363 DeserializeState,
364 Drive,
365 DriveMut,
366)]
367pub struct RegionBinder<T> {
368 #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_regions"))]
369 #[serde_state(stateless)]
370 pub regions: IndexVec<RegionId, RegionParam>,
371 /// Named this way to highlight accesses to the inner value that might be handling parameters
372 /// incorrectly. Prefer using helper methods.
373 #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_value"))]
374 pub skip_binder: T,
375}
376
377#[derive(
378 Debug,
379 Clone,
380 PartialEq,
381 Eq,
382 PartialOrd,
383 Ord,
384 Hash,
385 SerializeState,
386 DeserializeState,
387 Drive,
388 DriveMut,
389)]
390#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("BK"))]
391pub enum BinderKind {
392 /// The parameters of a generic associated type.
393 TraitType(TraitDeclId, AssocTypeId),
394 /// The parameters of a trait method. Used in the `methods` lists in trait decls and trait
395 /// impls.
396 TraitMethod(TraitDeclId, TraitMethodId),
397 /// The parameters bound in a non-trait `impl` block. Used in the `Name`s of inherent methods.
398 InherentImplBlock,
399 /// Binder used for `dyn Trait` existential predicates.
400 Dyn,
401 /// Some other use of a binder outside the main Charon ast.
402 Other,
403}
404
405/// A value of type `T` bound by generic parameters. Used in any context where we're adding generic
406/// parameters that aren't on the top-level item, e.g. `for<'a>` clauses (uses `RegionBinder` for
407/// now), trait methods, GATs (TODO).
408#[derive(
409 Debug,
410 Clone,
411 PartialEq,
412 Eq,
413 PartialOrd,
414 Ord,
415 Hash,
416 SerializeState,
417 DeserializeState,
418 Drive,
419 DriveMut,
420)]
421pub struct Binder<T> {
422 #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_params"))]
423 pub params: GenericParams,
424 /// Named this way to highlight accesses to the inner value that might be handling parameters
425 /// incorrectly. Prefer using helper methods.
426 #[cfg_attr(feature = "charon_on_charon", charon::rename("binder_value"))]
427 pub skip_binder: T,
428 /// The kind of binder this is.
429 #[cfg_attr(feature = "charon_on_charon", charon::opaque)]
430 pub kind: BinderKind,
431}
432
433/// Generic parameters for a declaration, including predicates.
434#[derive(
435 Default,
436 Clone,
437 PartialEq,
438 Eq,
439 PartialOrd,
440 Ord,
441 Hash,
442 SerializeState,
443 DeserializeState,
444 Drive,
445 DriveMut,
446)]
447pub struct GenericParams {
448 #[serde_state(stateless)]
449 pub regions: IndexVec<RegionId, RegionParam>,
450 #[serde_state(stateless)]
451 pub types: IndexVec<TypeVarId, TypeParam>,
452 pub const_generics: IndexVec<ConstGenericVarId, ConstGenericParam>,
453 // TODO: rename to match [GenericArgs]?
454 pub trait_clauses: IndexVec<TraitClauseId, TraitParam>,
455 /// The first region in the pair outlives the second region
456 pub regions_outlive: Vec<RegionBinder<RegionOutlives>>,
457 /// The type outlives the region
458 pub types_outlive: Vec<RegionBinder<TypeOutlives>>,
459 /// Constraints over trait associated types
460 pub trait_type_constraints: IndexVec<TraitTypeConstraintId, RegionBinder<TraitTypeConstraint>>,
461}
462
463/// Where a given predicate came from.
464#[derive(
465 Debug,
466 Clone,
467 PartialEq,
468 Eq,
469 PartialOrd,
470 Ord,
471 Hash,
472 SerializeState,
473 DeserializeState,
474 Drive,
475 DriveMut,
476)]
477pub enum PredicateOrigin {
478 // Note: we use this for globals too, but that's only available with an unstable feature.
479 // ```
480 // fn function<T: Clone>() {}
481 // fn function<T>() where T: Clone {}
482 // const NONE<T: Copy>: Option<T> = None;
483 // ```
484 WhereClauseOnFn,
485 // ```
486 // struct Struct<T: Clone> {}
487 // struct Struct<T> where T: Clone {}
488 // type TypeAlias<T: Clone> = ...;
489 // ```
490 WhereClauseOnType,
491 // Note: this is both trait impls and inherent impl blocks.
492 // ```
493 // impl<T: Clone> Type<T> {}
494 // impl<T> Type<T> where T: Clone {}
495 // impl<T> Trait for Type<T> where T: Clone {}
496 // ```
497 WhereClauseOnImpl,
498 // The special `Self: Trait` clause which is in scope inside the definition of `Foo` or an
499 // implementation of it.
500 // ```
501 // trait Trait {}
502 // ```
503 TraitSelf,
504 // Note: this also includes supertrait constraints.
505 // ```
506 // trait Trait<T: Clone> {}
507 // trait Trait<T> where T: Clone {}
508 // trait Trait: Clone {}
509 // ```
510 WhereClauseOnTrait,
511 // ```
512 // trait Trait {
513 // type AssocType: Clone;
514 // }
515 // ```
516 TraitItem(AssocTypeId),
517 /// Clauses that are part of a `dyn Trait` type.
518 #[cfg_attr(feature = "charon_on_charon", charon::rename("OriginDyn"))]
519 Dyn,
520}
521
522// rustc counts bytes in layouts as u64
523pub type ByteCount = u64;
524
525/// Simplified layout of a single variant.
526///
527/// Maps fields to their offset within the layout.
528#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Drive, DriveMut)]
529pub struct VariantLayout {
530 /// The offset of each field.
531 #[drive(skip)]
532 pub field_offsets: IndexVec<FieldId, ByteCount>,
533 /// Whether the variant is uninhabited, i.e. has any valid possible value.
534 /// Note that uninhabited types can have arbitrary layouts.
535 #[drive(skip)]
536 pub uninhabited: bool,
537 /// How to write the tag when constructing this variant. Each entry means: write `value` at
538 /// byte `offset`. Mirrors MiniRust's `Variant::tagger`.
539 #[drive(skip)]
540 pub tagger: Vec<(ByteCount, ScalarValue)>,
541}
542
543/// Decision tree used to determine the active variant by reading memory. Mirrors MiniRust's
544/// `Discriminator`.
545#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
546pub enum Discriminator {
547 /// The variant is known.
548 Known(VariantId),
549 /// No valid variant (e.g., invalid tag value).
550 Invalid,
551 /// Branch on an integer value read from memory at `offset`.
552 Branch {
553 /// Byte offset to read from.
554 offset: ByteCount,
555 /// Integer type to read.
556 int_ty: IntegerTy,
557 /// If the integer is in one of these ranges, continue with the given `Discriminator`. The
558 /// ranges are sorted.
559 children: Vec<(std::ops::RangeInclusive<ScalarValue>, Discriminator)>,
560 /// Fallback if no range in `children` matches.
561 fallback: Box<Discriminator>,
562 },
563}
564
565/// Simplified type layout information.
566///
567/// Does not include information about niches.
568/// If the type does not have a fully known layout (e.g. it is ?Sized)
569/// some of the layout parts are not available.
570#[derive(Debug, Clone, PartialEq, Eq, SerializeState, DeserializeState, Drive, DriveMut)]
571pub struct Layout {
572 /// The size of the type in bytes.
573 #[drive(skip)]
574 pub size: Option<ByteCount>,
575 /// The alignment, in bytes.
576 #[drive(skip)]
577 pub align: Option<ByteCount>,
578 /// Decision tree that determines the active variant by reading memory. Only `Some` for enums.
579 #[drive(skip)]
580 #[serde_state(stateless)]
581 pub discriminator: Option<Discriminator>,
582 /// Whether the type is uninhabited, i.e. has any valid value at all.
583 /// Note that uninhabited types can have arbitrary layouts: `(u32, !)` has space for the `u32`
584 /// and `enum E2 { A, B(!), C(i32, !) }` may have space for a discriminant.
585 #[drive(skip)]
586 pub uninhabited: bool,
587 /// Map from `VariantId` to the corresponding field layouts. Some variants don't have a
588 /// meaningful layout due to being uninhabited (though an uninhabited variant may have a
589 /// layout). Structs and unions are modeled as having exactly one variant.
590 #[serde_state(stateless)]
591 pub variant_layouts: IndexVec<VariantId, Option<VariantLayout>>,
592 /// The representation options of this type declaration as annotated by the user.
593 #[drive(skip)]
594 #[serde_state(stateless)]
595 pub repr: ReprOptions,
596}
597
598/// The metadata stored in a pointer. That's the information stored in pointers alongside
599/// their address. It's empty for `Sized` types, and interesting for unsized
600/// aka dynamically-sized types.
601#[derive(
602 Debug,
603 Clone,
604 PartialEq,
605 Eq,
606 PartialOrd,
607 Ord,
608 Hash,
609 SerializeState,
610 DeserializeState,
611 Drive,
612 DriveMut,
613)]
614#[serde_state(default_state = ())]
615pub enum PtrMetadata {
616 /// Types that need no metadata, namely `T: Sized` types.
617 #[cfg_attr(feature = "charon_on_charon", charon::rename("NoMetadata"))]
618 None,
619 /// Metadata for `[T]` and `str`, and user-defined types
620 /// that directly or indirectly contain one of the two.
621 /// Of type `usize`.
622 /// Notably, length for `[T]` denotes the number of elements in the slice.
623 /// While for `str` it denotes the number of bytes in the string.
624 Length,
625 /// Metadata for `dyn Trait`, referring to the vtable struct. Has type `&'static vtable`
626 VTable(TypeDeclRef),
627 /// Unknown due to generics, but will inherit from the given type.
628 /// This is consistent with `<Ty as Pointee>::Metadata`.
629 /// Of type `TyKind::Metadata(Ty)`.
630 InheritFrom(Ty),
631}
632
633/// Describes which layout algorithm is used for representing the corresponding type.
634/// Depends on the `#[repr(...)]` used.
635#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
636pub enum ReprAlgorithm {
637 /// The default layout algorithm. Used without an explicit `Ĺ—epr` or for `repr(Rust)`.
638 #[default]
639 Rust,
640 /// The C layout algorithm as enforced by `repr(C)`.
641 C,
642}
643
644/// Describes modifiers to the alignment and packing of the corresponding type.
645/// Represents `repr(align(n))` and `repr(packed(n))`.
646#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
647pub enum AlignmentModifier {
648 Align(ByteCount),
649 Pack(ByteCount),
650}
651
652/// The representation options as annotated by the user.
653///
654/// NOTE: This does not include less common/unstable representations such as `#[repr(simd)]`
655/// or the compiler internal `#[repr(linear)]`. Similarly, enum discriminant representations
656/// are encoded in [`Variant::discriminant`] and [`Discriminator`] instead.
657/// This only stores whether the discriminant type was derived from an explicit annotation.
658#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
659pub struct ReprOptions {
660 pub repr_algo: ReprAlgorithm,
661 pub align_modif: Option<AlignmentModifier>,
662 pub transparent: bool,
663 pub explicit_discr_type: bool,
664}
665
666/// A type declaration.
667///
668/// Types can be opaque or transparent.
669///
670/// Transparent types are local types not marked as opaque.
671/// Opaque types are the others: local types marked as opaque, and non-local
672/// types (coming from external dependencies).
673///
674/// In case the type is transparent, the declaration also contains the
675/// type definition (see [TypeDeclKind]).
676///
677/// A type can only be an ADT (structure or enumeration), as type aliases are
678/// inlined in MIR.
679#[derive(Debug, PartialEq, Eq, Clone, SerializeState, DeserializeState, Drive, DriveMut)]
680#[serde_state(state_implements = HashConsSerializerState)]
681pub struct TypeDecl {
682 pub def_id: TypeDeclId,
683 /// Meta information associated with the item.
684 pub item_meta: ItemMeta,
685 pub generics: GenericParams,
686 /// The context of the type: distinguishes top-level items from closure-related items.
687 pub src: ItemSource,
688 /// The type kind: enum, struct, or opaque.
689 pub kind: TypeDeclKind,
690 /// The layout of the type for each target. Information may be partial because of generics or
691 /// dynamically-sized types. If we cannot compute a layout, the target has no entry.
692 #[serde(with = "SeqHashMapToArray::<TargetTriple, Layout>")]
693 pub layout: SeqHashMap<TargetTriple, Layout>,
694 /// The metadata associated with a pointer to the type.
695 pub ptr_metadata: PtrMetadata,
696}
697
698generate_index_type!(VariantId, "Variant");
699generate_index_type!(FieldId, "Field");
700
701#[derive(
702 Debug,
703 PartialEq,
704 Eq,
705 Clone,
706 EnumIsA,
707 EnumAsGetters,
708 SerializeState,
709 DeserializeState,
710 Drive,
711 DriveMut,
712)]
713pub enum TypeDeclKind {
714 Struct(IndexVec<FieldId, Field>),
715 Enum(IndexVec<VariantId, Variant>),
716 Union(IndexVec<FieldId, Field>),
717 /// An opaque type.
718 ///
719 /// Either a local type marked as opaque, or an external type.
720 Opaque,
721 /// An alias to another type. This only shows up in the top-level list of items, as rustc
722 /// inlines uses of type aliases everywhere else.
723 Alias(Ty),
724 /// Used if an error happened during the extraction, and we don't panic
725 /// on error.
726 #[cfg_attr(feature = "charon_on_charon", charon::rename("TDeclError"))]
727 #[drive(skip)]
728 Error(String),
729}
730
731#[derive(Debug, PartialEq, Eq, Clone, SerializeState, DeserializeState, Drive, DriveMut)]
732#[serde_state(stateless)]
733pub struct Variant {
734 pub id: VariantId,
735 pub span: Span,
736 #[drive(skip)]
737 pub attr_info: AttrInfo,
738 #[cfg_attr(feature = "charon_on_charon", charon::rename("variant_name"))]
739 #[drive(skip)]
740 pub name: String,
741 #[serde_state(stateful)]
742 pub fields: IndexVec<FieldId, Field>,
743 /// The discriminant value outputted by `std::mem::discriminant` for this variant. This can be
744 /// different than the value stored in memory (called `tag`); that one is described by
745 /// [`Discriminator`] and [`VariantLayout::tagger`].
746 pub discriminant: Literal,
747}
748
749#[derive(Debug, PartialEq, Eq, Clone, SerializeState, DeserializeState, Drive, DriveMut)]
750#[serde_state(stateless)]
751pub struct Field {
752 pub span: Span,
753 #[drive(skip)]
754 pub attr_info: AttrInfo,
755 #[cfg_attr(feature = "charon_on_charon", charon::rename("field_name"))]
756 #[drive(skip)]
757 pub name: Option<String>,
758 #[cfg_attr(feature = "charon_on_charon", charon::rename("field_ty"))]
759 #[serde_state(stateful)]
760 pub ty: Ty,
761}
762
763#[derive(
764 Debug,
765 PartialEq,
766 Eq,
767 Copy,
768 Clone,
769 EnumIsA,
770 VariantName,
771 Serialize,
772 Deserialize,
773 Drive,
774 DriveMut,
775 Hash,
776 Ord,
777 PartialOrd,
778)]
779pub enum IntTy {
780 Isize,
781 I8,
782 I16,
783 I32,
784 I64,
785 I128,
786}
787
788#[derive(
789 Debug,
790 PartialEq,
791 Eq,
792 Copy,
793 Clone,
794 EnumIsA,
795 VariantName,
796 Serialize,
797 Deserialize,
798 Drive,
799 DriveMut,
800 Hash,
801 Ord,
802 PartialOrd,
803)]
804pub enum UIntTy {
805 Usize,
806 U8,
807 U16,
808 U32,
809 U64,
810 U128,
811}
812
813#[derive(
814 Debug,
815 PartialEq,
816 Eq,
817 Copy,
818 Clone,
819 EnumIsA,
820 VariantName,
821 Serialize,
822 Deserialize,
823 Drive,
824 DriveMut,
825 Hash,
826 Ord,
827 PartialOrd,
828)]
829#[cfg_attr(feature = "charon_on_charon", charon::rename("IntegerType"))]
830pub enum IntegerTy {
831 Signed(IntTy),
832 Unsigned(UIntTy),
833}
834
835#[derive(
836 Debug,
837 PartialEq,
838 Eq,
839 Copy,
840 Clone,
841 EnumIsA,
842 VariantName,
843 Serialize,
844 Deserialize,
845 Drive,
846 DriveMut,
847 Hash,
848 Ord,
849 PartialOrd,
850)]
851#[cfg_attr(feature = "charon_on_charon", charon::rename("FloatType"))]
852pub enum FloatTy {
853 F16,
854 F32,
855 F64,
856 F128,
857}
858
859#[derive(
860 Debug,
861 PartialEq,
862 Eq,
863 Clone,
864 Copy,
865 Hash,
866 VariantName,
867 EnumIsA,
868 Serialize,
869 Deserialize,
870 SerializeState,
871 DeserializeState,
872 Drive,
873 DriveMut,
874 Ord,
875 PartialOrd,
876)]
877#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("R"))]
878#[serde_state(stateless)]
879pub enum RefKind {
880 Mut,
881 Shared,
882}
883
884/// The nature of locations where a given lifetime parameter is used. If this lifetime ever flows
885/// to be used as the lifetime of a mutable reference `&'a mut` then we consider it mutable.
886#[derive(
887 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumIsA,
888)]
889#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Lt"))]
890pub enum LifetimeMutability {
891 /// A lifetime that is used for a mutable reference.
892 Mutable,
893 /// A lifetime used only in shared references.
894 Shared,
895 /// A lifetime for which we couldn't/didn't compute mutability.
896 Unknown,
897}
898
899/// Type identifier.
900///
901/// Allows us to factorize the code for built-in types, adts and tuples
902#[derive(
903 Debug,
904 PartialEq,
905 Eq,
906 Clone,
907 Copy,
908 VariantName,
909 EnumAsGetters,
910 EnumIsA,
911 SerializeState,
912 DeserializeState,
913 Drive,
914 DriveMut,
915 Hash,
916 Ord,
917 PartialOrd,
918)]
919#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
920pub enum TypeId {
921 /// A "regular" ADT type.
922 ///
923 /// Includes transparent ADTs and opaque ADTs (local ADTs marked as opaque,
924 /// and external ADTs).
925 #[cfg_attr(feature = "charon_on_charon", charon::rename("TAdtId"))]
926 Adt(TypeDeclId),
927 Tuple,
928 /// Built-in type. Either a primitive type like array or slice, or a
929 /// non-primitive type coming from a standard library
930 /// and that we handle like a primitive type. Types falling into this
931 /// category include: Box, Vec, Cell...
932 /// The Array and Slice types were initially modelled as primitive in
933 /// the [Ty] type. We decided to move them to built-in types as it allows
934 /// for more uniform treatment throughout the codebase.
935 #[cfg_attr(feature = "charon_on_charon", charon::rename("TBuiltin"))]
936 #[serde_state(stateless)]
937 Builtin(BuiltinTy),
938}
939
940/// Reference to a type declaration or builtin type.
941#[derive(
942 Debug,
943 Clone,
944 PartialEq,
945 Eq,
946 PartialOrd,
947 Ord,
948 Hash,
949 SerializeState,
950 DeserializeState,
951 Drive,
952 DriveMut,
953)]
954pub struct TypeDeclRef {
955 pub id: TypeId,
956 pub generics: BoxedArgs,
957}
958
959/// Types of primitive values. Either an integer, bool, char
960#[derive(
961 Debug,
962 PartialEq,
963 Eq,
964 Clone,
965 Copy,
966 VariantName,
967 EnumIsA,
968 EnumAsGetters,
969 VariantIndexArity,
970 Serialize,
971 Deserialize,
972 SerializeState,
973 DeserializeState,
974 Drive,
975 DriveMut,
976 Hash,
977 Ord,
978 PartialOrd,
979)]
980#[cfg_attr(feature = "charon_on_charon", charon::rename("LiteralType"))]
981#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
982#[serde_state(stateless)]
983pub enum LiteralTy {
984 Int(IntTy),
985 UInt(UIntTy),
986 Float(FloatTy),
987 Bool,
988 Char,
989}
990
991/// A type.
992///
993/// Warning: the `DriveMut` impls of `Ty` needs to clone and re-hash the modified type to maintain
994/// the hash-consing invariant. This is expensive, avoid visiting types mutably when not needed.
995#[derive(
996 Debug,
997 Clone,
998 PartialEq,
999 Eq,
1000 PartialOrd,
1001 Ord,
1002 Hash,
1003 SerializeState,
1004 DeserializeState,
1005 Drive,
1006 DriveMut,
1007)]
1008#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
1009pub struct Ty(pub HashConsed<TyKind>);
1010
1011#[derive(
1012 Debug,
1013 Clone,
1014 PartialEq,
1015 Eq,
1016 PartialOrd,
1017 Ord,
1018 Hash,
1019 VariantName,
1020 EnumIsA,
1021 EnumAsGetters,
1022 EnumToGetters,
1023 VariantIndexArity,
1024 SerializeState,
1025 DeserializeState,
1026 Drive,
1027 DriveMut,
1028)]
1029#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
1030pub enum TyKind {
1031 /// An ADT.
1032 /// Note that here ADTs are very general. They can be:
1033 /// - user-defined ADTs
1034 /// - tuples (including `unit`, which is a 0-tuple)
1035 /// - built-in types (includes some primitive types, e.g., arrays or slices)
1036 ///
1037 /// The information on the nature of the ADT is stored in (`TypeId`)[TypeId].
1038 /// The last list is used encode const generics, e.g., the size of an array
1039 ///
1040 /// Note: this is incorrectly named: this can refer to any valid `TypeDecl` including extern
1041 /// types.
1042 Adt(TypeDeclRef),
1043 #[cfg_attr(feature = "charon_on_charon", charon::rename("TVar"))]
1044 TypeVar(TypeDbVar),
1045 Literal(LiteralTy),
1046 /// The never type, for computations which don't return. It is sometimes
1047 /// necessary for intermediate variables. For instance, if we do (coming
1048 /// from the rust documentation):
1049 /// ```text
1050 /// let num: u32 = match get_a_number() {
1051 /// Some(num) => num,
1052 /// None => break,
1053 /// };
1054 /// ```
1055 /// the second branch will have type `Never`. Also note that `Never`
1056 /// can be coerced to any type.
1057 ///
1058 /// Note that we eliminate the variables which have this type in a micro-pass.
1059 /// As statements don't have types, this type disappears eventually disappears
1060 /// from the AST.
1061 Never,
1062 // We don't support floating point numbers on purpose (for now)
1063 /// A borrow
1064 Ref(Region, Ty, RefKind),
1065 /// A raw pointer.
1066 RawPtr(Ty, RefKind),
1067 /// A trait associated type
1068 ///
1069 /// Ex.:
1070 /// ```text
1071 /// trait Foo {
1072 /// type Bar; // type associated to the trait Foo
1073 /// }
1074 /// ```
1075 TraitType(TraitRef, AssocTypeId, GenericArgs),
1076 /// `dyn Trait`
1077 DynTrait(DynPredicate),
1078 /// Function pointer type. This is a literal pointer to a region of memory that
1079 /// contains a callable function.
1080 /// This is a function signature with limited generics: it only supports lifetime generics, not
1081 /// other kinds of generics.
1082 FnPtr(RegionBinder<FunSig>),
1083 /// The unique type associated with each function item. Each function item is given
1084 /// a unique generic type that takes as input the function's early-bound generics. This type
1085 /// is not generally nameable in Rust; it's a ZST (there's a unique value), and a value of that type
1086 /// can be cast to a function pointer or passed to functions that expect `FnOnce`/`FnMut`/`Fn` parameters.
1087 /// There's a binder here because charon function items take both early and late-bound
1088 /// lifetimes as arguments; given that the type here is polymorpohic in the late-bound
1089 /// variables (those that could appear in a function pointer type like `for<'a> fn(&'a u32)`),
1090 /// we need to bind them here.
1091 FnDef(RegionBinder<FnPtr>),
1092 /// As a marker of taking out metadata from a given type
1093 /// The internal type is assumed to be a type variable
1094 PtrMetadata(Ty),
1095 /// An array type `[T; N]`
1096 Array(Ty, Box<ConstantExpr>),
1097 /// A slice type `[T]`
1098 Slice(Ty),
1099 /// A pattern type. This is a newtype over the first type whose valid values are restricted by
1100 /// the pattern.
1101 Pattern(Ty, TypePattern),
1102 /// A type that could not be computed or was incorrect.
1103 #[drive(skip)]
1104 Error(String),
1105}
1106
1107/// Builtin types identifiers.
1108///
1109/// WARNING: for now, all the built-in types are covariant in the generic
1110/// parameters (if there are). Adding types which don't satisfy this
1111/// will require to update the code abstracting the signatures (to properly
1112/// take into account the lifetime constraints).
1113///
1114/// TODO: update to not hardcode the types (except `Box` maybe) and be more
1115/// modular.
1116/// TODO: move to builtins.rs?
1117#[derive(
1118 Debug,
1119 PartialEq,
1120 Eq,
1121 Clone,
1122 Copy,
1123 EnumIsA,
1124 EnumAsGetters,
1125 VariantName,
1126 Serialize,
1127 Deserialize,
1128 Drive,
1129 DriveMut,
1130 Hash,
1131 Ord,
1132 PartialOrd,
1133)]
1134#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
1135pub enum BuiltinTy {
1136 /// Boxes are de facto a primitive type.
1137 Box,
1138 /// Primitive type
1139 Str,
1140}
1141
1142#[derive(
1143 Debug,
1144 Copy,
1145 Clone,
1146 PartialEq,
1147 Eq,
1148 PartialOrd,
1149 Ord,
1150 Hash,
1151 Serialize,
1152 Deserialize,
1153 Drive,
1154 DriveMut,
1155)]
1156pub enum ClosureKind {
1157 Fn,
1158 FnMut,
1159 FnOnce,
1160}
1161
1162impl ClosureKind {
1163 // pub fn trait_name(self) -> &'static str {}
1164 pub fn method_name(self) -> &'static str {
1165 match self {
1166 ClosureKind::FnOnce => "call_once",
1167 ClosureKind::FnMut => "call_mut",
1168 ClosureKind::Fn => "call",
1169 }
1170 }
1171}
1172
1173/// Additional information for closures.
1174#[derive(
1175 Debug, Clone, PartialEq, Eq, PartialOrd, Ord, SerializeState, DeserializeState, Drive, DriveMut,
1176)]
1177pub struct ClosureInfo {
1178 #[serde_state(stateless)]
1179 pub kind: ClosureKind,
1180 /// The `FnOnce` implementation of this closure -- always exists.
1181 pub fn_once_impl: RegionBinder<TraitImplRef>,
1182 /// The `FnMut` implementation of this closure, if any.
1183 pub fn_mut_impl: Option<RegionBinder<TraitImplRef>>,
1184 /// The `Fn` implementation of this closure, if any.
1185 pub fn_impl: Option<RegionBinder<TraitImplRef>>,
1186 /// The signature of the function that this closure represents.
1187 pub signature: RegionBinder<FunSig>,
1188}
1189
1190/// A function signature.
1191#[derive(
1192 Debug,
1193 Clone,
1194 PartialEq,
1195 Eq,
1196 PartialOrd,
1197 Ord,
1198 Hash,
1199 SerializeState,
1200 DeserializeState,
1201 Drive,
1202 DriveMut,
1203)]
1204pub struct FunSig {
1205 /// Is the function unsafe or not
1206 #[drive(skip)]
1207 pub is_unsafe: bool,
1208 /// The calling convention of this function.
1209 #[drive(skip)]
1210 pub abi: Abi,
1211 /// Whether this is a C-variadic function (its last parameter is `...`).
1212 #[drive(skip)]
1213 pub is_variadic: bool,
1214 pub inputs: Vec<Ty>,
1215 pub output: Ty,
1216}
1217
1218#[derive(
1219 Debug,
1220 Clone,
1221 PartialEq,
1222 Eq,
1223 PartialOrd,
1224 Ord,
1225 Hash,
1226 VariantName,
1227 EnumIsA,
1228 SerializeState,
1229 DeserializeState,
1230 Drive,
1231 DriveMut,
1232)]
1233#[serde_state(stateless)]
1234#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("Abi"))]
1235pub enum Abi {
1236 Rust,
1237 C,
1238 /// Rust's spelling for the ABI, e.g. "C-unwind" or "system".
1239 Other(#[drive(skip)] ustr::Ustr),
1240}
1241
1242impl Abi {
1243 pub fn rust() -> Self {
1244 Self::Rust
1245 }
1246
1247 pub fn rust_name(&self) -> &str {
1248 match self {
1249 Self::Rust => "Rust",
1250 Self::C => "C",
1251 Self::Other(name) => name.as_str(),
1252 }
1253 }
1254}
1255
1256/// The contents of a `dyn Trait` type.
1257#[derive(
1258 Debug,
1259 Clone,
1260 PartialEq,
1261 Eq,
1262 PartialOrd,
1263 Ord,
1264 Hash,
1265 SerializeState,
1266 DeserializeState,
1267 Drive,
1268 DriveMut,
1269)]
1270pub struct DynPredicate {
1271 /// This binder binds a single type `T`, which is considered existentially quantified. The
1272 /// predicates in the binder apply to `T` and represent the `dyn Trait` constraints.
1273 /// E.g. `dyn Iterator<Item=u32> + Send` is represented as `exists<T: Iterator<Item=u32> + Send> T`.
1274 ///
1275 /// Only the first trait clause may have methods. We use the vtable of this trait in the `dyn
1276 /// Trait` pointer metadata.
1277 pub binder: Binder<Ty>,
1278}
1279
1280/// A type-level pattern used by [`TyKind::Pattern`].
1281#[derive(
1282 Debug,
1283 Clone,
1284 PartialEq,
1285 Eq,
1286 PartialOrd,
1287 Ord,
1288 Hash,
1289 VariantName,
1290 EnumIsA,
1291 SerializeState,
1292 DeserializeState,
1293 Drive,
1294 DriveMut,
1295)]
1296#[serde_state(state_implements = HashConsSerializerState)] // Avoid corecursive impls due to perfect derive
1297pub enum TypePattern {
1298 Range(Box<ConstantExpr>, Box<ConstantExpr>),
1299 OrPattern(Vec<TypePattern>),
1300 NotNull,
1301}