charon_lib/transform/normalize/
desugar_drops.rs1use crate::{
2 transform::{
3 TransformCtx,
4 ctx::{BodyTransformCtx, UllbcPass, UllbcStatementTransformCtx},
5 },
6 ullbc_ast::*,
7};
8
9fn is_noop_destruct(glue: &FnPtr) -> bool {
10 match glue.kind.as_ref() {
11 FnPtrKind::Trait(tref, _) => matches!(
12 &tref.kind,
13 TraitRefKind::BuiltinOrAuto {
14 builtin_data: BuiltinImplData::NoopDestruct,
15 ..
16 }
17 ),
18 _ => false,
19 }
20}
21
22impl<'a> UllbcStatementTransformCtx<'a> {
23 fn transform_drop_to_call(&mut self, term: &mut Terminator) {
26 if let TerminatorKind::Drop {
27 kind: DropKind::Precise,
28 place,
29 fn_ptr,
30 target,
31 on_unwind,
32 } = &mut term.kind
33 {
34 if is_noop_destruct(fn_ptr) {
36 term.kind = TerminatorKind::Goto { target: *target };
37 return;
38 }
39
40 let drop_arg =
42 self.borrow_to_new_var(place.clone(), BorrowKind::Mut, Some("drop_arg".into()));
43
44 let drop_ret = self.fresh_var(Some("drop_ret".into()), Ty::mk_unit());
45 let call = Call {
46 func: FnOperand::Regular(fn_ptr.clone()),
47 args: Vec::from([Operand::Move(drop_arg)]),
48 dest: drop_ret,
49 safety: CallSafety::Safe, };
51 term.kind = TerminatorKind::Call {
52 call,
53 target: *target,
54 on_unwind: *on_unwind,
55 };
56 }
57 }
58}
59
60pub struct Transform;
61
62impl UllbcPass for Transform {
63 fn should_run(&self, options: &crate::options::TranslateOptions) -> bool {
64 options.desugar_drops
65 }
66 fn transform_function(&self, ctx: &mut TransformCtx, decl: &mut FunDecl) {
67 decl.transform_ullbc_terminators(ctx, |ctx, term| {
68 ctx.transform_drop_to_call(term);
69 });
70 }
71}