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