charon_driver/translate/
translate_constants.rs1use super::translate_ctx::*;
3use charon_lib::ast::*;
4
5impl<'tcx, 'ctx> ItemTransCtx<'tcx, 'ctx> {
6 fn translate_constant_literal_to_constant_expr_kind(
7 &mut self,
8 span: Span,
9 v: &hax::ConstantLiteral,
10 ) -> Result<ConstantExprKind, Error> {
11 let lit = match v {
12 hax::ConstantLiteral::ByteStr(bs) => Literal::ByteStr(bs.clone()),
13 hax::ConstantLiteral::Str(..) => {
14 raise_error!(self, span, "found a `str` constants not behind a reference")
17 }
18 hax::ConstantLiteral::Char(c) => Literal::Char(*c),
19 hax::ConstantLiteral::Bool(b) => Literal::Bool(*b),
20 hax::ConstantLiteral::Int(i) => {
21 use hax::ConstantInt;
22 let scalar = match i {
23 ConstantInt::Int(v, int_type) => {
24 let ty = Self::translate_hax_int_ty(int_type);
25 ScalarValue::Signed(ty, *v)
26 }
27 ConstantInt::Uint(v, uint_type) => {
28 let ty = Self::translate_hax_uint_ty(uint_type);
29 ScalarValue::Unsigned(ty, *v)
30 }
31 };
32 Literal::Scalar(scalar)
33 }
34 hax::ConstantLiteral::Float(value, float_type) => {
35 let value = value.clone();
36 let ty = match float_type {
37 hax::FloatTy::F16 => FloatTy::F16,
38 hax::FloatTy::F32 => FloatTy::F32,
39 hax::FloatTy::F64 => FloatTy::F64,
40 hax::FloatTy::F128 => FloatTy::F128,
41 };
42 Literal::Float(FloatValue { value, ty })
43 }
44 hax::ConstantLiteral::PtrNoProvenance(v) => {
45 return Ok(ConstantExprKind::PtrNoProvenance(*v));
46 }
47 };
48 Ok(ConstantExprKind::Literal(lit))
49 }
50
51 pub(crate) fn translate_constant_expr_to_constant_expr(
57 &mut self,
58 span: Span,
59 v: &hax::ConstantExpr,
60 ) -> Result<ConstantExpr, Error> {
61 let ty = self.translate_ty(span, &v.ty)?;
62 let kind = match v.contents.as_ref() {
63 hax::ConstantExprKind::Literal(lit) => {
64 self.translate_constant_literal_to_constant_expr_kind(span, lit)?
65 }
66 hax::ConstantExprKind::Adt { info, fields } => {
67 let fields: Vec<ConstantExpr> = fields
68 .iter()
69 .map(|f| self.translate_constant_expr_to_constant_expr(span, &f.value))
70 .try_collect()?;
71 use hax::VariantKind;
72 let vid = if let VariantKind::Enum { index, .. } = info.kind {
73 Some(VariantId::new(index))
74 } else {
75 None
76 };
77 ConstantExprKind::Adt(vid, fields)
78 }
79 hax::ConstantExprKind::Array { fields } => {
80 let fields: Vec<ConstantExpr> = fields
81 .iter()
82 .map(|x| self.translate_constant_expr_to_constant_expr(span, x))
83 .try_collect()?;
84
85 if matches!(v.ty.kind(), hax::TyKind::Slice { .. }) {
86 ConstantExprKind::Slice(fields)
87 } else {
88 ConstantExprKind::Array(fields)
89 }
90 }
91 hax::ConstantExprKind::Tuple { fields } => {
92 let fields: Vec<ConstantExpr> = fields
93 .iter()
94 .map(|f| self.translate_constant_expr_to_constant_expr(span, f))
96 .try_collect()?;
97 ConstantExprKind::Adt(None, fields)
98 }
99 hax::ConstantExprKind::NamedGlobal(item) => match &item.in_trait {
100 Some(impl_expr) => {
101 let trait_ref = self.translate_trait_impl_expr(span, impl_expr)?;
102 assert!(item.generic_args.is_empty());
104 let name = self.translate_trait_item_name(&item.def_id)?;
105 ConstantExprKind::TraitConst(trait_ref, name)
106 }
107 None => {
108 let global_ref = self.translate_global_decl_ref(span, item)?;
109 ConstantExprKind::Global(global_ref)
110 }
111 },
112 hax::ConstantExprKind::Borrow(v)
113 if let hax::ConstantExprKind::Literal(hax::ConstantLiteral::Str(s)) =
114 v.contents.as_ref() =>
115 {
116 ConstantExprKind::Literal(Literal::Str(s.clone()))
117 }
118 hax::ConstantExprKind::Borrow(v) => {
119 let val = self.translate_constant_expr_to_constant_expr(span, v)?;
120 ConstantExprKind::Ref(Box::new(val))
121 }
122 hax::ConstantExprKind::Cast { .. } => {
123 register_error!(
124 self,
125 span,
126 "Unsupported constant: `ConstantExprKind::Cast {{..}}`",
127 );
128 ConstantExprKind::Opaque("`ConstantExprKind::Cast {{..}}`".into())
129 }
130 hax::ConstantExprKind::RawBorrow { mutability, arg } => {
131 let arg = self.translate_constant_expr_to_constant_expr(span, arg)?;
132 let rk = RefKind::mutable(*mutability);
133 ConstantExprKind::Ptr(rk, Box::new(arg))
134 }
135 hax::ConstantExprKind::ConstRef { id } => {
136 match self.lookup_const_generic_var(span, id) {
137 Ok(var) => ConstantExprKind::Var(var),
138 Err(err) => ConstantExprKind::Opaque(err.msg),
139 }
140 }
141 hax::ConstantExprKind::FnDef(item) => {
142 let fn_ptr = self
143 .translate_fn_ptr(span, item, TransItemSourceKind::Fun)?
144 .erase();
145 ConstantExprKind::FnDef(fn_ptr)
146 }
147 hax::ConstantExprKind::FnPtr(item) => {
148 let fn_ptr = self
149 .translate_fn_ptr(span, item, TransItemSourceKind::Fun)?
150 .erase();
151 ConstantExprKind::FnPtr(fn_ptr)
152 }
153 hax::ConstantExprKind::Memory(bytes) => {
154 ConstantExprKind::RawMemory(bytes.iter().map(|b| Byte::Value(*b)).collect())
155 }
156 hax::ConstantExprKind::Todo(msg) => {
157 register_error!(self, span, "Unsupported constant: {:?}", msg);
158 ConstantExprKind::Opaque(msg.into())
159 }
160 };
161
162 Ok(ConstantExpr { kind, ty })
163 }
164
165 pub(crate) fn translate_constant_expr_to_const_generic(
168 &mut self,
169 span: Span,
170 v: &hax::ConstantExpr,
171 ) -> Result<ConstGeneric, Error> {
172 let kind = self.translate_constant_expr_to_constant_expr(span, v)?.kind;
175 match kind {
176 ConstantExprKind::Var(v) => Ok(ConstGeneric::Var(v)),
177 ConstantExprKind::Literal(v) => Ok(ConstGeneric::Value(v)),
178 ConstantExprKind::Global(global_ref) => {
179 error_assert!(self, span, global_ref.generics.is_empty());
182 Ok(ConstGeneric::Global(global_ref.id))
183 }
184 ConstantExprKind::Adt(..)
185 | ConstantExprKind::Array { .. }
186 | ConstantExprKind::Slice { .. }
187 | ConstantExprKind::RawMemory { .. }
188 | ConstantExprKind::TraitConst { .. }
189 | ConstantExprKind::Ref(_)
190 | ConstantExprKind::Ptr(..)
191 | ConstantExprKind::FnPtr { .. }
192 | ConstantExprKind::FnDef { .. }
193 | ConstantExprKind::Opaque(_)
194 | ConstantExprKind::PtrNoProvenance(..) => {
195 raise_error!(self, span, "Unexpected constant generic: {:?}", kind)
196 }
197 }
198 }
199}