1use crate::translate::translate_bodies::BodyTransCtx;
2
3use super::translate_ctx::*;
4use charon_lib::ast::*;
5use hax_frontend_exporter as hax;
6
7impl ItemTransCtx<'_, '_> {
8 fn translate_drop_method_body(
9 &mut self,
10 span: Span,
11 def: &hax::FullDef,
12 ) -> Result<Result<Body, Opaque>, Error> {
13 let (hax::FullDefKind::Struct { drop_glue, .. }
14 | hax::FullDefKind::Enum { drop_glue, .. }
15 | hax::FullDefKind::Union { drop_glue, .. }
16 | hax::FullDefKind::Closure { drop_glue, .. }) = def.kind()
17 else {
18 panic!("Unexpected def adt: {def:?}")
19 };
20 let Some(body) = drop_glue else {
21 return Ok(Err(Opaque));
22 };
23
24 let mut bt_ctx = BodyTransCtx::new(self);
25 Ok(match bt_ctx.translate_body(span, body, &def.source_text) {
26 Ok(Ok(body)) => Ok(body),
27 Ok(Err(Opaque)) => Err(Opaque),
28 Err(_) => Err(Opaque),
29 })
30 }
31
32 fn adt_self_ty(&mut self, span: Span, def_id: &hax::DefId) -> Result<Ty, Error> {
35 let self_decl_id = self.register_type_decl_id(span, def_id);
37 let self_ty = TyKind::Adt(TypeDeclRef {
38 id: TypeId::Adt(self_decl_id),
39 generics: Box::new(self.the_only_binder().params.identity_args()),
40 })
41 .into_ty();
42 Ok(self_ty)
43 }
44
45 fn adt_drop_predicate(
46 &mut self,
47 span: Span,
48 def_id: &hax::DefId,
49 ) -> Result<TraitDeclRef, Error> {
50 let drop_trait = self.get_lang_item(rustc_hir::LangItem::Drop);
51 let drop_trait = self.register_trait_decl_id(span, &drop_trait);
52
53 let self_ty = self.adt_self_ty(span, def_id)?;
54 let implemented_trait = TraitDeclRef {
55 id: drop_trait,
56 generics: Box::new(GenericArgs::new_types([self_ty.clone()].into())),
57 };
58 Ok(implemented_trait)
59 }
60
61 #[tracing::instrument(skip(self, item_meta))]
64 pub fn translate_drop_method(
65 mut self,
66 def_id: FunDeclId,
67 item_meta: ItemMeta,
68 def: &hax::FullDef,
69 ) -> Result<FunDecl, Error> {
70 let span = item_meta.span;
71 let drop_impl_id = self.register_drop_trait_impl_id(span, def.def_id());
72
73 self.translate_def_generics(span, def)?;
74
75 let implemented_trait = self.adt_drop_predicate(span, def.def_id())?;
76 let self_ty = implemented_trait.generics.types[0].clone();
77 let impl_ref = TraitImplRef {
78 id: drop_impl_id,
79 generics: Box::new(self.the_only_binder().params.identity_args()),
80 };
81
82 let kind = ItemKind::TraitImpl {
83 impl_ref,
84 trait_ref: implemented_trait,
85 item_name: TraitItemName("drop".to_owned()),
86 reuses_default: false,
87 };
88
89 assert!(self.innermost_binder_mut().bound_region_vars.is_empty());
91 let region_id = self
92 .innermost_binder_mut()
93 .push_bound_region(hax::BoundRegionKind::Anon);
94
95 let body = if item_meta.opacity.with_private_contents().is_opaque() {
96 Err(Opaque)
97 } else {
98 self.translate_drop_method_body(span, def)?
99 };
100
101 let input = TyKind::Ref(
102 Region::Var(DeBruijnVar::new_at_zero(region_id)),
103 self_ty,
104 RefKind::Mut,
105 )
106 .into_ty();
107 let signature = FunSig {
108 generics: self.into_generics(),
109 is_unsafe: false,
110 inputs: vec![input],
111 output: Ty::mk_unit(),
112 };
113
114 Ok(FunDecl {
115 def_id,
116 item_meta,
117 signature,
118 kind,
119 is_global_initializer: None,
120 body,
121 })
122 }
123
124 #[tracing::instrument(skip(self, item_meta))]
125 pub fn translate_drop_impl(
126 mut self,
127 impl_id: TraitImplId,
128 item_meta: ItemMeta,
129 def: &hax::FullDef,
130 ) -> Result<TraitImpl, Error> {
131 let span = item_meta.span;
132
133 self.translate_def_generics(span, def)?;
134
135 let implemented_trait = self.adt_drop_predicate(span, def.def_id())?;
136 let drop_trait = implemented_trait.id;
137
138 let method_id = self.register_drop_method_id(span, &def.def_id);
140 let method_name = TraitItemName("drop".to_owned());
141 let method_binder = {
142 let mut method_params = GenericParams::empty();
143 method_params
144 .regions
145 .push_with(|index| RegionVar { index, name: None });
146
147 let generics = self
148 .outermost_binder()
149 .params
150 .identity_args_at_depth(DeBruijnId::one())
151 .concat(&method_params.identity_args_at_depth(DeBruijnId::zero()));
152 Binder::new(
153 BinderKind::TraitMethod(drop_trait, method_name.clone()),
154 method_params,
155 FunDeclRef {
156 id: method_id,
157 generics: Box::new(generics),
158 },
159 )
160 };
161
162 let parent_trait_refs = {
163 let meta_sized_trait = self.get_lang_item(rustc_hir::LangItem::MetaSized);
164 let meta_sized_trait = self.register_trait_decl_id(span, &meta_sized_trait);
165 let self_ty = implemented_trait.generics.types[0].clone();
166 [TraitRef::new_builtin(
167 meta_sized_trait,
168 self_ty,
169 Default::default(),
170 )]
171 .into()
172 };
173
174 Ok(TraitImpl {
175 def_id: impl_id,
176 item_meta,
177 impl_trait: implemented_trait,
178 generics: self.into_generics(),
179 methods: vec![(method_name, method_binder)],
180 parent_trait_refs,
181 type_clauses: Default::default(),
182 consts: Default::default(),
183 types: Default::default(),
184 })
185 }
186}