1use crate::translate::translate_crate::TransItemSourceKind;
2
3use super::translate_ctx::*;
4use crate::hax;
5use crate::hax::FullDefKind;
6use charon_lib::{ast::*, formatter::IntoFormatter, pretty::FmtWithCtx};
7
8impl ItemTransCtx<'_, '_> {
9 fn translate_drop_in_place_method_body(
10 &mut self,
11 span: Span,
12 def: &hax::FullDef,
13 self_ty: &Ty,
14 ) -> Result<Body, Error> {
15 let (hax::FullDefKind::Adt { .. } | hax::FullDefKind::Closure { .. }) = def.kind() else {
16 return Ok(Body::Missing);
17 };
18
19 let translate_glue = self.options.translate_poly_drop_glue
22 || self.monomorphize()
23 || def
24 .this
25 .def_id
26 .underlying_rust_def_id()
27 .is_none_or(|def_id| self.tcx.generics_of(def_id).is_empty());
28 if !translate_glue {
29 return Ok(Body::Missing);
30 }
31
32 let body = {
33 let ctx = std::panic::AssertUnwindSafe(&mut *self);
34 let Ok(body) =
36 std::panic::catch_unwind(move || def.this().drop_glue_shim(ctx.hax_state()))
37 else {
38 let self_ty_name = if let TyKind::Adt(TypeDeclRef {
39 id: TypeId::Adt(type_id),
40 ..
41 }) = self_ty.kind()
42 && let Some(name) = self.translated.item_name(*type_id)
43 {
44 name.to_string_with_ctx(&self.into_fmt())
45 } else {
46 "crate::the::Type".to_string()
47 };
48 raise_error!(
49 self,
50 span,
51 "rustc panicked while retrieving drop glue. \
52 This is known to happen with `--precise-drops`; to silence this warning, \
53 pass `--opaque '{{impl core::marker::Destruct for {}}}'` to charon",
54 self_ty_name
55 )
56 };
57 body
58 };
59
60 Ok(self.translate_body(span, body, &def.source_text))
61 }
62
63 #[tracing::instrument(skip(self, item_meta, def))]
66 pub fn translate_drop_in_place_method(
67 mut self,
68 def_id: FunDeclId,
69 item_meta: ItemMeta,
70 def: &hax::FullDef,
71 impl_kind: Option<TraitImplSource>,
72 ) -> Result<FunDecl, Error> {
73 let span = item_meta.span;
74
75 let trait_pred = match def.kind() {
76 FullDefKind::Adt { destruct_impl, .. } | FullDefKind::Closure { destruct_impl, .. } => {
78 assert_eq!(impl_kind, Some(TraitImplSource::ImplicitDestruct));
79 &destruct_impl.trait_pred
80 }
81 FullDefKind::Trait { self_predicate, .. } => {
83 assert_eq!(impl_kind, None);
84 self_predicate
85 }
86 _ => unreachable!(),
87 };
88
89 let implemented_trait = self.translate_trait_predicate(span, trait_pred)?;
90 let item_name = TraitItemName("drop_in_place".into());
91 let self_ty = implemented_trait
92 .self_ty(&self.t_ctx.translated)
93 .unwrap()
94 .clone();
95
96 let src = match impl_kind {
97 Some(impl_kind) => {
98 let destruct_impl_id =
99 self.register_item(span, def.this(), TransItemSourceKind::TraitImpl(impl_kind));
100 let impl_ref = TraitImplRef {
101 id: destruct_impl_id,
102 generics: Box::new(self.the_only_binder().params.identity_args()),
103 };
104 ItemSource::TraitImpl {
105 impl_ref,
106 trait_ref: implemented_trait,
107 item_name,
108 reuses_default: false,
109 }
110 }
111 None => ItemSource::TraitDecl {
112 trait_ref: implemented_trait,
113 item_name,
114 has_default: false,
115 },
116 };
117
118 let body = if item_meta.opacity.with_private_contents().is_opaque() {
119 Body::Opaque
120 } else {
121 self.translate_drop_in_place_method_body(span, def, &self_ty)?
122 };
123
124 let input = TyKind::RawPtr(self_ty, RefKind::Mut).into_ty();
125 let signature = FunSig {
126 is_unsafe: true,
127 inputs: vec![input],
128 output: Ty::mk_unit(),
129 };
130
131 Ok(FunDecl {
132 def_id,
133 item_meta,
134 generics: self.into_generics(),
135 signature,
136 src,
137 is_global_initializer: None,
138 body,
139 })
140 }
141
142 pub fn prepare_drop_in_place_method(
144 &mut self,
145 def: &hax::FullDef,
146 span: Span,
147 destruct_trait_id: TraitDeclId,
148 impl_kind: Option<TraitImplSource>,
149 ) -> (TraitItemName, Binder<FunDeclRef>) {
150 let method_id = self.register_item(
151 span,
152 def.this(),
153 TransItemSourceKind::DropInPlaceMethod(impl_kind),
154 );
155 let method_name = TraitItemName("drop_in_place".into());
156 let method_binder = {
157 let generics = self
158 .outermost_binder()
159 .params
160 .identity_args_at_depth(DeBruijnId::one());
161 Binder::new(
162 BinderKind::TraitMethod(destruct_trait_id, method_name),
163 GenericParams::empty(),
164 FunDeclRef {
165 id: method_id,
166 generics: Box::new(generics),
167 },
168 )
169 };
170 (method_name, method_binder)
171 }
172
173 #[tracing::instrument(skip(self, item_meta, def))]
174 pub fn translate_implicit_destruct_impl(
175 mut self,
176 impl_id: TraitImplId,
177 item_meta: ItemMeta,
178 def: &hax::FullDef,
179 ) -> Result<TraitImpl, Error> {
180 let span = item_meta.span;
181
182 let (FullDefKind::Adt { destruct_impl, .. } | FullDefKind::Closure { destruct_impl, .. }) =
183 def.kind()
184 else {
185 unreachable!("{:?}", def.def_id())
186 };
187 let mut timpl = self.translate_virtual_trait_impl(impl_id, item_meta, destruct_impl)?;
188
189 timpl.methods.push(self.prepare_drop_in_place_method(
191 def,
192 span,
193 timpl.impl_trait.id,
194 Some(TraitImplSource::ImplicitDestruct),
195 ));
196
197 Ok(timpl)
198 }
199}