charon_lib/transform/normalize/
desugar_drops.rs1use super::super::ctx::UllbcPass;
2use crate::{
3 transform::{
4 TransformCtx,
5 ctx::{BodyTransformCtx, UllbcStatementTransformCtx},
6 },
7 ullbc_ast::*,
8};
9
10fn is_noop_destruct(tref: &TraitRef) -> bool {
11 matches!(
12 &tref.kind,
13 TraitRefKind::BuiltinOrAuto {
14 builtin_data: BuiltinImplData::NoopDestruct,
15 ..
16 }
17 )
18}
19
20impl<'a> UllbcStatementTransformCtx<'a> {
21 fn transform_drop_to_call(&mut self, term: &mut Terminator) {
24 if let TerminatorKind::Drop {
25 place,
26 tref,
27 target,
28 on_unwind,
29 } = &mut term.kind
30 {
31 if is_noop_destruct(tref) {
33 term.kind = TerminatorKind::Goto {
34 target: target.clone(),
35 };
36 return;
37 }
38
39 let ref_drop_arg = TyKind::RawPtr(place.ty().clone(), RefKind::Mut).into_ty();
40 let drop_arg = self.fresh_var(Some("drop_arg".into()), ref_drop_arg);
41 let drop_ret = self.fresh_var(Some("drop_ret".into()), Ty::mk_unit());
42
43 let ptr_metadata = self.compute_place_metadata(&place);
44 let rval = Rvalue::RawPtr {
45 place: place.clone(),
46 kind: RefKind::Mut,
47 ptr_metadata: ptr_metadata,
48 };
49 self.insert_assn_stmt(drop_arg.clone(), rval);
51
52 let trait_id = tref.trait_decl_ref.skip_binder.id;
54 let Some(tdecl) = self.ctx.translated.trait_decls.get(trait_id) else {
55 return;
56 };
57 let method_name = TraitItemName("drop_in_place".into());
58 let Some(bound_method) = tdecl.methods.iter().find(|m| m.name() == method_name) else {
59 return;
61 };
62 let method_decl_id = bound_method.skip_binder.item.id;
63
64 let fn_ptr = FnPtr::new(
65 FnPtrKind::Trait(tref.clone(), method_name, method_decl_id),
66 GenericArgs::empty(),
67 );
68 let call = Call {
69 func: FnOperand::Regular(fn_ptr),
70 args: Vec::from([Operand::Move(drop_arg)]),
71 dest: drop_ret,
72 };
73 term.kind = TerminatorKind::Call {
74 call,
75 target: target.clone(),
76 on_unwind: on_unwind.clone(),
77 };
78 }
79 }
80}
81
82pub struct Transform;
83
84impl UllbcPass for Transform {
85 fn transform_function(&self, ctx: &mut TransformCtx, decl: &mut FunDecl) {
86 if !ctx.options.desugar_drops {
87 return;
88 }
89 decl.transform_ullbc_terminators(ctx, |ctx, term| {
90 ctx.transform_drop_to_call(term);
91 });
92 }
93}