Skip to main content

charon_driver/hax/
constant_utils.rs

1use crate::hax::prelude::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4pub enum ConstantInt {
5    Int(i128, IntTy),
6    Uint(u128, UintTy),
7}
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub enum ConstantLiteral {
11    Bool(bool),
12    Char(char),
13    Float(String, u128, FloatTy),
14    Int(ConstantInt),
15    PtrNoProvenance(u128),
16    Str(String),
17    ByteStr(Vec<u8>),
18}
19
20sinto_reexport!(rustc_abi::VariantIdx);
21
22/// Describe the kind of a variant
23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub enum VariantKind {
25    Struct,
26    Union,
27    Enum { index: VariantIdx },
28}
29
30/// The subset of expressions that corresponds to constants.
31#[derive(Debug, Clone, PartialEq, Eq, Hash)]
32pub enum ConstantExprKind<'tcx> {
33    Literal(ConstantLiteral),
34    // Adts (structs, enums, unions) or closures.
35    Adt {
36        kind: VariantKind,
37        fields: Vec<ConstantFieldExpr<'tcx>>,
38    },
39    Array {
40        fields: Vec<ConstantExpr<'tcx>>,
41    },
42    Repeat {
43        value: ConstantExpr<'tcx>,
44    },
45    Tuple {
46        fields: Vec<ConstantExpr<'tcx>>,
47    },
48    /// A top-level or associated constant.
49    ///
50    /// Remark: constants *can* have generic parameters.
51    /// Example:
52    /// ```text
53    /// struct V<const N: usize, T> {
54    ///   x: [T; N],
55    /// }
56    ///
57    /// impl<const N: usize, T> V<N, T> {
58    ///   const LEN: usize = N; // This has generics <N, T>
59    /// }
60    ///
61    /// impl Foo for Bar {
62    ///   const C : usize = 32; // <-
63    /// }
64    /// ```
65    ///
66    /// If `options.inline_anon_consts` is `false`, this is also used for inline const blocks and
67    /// advanced const generics expressions.
68    NamedGlobal(ItemRef<'tcx>),
69    /// A reference or raw pointer (as given by the type of this constant) to a place inside a
70    /// constant value: `projections` applied to `base`, each with the type of the place it
71    /// reaches.
72    Ptr {
73        base: ConstantPtrBase<'tcx>,
74        projections: Vec<(ConstantProjectionElem<'tcx>, Ty<'tcx>)>,
75        metadata: Option<UnsizingMetadata<'tcx>>,
76    },
77    /// Casts a thin pointer to the type of this constant. If metadata is given, this is an
78    /// unsizing cast from the pointee of the given pointer.
79    PtrCast(ConstantExpr<'tcx>, Option<UnsizingMetadata<'tcx>>),
80    ConstRef {
81        id: ParamConst,
82    },
83    /// A function definition, corresponding to a particular item. This is a ZST, unlike `FnPtr`.
84    FnDef(ItemRef<'tcx>),
85    /// A function pointer. This is an actual pointer to that function.
86    FnPtr(FnPtrTarget<'tcx>),
87    /// The `TypeId` of this type.
88    TypeId(Ty<'tcx>),
89    /// A blob of memory containing the byte representation of the value. This can occur when
90    /// evaluating MIR constants (e.g. unions). Interpreting this back to a structured value
91    /// is left as an exercice to the consumer.
92    Memory(Vec<ConstantByte<'tcx>>),
93    Todo(String),
94}
95
96/// The place a constant pointer starts from.
97#[derive(Debug, Clone, PartialEq, Eq, Hash)]
98pub enum ConstantPtrBase<'tcx> {
99    /// The allocation behind this provenance, of the given type.
100    Global(ConstantByteProvenance<'tcx>, Ty<'tcx>),
101    /// A constant value that isn't stored in an allocation we name.
102    Value(ConstantExpr<'tcx>),
103}
104
105/// Projects a place inside the pointee of a constant pointer.
106#[derive(Debug, Clone, PartialEq, Eq, Hash)]
107pub enum ConstantProjectionElem<'tcx> {
108    /// A field of a struct, tuple or closure, or of the given variant of an enum.
109    Field(Option<VariantIdx>, FieldIdx),
110    /// An element of an array.
111    Index(u64),
112    /// The subarray `array[from..to]`.
113    Subslice { from: u64, to: u64 },
114    /// The place `count * size_of(ty)` bytes after the current place, or
115    /// `count` bytes if `ty` is `None`. If `in_bounds` is `false`, this may point outside of the
116    /// allocation. `pointee_is_sized` proves that the resulting place is sized.
117    Offset {
118        count: i64,
119        ty: Option<Ty<'tcx>>,
120        in_bounds: bool,
121        pointee_is_sized: TraitProof<'tcx>,
122    },
123}
124
125/// A byte of an evaluated constant, in the MiniRust sense.
126#[derive(Debug, Clone, PartialEq, Eq, Hash)]
127pub enum ConstantByte<'tcx> {
128    /// An uninitialized byte (e.g. padding, or the bytes of a union not covered by the active
129    /// field).
130    Uninit,
131    /// A concrete byte value.
132    Value(u8),
133    /// A byte that is part of a pointer with provenance, at the given offset into the pointee
134    /// allocation. The `u8` is the index of this byte within the pointer.
135    Provenance(ConstantByteProvenance<'tcx>, u64, u8),
136}
137
138/// The function a function pointer points to.
139#[derive(Debug, Clone, PartialEq, Eq, Hash)]
140pub enum FnPtrTarget<'tcx> {
141    /// The function of an item.
142    Fn(ItemRef<'tcx>),
143    /// A stateless closure coerced to a function pointer.
144    ClosureAsFn(ClosureTy<'tcx>),
145}
146
147/// What a pointer byte in an evaluated constant points to.
148#[derive(Debug, Clone, PartialEq, Eq, Hash)]
149pub enum ConstantByteProvenance<'tcx> {
150    /// A pointer to a static.
151    Global(ItemRef<'tcx>),
152    /// A pointer to a function, with the type of function pointers to it.
153    Function(FnPtrTarget<'tcx>, Ty<'tcx>),
154    /// The TypeId of a type.
155    TypeId(Ty<'tcx>),
156    /// A pointer to the vtable of this trait implementation.
157    VTable(TraitProof<'tcx>),
158}
159
160#[derive(Debug, Clone, PartialEq, Eq, Hash)]
161pub struct ConstantFieldExpr<'tcx> {
162    pub field: DefId,
163    pub value: ConstantExpr<'tcx>,
164}
165
166/// Rustc has different representations for constants: one for MIR
167/// ([`rustc_middle::mir::Const`]), one for the type system
168/// ([`rustc_middle::ty::ConstKind`]). For simplicity hax maps those
169/// two constructs to the same `ConstantExpr` type.
170#[derive(Debug, Clone, PartialEq, Eq, Hash)]
171pub struct ConstantExpr<'tcx> {
172    pub kind: Box<ConstantExprKind<'tcx>>,
173    pub ty: Ty<'tcx>,
174}
175
176impl<'tcx> ConstantExpr<'tcx> {
177    pub fn new(kind: ConstantExprKind<'tcx>, ty: Ty<'tcx>) -> Self {
178        Self {
179            kind: Box::new(kind),
180            ty,
181        }
182    }
183}
184
185pub use self::uneval::*;
186pub use rustc_const_uneval::{ConstSource, GlobalRef, ReadMode};
187mod uneval;