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