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;