charon_driver/translate/
translate_functions.rs1use std::panic;
7
8use super::translate_ctx::*;
9use charon_lib::ast::*;
10use charon_lib::common::*;
11use charon_lib::formatter::IntoFormatter;
12use charon_lib::ids::Vector;
13use charon_lib::pretty::FmtWithCtx;
14use charon_lib::ullbc_ast::*;
15use hax_frontend_exporter as hax;
16use itertools::Itertools;
17
18impl ItemTransCtx<'_, '_> {
19 pub(crate) fn translate_function_signature(
23 &mut self,
24 def: &hax::FullDef,
25 item_meta: &ItemMeta,
26 ) -> Result<FunSig, Error> {
27 let span = item_meta.span;
28
29 self.translate_def_generics(span, def)?;
30
31 let signature = match &def.kind {
32 hax::FullDefKind::Fn { sig, .. } => sig,
33 hax::FullDefKind::AssocFn { sig, .. } => sig,
34 hax::FullDefKind::Ctor {
35 fields, output_ty, ..
36 } => {
37 let sig = hax::TyFnSig {
38 inputs: fields.iter().map(|field| field.ty.clone()).collect(),
39 output: output_ty.clone(),
40 c_variadic: false,
41 safety: hax::Safety::Safe,
42 abi: hax::ExternAbi::Rust,
43 };
44 &hax::Binder {
45 value: sig,
46 bound_vars: Default::default(),
47 }
48 }
49 hax::FullDefKind::Const { ty, .. }
50 | hax::FullDefKind::AssocConst { ty, .. }
51 | hax::FullDefKind::AnonConst { ty, .. }
52 | hax::FullDefKind::InlineConst { ty, .. }
53 | hax::FullDefKind::PromotedConst { ty, .. }
54 | hax::FullDefKind::Static { ty, .. } => {
55 let sig = hax::TyFnSig {
56 inputs: vec![],
57 output: ty.clone(),
58 c_variadic: false,
59 safety: hax::Safety::Safe,
60 abi: hax::ExternAbi::Rust,
61 };
62 &hax::Binder {
63 value: sig,
64 bound_vars: Default::default(),
65 }
66 }
67 _ => panic!("Unexpected definition for function: {def:?}"),
68 };
69
70 trace!("signature of {:?}:\n{:?}", def.def_id, signature.value);
72 let inputs: Vec<Ty> = signature
73 .value
74 .inputs
75 .iter()
76 .map(|ty| self.translate_ty(span, ty))
77 .try_collect()?;
78 let output = self.translate_ty(span, &signature.value.output)?;
79
80 let fmt_ctx = &self.into_fmt();
81 trace!(
82 "# Input variables types:\n{}",
83 pretty_display_list(|x| x.to_string_with_ctx(fmt_ctx), &inputs)
84 );
85 trace!("# Output variable type:\n{}", output.with_ctx(fmt_ctx));
86
87 let is_unsafe = match signature.value.safety {
88 hax::Safety::Unsafe => true,
89 hax::Safety::Safe => false,
90 };
91
92 Ok(FunSig {
93 generics: self.the_only_binder().params.clone(),
94 is_unsafe,
95 inputs,
96 output,
97 })
98 }
99
100 pub(crate) fn build_ctor_body(
102 &mut self,
103 span: Span,
104 signature: &FunSig,
105 adt_def_id: &hax::DefId,
106 ctor_of: &hax::CtorOf,
107 variant_id: usize,
108 fields: &hax::IndexVec<hax::FieldIdx, hax::FieldDef>,
109 output_ty: &hax::Ty,
110 ) -> Result<Body, Error> {
111 let adt_decl_id = self.register_type_decl_id(span, adt_def_id);
112 let output_ty = self.translate_ty(span, output_ty)?;
113 let mut locals = Locals {
114 arg_count: fields.len(),
115 locals: Vector::new(),
116 };
117 locals.new_var(None, output_ty);
118 let args: Vec<_> = fields
119 .iter()
120 .map(|field| {
121 let ty = self.translate_ty(span, &field.ty)?;
122 let place = locals.new_var(None, ty);
123 Ok(Operand::Move(place))
124 })
125 .try_collect()?;
126 let variant = match ctor_of {
127 hax::CtorOf::Struct => None,
128 hax::CtorOf::Variant => Some(VariantId::from(variant_id)),
129 };
130 let tref = TypeDeclRef::new(TypeId::Adt(adt_decl_id), signature.generics.identity_args());
131 let st_kind = RawStatement::Assign(
132 locals.return_place(),
133 Rvalue::Aggregate(AggregateKind::Adt(tref, variant, None), args),
134 );
135 let statement = Statement::new(span, st_kind);
136 let block = BlockData {
137 statements: vec![statement],
138 terminator: Terminator::new(span, RawTerminator::Return),
139 };
140 let body = Body::Unstructured(GExprBody {
141 span,
142 locals,
143 comments: Default::default(),
144 body: [block].into_iter().collect(),
145 });
146 Ok(body)
147 }
148
149 pub(crate) fn recognize_builtin_fun(
151 &mut self,
152 def_id: &hax::DefId,
153 ) -> Result<Option<BuiltinFunId>, Error> {
154 let def = self.t_ctx.hax_def(def_id)?;
155 let fun_id =
156 if def.diagnostic_item.as_deref() == Some("box_new") && !self.t_ctx.options.raw_boxes {
157 Some(BuiltinFunId::BoxNew)
158 } else {
159 None
160 };
161 Ok(fun_id)
162 }
163}