1use charon_lib::ast::ullbc_ast_utils::BodyBuilder;
2use itertools::Itertools;
3use std::mem;
4
5use super::{
6 translate_crate::TransItemSourceKind, translate_ctx::*, translate_generics::BindingLevel,
7};
8use charon_lib::formatter::IntoFormatter;
9use charon_lib::ids::Vector;
10use charon_lib::pretty::FmtWithCtx;
11use charon_lib::ullbc_ast::*;
12
13fn dummy_public_attr_info() -> AttrInfo {
14 AttrInfo {
15 public: true,
16 ..Default::default()
17 }
18}
19
20fn usize_ty() -> Ty {
21 Ty::new(TyKind::Literal(LiteralTy::UInt(UIntTy::Usize)))
22}
23
24fn dynify<T: TyVisitable>(mut x: T, new_self: Option<Ty>, for_method: bool) -> T {
32 struct ReplaceSelfVisitor {
33 new_self: Option<Ty>,
34 for_method: bool,
35 }
36 impl VarsVisitor for ReplaceSelfVisitor {
37 fn visit_type_var(&mut self, v: TypeDbVar) -> Option<Ty> {
38 if let DeBruijnVar::Bound(DeBruijnId::ZERO, type_id) = v {
39 Some(if let Some(new_id) = type_id.index().checked_sub(1) {
41 TyKind::TypeVar(DeBruijnVar::Bound(DeBruijnId::ZERO, TypeVarId::new(new_id)))
42 .into_ty()
43 } else {
44 self.new_self.clone().expect(
45 "Found unexpected `Self`
46 type when constructing vtable",
47 )
48 })
49 } else {
50 None
51 }
52 }
53
54 fn visit_clause_var(&mut self, v: ClauseDbVar) -> Option<TraitRefKind> {
55 if let DeBruijnVar::Bound(DeBruijnId::ZERO, clause_id) = v {
56 if self.for_method && clause_id == TraitClauseId::ZERO {
57 Some(TraitRefKind::Dyn)
59 } else {
60 panic!("Found unexpected clause var when constructing vtable: {v}")
61 }
62 } else {
63 None
64 }
65 }
66
67 fn visit_self_clause(&mut self) -> Option<TraitRefKind> {
68 Some(TraitRefKind::Dyn)
69 }
70 }
71 x.visit_vars(&mut ReplaceSelfVisitor {
72 new_self,
73 for_method,
74 });
75 x
76}
77
78impl ItemTransCtx<'_, '_> {
80 pub fn check_at_most_one_pred_has_methods(
81 &mut self,
82 span: Span,
83 preds: &hax::GenericPredicates,
84 ) -> Result<(), Error> {
85 for (clause, _) in preds.predicates.iter().skip(1) {
87 if let hax::ClauseKind::Trait(trait_predicate) = clause.kind.hax_skip_binder_ref() {
88 let trait_def_id = &trait_predicate.trait_ref.def_id;
89 let trait_def = self.poly_hax_def(trait_def_id)?;
90 let has_methods = match trait_def.kind() {
91 hax::FullDefKind::Trait { items, .. } => items
92 .iter()
93 .any(|assoc| matches!(assoc.kind, hax::AssocKind::Fn { .. })),
94 hax::FullDefKind::TraitAlias { .. } => false,
95 _ => unreachable!(),
96 };
97 if has_methods {
98 raise_error!(
99 self,
100 span,
101 "`dyn Trait` with multiple method-bearing predicates is not supported"
102 );
103 }
104 }
105 }
106 Ok(())
107 }
108
109 pub fn translate_existential_predicates(
110 &mut self,
111 span: Span,
112 self_ty: &hax::ParamTy,
113 preds: &hax::GenericPredicates,
114 region: &hax::Region,
115 ) -> Result<DynPredicate, Error> {
116 self.check_at_most_one_pred_has_methods(span, preds)?;
120
121 let region = self.translate_region(span, region)?;
123 let region = region.move_under_binder();
124
125 self.binding_levels.push(BindingLevel::new(true));
127
128 let ty_id = self
130 .innermost_binder_mut()
131 .push_type_var(self_ty.index, self_ty.name.clone());
132 let ty = TyKind::TypeVar(DeBruijnVar::new_at_zero(ty_id)).into_ty();
133
134 self.innermost_binder_mut()
135 .params
136 .types_outlive
137 .push(RegionBinder::empty(OutlivesPred(ty.clone(), region)));
138 self.register_predicates(preds, PredicateOrigin::Dyn)?;
139
140 let params = self.binding_levels.pop().unwrap().params;
141 let binder = Binder {
142 params: params,
143 skip_binder: ty,
144 kind: BinderKind::Dyn,
145 };
146 Ok(DynPredicate { binder })
147 }
148}
149
150impl ItemTransCtx<'_, '_> {
152 pub fn trait_is_dyn_compatible(&mut self, def_id: &hax::DefId) -> Result<bool, Error> {
156 let def = self.poly_hax_def(def_id)?;
157 Ok(match def.kind() {
158 hax::FullDefKind::Trait { dyn_self, .. }
159 | hax::FullDefKind::TraitAlias { dyn_self, .. } => dyn_self.is_some(),
160 _ => false,
161 })
162 }
163
164 fn pred_is_for_self(&self, tref: &hax::TraitRef) -> bool {
166 let first_ty = tref
167 .generic_args
168 .iter()
169 .filter_map(|arg| match arg {
170 hax::GenericArg::Type(ty) => Some(ty),
171 _ => None,
172 })
173 .next();
174 match first_ty {
175 None => false,
176 Some(first_ty) => match first_ty.kind() {
177 hax::TyKind::Param(param_ty) if param_ty.index == 0 => {
178 assert_eq!(param_ty.name, "Self");
179 true
180 }
181 _ => false,
182 },
183 }
184 }
185
186 pub fn translate_vtable_struct_ref(
187 &mut self,
188 span: Span,
189 tref: &hax::TraitRef,
190 ) -> Result<Option<TypeDeclRef>, Error> {
191 self.translate_vtable_struct_ref_maybe_enqueue(true, span, tref)
192 }
193
194 pub fn translate_vtable_struct_ref_no_enqueue(
195 &mut self,
196 span: Span,
197 tref: &hax::TraitRef,
198 ) -> Result<Option<TypeDeclRef>, Error> {
199 self.translate_vtable_struct_ref_maybe_enqueue(false, span, tref)
200 }
201
202 pub fn translate_vtable_struct_ref_maybe_enqueue(
204 &mut self,
205 enqueue: bool,
206 span: Span,
207 tref: &hax::TraitRef,
208 ) -> Result<Option<TypeDeclRef>, Error> {
209 if !self.trait_is_dyn_compatible(&tref.def_id)? {
210 return Ok(None);
211 }
212 let mut vtable_ref: TypeDeclRef =
215 self.translate_item_maybe_enqueue(span, enqueue, tref, TransItemSourceKind::VTable)?;
216 vtable_ref
218 .generics
219 .types
220 .remove_and_shift_ids(TypeVarId::ZERO);
221
222 let assoc_tys: Vec<_> = tref
224 .trait_associated_types(self.hax_state_with_id())
225 .iter()
226 .map(|ty| self.translate_ty(span, ty))
227 .try_collect()?;
228 vtable_ref.generics.types.extend(assoc_tys);
229
230 Ok(Some(vtable_ref))
231 }
232
233 fn add_method_to_vtable_def(
235 &mut self,
236 span: Span,
237 trait_def: &hax::FullDef,
238 mut mk_field: impl FnMut(String, Ty),
239 item: &hax::AssocItem,
240 ) -> Result<(), Error> {
241 let item_def_id = &item.def_id;
242 let item_def = self.hax_def(
243 &trait_def
244 .this()
245 .with_def_id(&self.t_ctx.hax_state, item_def_id),
246 )?;
247 let hax::FullDefKind::AssocFn {
248 sig,
249 vtable_sig: Some(_),
250 ..
251 } = item_def.kind()
252 else {
253 return Ok(());
254 };
255
256 let item_name = self.t_ctx.translate_trait_item_name(item_def_id)?;
257 let sig = self.translate_fun_sig(span, sig)?;
260 let ty = TyKind::FnPtr(sig).into_ty();
261
262 mk_field(format!("method_{}", item_name.0), ty);
263 Ok(())
264 }
265
266 fn add_supertraits_to_vtable_def(
268 &mut self,
269 span: Span,
270 mut mk_field: impl FnMut(String, Ty),
271 implied_predicates: &hax::GenericPredicates,
272 ) -> Result<(), Error> {
273 let mut counter = (0..).into_iter();
274 for (clause, _span) in &implied_predicates.predicates {
275 if let hax::ClauseKind::Trait(pred) = clause.kind.hax_skip_binder_ref() {
276 if !self.pred_is_for_self(&pred.trait_ref) {
278 continue;
279 }
280 let vtbl_struct = self
281 .translate_region_binder(span, &clause.kind, |ctx, _| {
282 ctx.translate_vtable_struct_ref(span, &pred.trait_ref)
283 })?
284 .erase()
285 .expect("parent trait should be dyn compatible");
286 let ty = Ty::new(TyKind::Ref(
287 Region::Static,
288 Ty::new(TyKind::Adt(vtbl_struct)),
289 RefKind::Shared,
290 ));
291 mk_field(format!("super_trait_{}", counter.next().unwrap()), ty);
292 }
293 }
294 Ok(())
295 }
296
297 fn gen_vtable_struct_fields(
298 &mut self,
299 span: Span,
300 trait_def: &hax::FullDef,
301 implied_predicates: &hax::GenericPredicates,
302 ) -> Result<Vector<FieldId, Field>, Error> {
303 let mut fields = Vector::new();
304 let mut mk_field = |name, ty| {
305 fields.push(Field {
306 span,
307 attr_info: dummy_public_attr_info(),
308 name: Some(name),
309 ty,
310 });
311 };
312
313 mk_field("size".into(), usize_ty());
316 mk_field("align".into(), usize_ty());
318 mk_field("drop".into(), {
320 let self_ty = TyKind::TypeVar(DeBruijnVar::new_at_zero(TypeVarId::ZERO)).into_ty();
321 let self_ptr = TyKind::RawPtr(self_ty, RefKind::Mut).into_ty();
322 Ty::new(TyKind::FnPtr(RegionBinder::empty((
323 [self_ptr].into(),
324 Ty::mk_unit(),
325 ))))
326 });
327
328 if let hax::FullDefKind::Trait { items, .. } = trait_def.kind() {
330 for item in items {
331 self.add_method_to_vtable_def(span, trait_def, &mut mk_field, item)?;
332 }
333 }
334
335 self.add_supertraits_to_vtable_def(span, &mut mk_field, implied_predicates)?;
337
338 Ok(fields)
339 }
340
341 pub(crate) fn check_no_monomorphize(&self, span: Span) -> Result<(), Error> {
343 if self.monomorphize() {
344 raise_error!(
345 self,
346 span,
347 "`dyn Trait` is not yet supported with `--monomorphize`; \
348 use `--monomorphize-conservative` instead"
349 )
350 }
351 Ok(())
352 }
353
354 pub(crate) fn translate_vtable_struct(
369 mut self,
370 type_id: TypeDeclId,
371 item_meta: ItemMeta,
372 trait_def: &hax::FullDef,
373 ) -> Result<TypeDecl, Error> {
374 let span = item_meta.span;
375 if !self.trait_is_dyn_compatible(trait_def.def_id())? {
376 raise_error!(
377 self,
378 span,
379 "Trying to compute the vtable type \
380 for a non-dyn-compatible trait"
381 );
382 }
383 self.check_no_monomorphize(span)?;
384
385 self.translate_def_generics(span, trait_def)?;
386
387 let (hax::FullDefKind::Trait {
388 dyn_self,
389 implied_predicates,
390 ..
391 }
392 | hax::FullDefKind::TraitAlias {
393 dyn_self,
394 implied_predicates,
395 ..
396 }) = trait_def.kind()
397 else {
398 panic!()
399 };
400 let Some(dyn_self) = dyn_self else {
401 panic!("Trying to generate a vtable for a non-dyn-compatible trait")
402 };
403
404 let mut dyn_self = {
406 let dyn_self = self.translate_ty(span, dyn_self)?;
407 let TyKind::DynTrait(mut dyn_pred) = dyn_self.kind().clone() else {
408 panic!("incorrect `dyn_self`")
409 };
410
411 for (i, ty_constraint) in dyn_pred
414 .binder
415 .params
416 .trait_type_constraints
417 .iter_mut()
418 .enumerate()
419 {
420 let name = format!("Ty{i}");
421 let new_ty = self
422 .the_only_binder_mut()
423 .params
424 .types
425 .push_with(|index| TypeParam { index, name });
426 let new_ty =
429 TyKind::TypeVar(DeBruijnVar::bound(DeBruijnId::new(2), new_ty)).into_ty();
430 ty_constraint.skip_binder.ty = new_ty;
431 }
432 TyKind::DynTrait(dyn_pred).into_ty()
433 };
434
435 let fields = self.gen_vtable_struct_fields(span, trait_def, implied_predicates)?;
438 let mut kind = TypeDeclKind::Struct(fields);
439 let layout = self.generate_naive_layout(span, &kind)?;
440
441 let mut generics = self.into_generics();
444 {
445 dyn_self = dynify(dyn_self, None, false);
446 generics = dynify(generics, Some(dyn_self.clone()), false);
447 kind = dynify(kind, Some(dyn_self.clone()), true);
448 generics.types.remove_and_shift_ids(TypeVarId::ZERO);
449 generics.types.iter_mut().for_each(|ty| {
450 ty.index -= 1;
451 });
452 }
453
454 let dyn_predicate = dyn_self
455 .kind()
456 .as_dyn_trait()
457 .expect("incorrect `dyn_self`");
458 Ok(TypeDecl {
459 def_id: type_id,
460 item_meta: item_meta,
461 generics: generics,
462 src: ItemSource::VTableTy {
463 dyn_predicate: dyn_predicate.clone(),
464 },
465 kind,
466 layout: Some(layout),
467 ptr_metadata: PtrMetadata::None,
469 repr: None,
470 })
471 }
472}
473
474impl ItemTransCtx<'_, '_> {
476 pub fn translate_vtable_instance_ref(
477 &mut self,
478 span: Span,
479 trait_ref: &hax::TraitRef,
480 impl_ref: &hax::ItemRef,
481 ) -> Result<Option<GlobalDeclRef>, Error> {
482 self.translate_vtable_instance_ref_maybe_enqueue(true, span, trait_ref, impl_ref)
483 }
484
485 pub fn translate_vtable_instance_ref_no_enqueue(
486 &mut self,
487 span: Span,
488 trait_ref: &hax::TraitRef,
489 impl_ref: &hax::ItemRef,
490 ) -> Result<Option<GlobalDeclRef>, Error> {
491 self.translate_vtable_instance_ref_maybe_enqueue(false, span, trait_ref, impl_ref)
492 }
493
494 pub fn translate_vtable_instance_ref_maybe_enqueue(
495 &mut self,
496 enqueue: bool,
497 span: Span,
498 trait_ref: &hax::TraitRef,
499 impl_ref: &hax::ItemRef,
500 ) -> Result<Option<GlobalDeclRef>, Error> {
501 if !self.trait_is_dyn_compatible(&trait_ref.def_id)? {
502 return Ok(None);
503 }
504 let vtable_ref: GlobalDeclRef = self.translate_item_maybe_enqueue(
509 span,
510 enqueue,
511 impl_ref,
512 TransItemSourceKind::VTableInstance(TraitImplSource::Normal),
513 )?;
514 Ok(Some(vtable_ref))
515 }
516
517 fn get_vtable_instance_info<'a>(
519 &mut self,
520 span: Span,
521 impl_def: &'a hax::FullDef,
522 impl_kind: &TraitImplSource,
523 ) -> Result<(TraitImplRef, TypeDeclRef), Error> {
524 let implemented_trait = match impl_def.kind() {
525 hax::FullDefKind::TraitImpl { trait_pred, .. } => &trait_pred.trait_ref,
526 _ => unreachable!(),
527 };
528 let vtable_struct_ref = self
529 .translate_vtable_struct_ref(span, implemented_trait)?
530 .expect("trait should be dyn-compatible");
531 let impl_ref = self.translate_item(
532 span,
533 impl_def.this(),
534 TransItemSourceKind::TraitImpl(*impl_kind),
535 )?;
536 Ok((impl_ref, vtable_struct_ref))
537 }
538
539 pub(crate) fn translate_vtable_instance(
554 mut self,
555 global_id: GlobalDeclId,
556 item_meta: ItemMeta,
557 impl_def: &hax::FullDef,
558 impl_kind: &TraitImplSource,
559 ) -> Result<GlobalDecl, Error> {
560 let span = item_meta.span;
561 self.translate_def_generics(span, impl_def)?;
562 self.check_no_monomorphize(span)?;
563
564 let (impl_ref, vtable_struct_ref) =
565 self.get_vtable_instance_info(span, impl_def, impl_kind)?;
566 let init = self.register_item(
568 span,
569 impl_def.this(),
570 TransItemSourceKind::VTableInstanceInitializer(*impl_kind),
571 );
572
573 Ok(GlobalDecl {
574 def_id: global_id,
575 item_meta,
576 generics: self.into_generics(),
577 src: ItemSource::VTableInstance { impl_ref },
578 global_kind: GlobalKind::Static,
580 ty: Ty::new(TyKind::Adt(vtable_struct_ref)),
581 init,
582 })
583 }
584
585 fn add_method_to_vtable_value(
586 &mut self,
587 span: Span,
588 impl_def: &hax::FullDef,
589 item: &hax::ImplAssocItem,
590 mut mk_field: impl FnMut(ConstantExprKind),
591 ) -> Result<(), Error> {
592 match self.poly_hax_def(&item.decl_def_id)?.kind() {
594 hax::FullDefKind::AssocFn {
595 vtable_sig: Some(_),
596 ..
597 } => {}
598 _ => return Ok(()),
599 }
600
601 let const_kind = match &item.value {
602 hax::ImplAssocItemValue::Provided {
603 def_id: item_def_id,
604 ..
605 } => {
606 let item_ref = impl_def.this().with_def_id(self.hax_state(), item_def_id);
609 let shim_ref = self
610 .translate_fn_ptr(span, &item_ref, TransItemSourceKind::VTableMethod)?
611 .erase();
612 ConstantExprKind::FnPtr(shim_ref)
613 }
614 hax::ImplAssocItemValue::DefaultedFn { .. } => ConstantExprKind::Opaque(
615 "shim for default methods \
616 aren't yet supported"
617 .to_string(),
618 ),
619 _ => return Ok(()),
620 };
621
622 mk_field(const_kind);
623
624 Ok(())
625 }
626
627 fn add_supertraits_to_vtable_value(
628 &mut self,
629 span: Span,
630 trait_def: &hax::FullDef,
631 impl_def: &hax::FullDef,
632 mut mk_field: impl FnMut(ConstantExprKind),
633 ) -> Result<(), Error> {
634 let hax::FullDefKind::TraitImpl {
635 implied_impl_exprs, ..
636 } = impl_def.kind()
637 else {
638 unreachable!()
639 };
640 let hax::FullDefKind::Trait {
641 implied_predicates, ..
642 } = trait_def.kind()
643 else {
644 unreachable!()
645 };
646 for ((clause, _), impl_expr) in implied_predicates.predicates.iter().zip(implied_impl_exprs)
647 {
648 let hax::ClauseKind::Trait(pred) = clause.kind.hax_skip_binder_ref() else {
649 continue;
650 };
651 if !self.pred_is_for_self(&pred.trait_ref) {
653 continue;
654 }
655
656 let vtable_def_ref = self
657 .translate_region_binder(span, &impl_expr.r#trait, |ctx, tref| {
658 ctx.translate_vtable_struct_ref(span, tref)
659 })?
660 .erase()
661 .expect("parent trait should be dyn compatible");
662 let fn_ptr_ty = TyKind::Adt(vtable_def_ref).into_ty();
663 let kind = match &impl_expr.r#impl {
664 hax::ImplExprAtom::Concrete(impl_item) => {
665 let vtable_instance_ref = self
666 .translate_region_binder(span, &impl_expr.r#trait, |ctx, tref| {
667 ctx.translate_vtable_instance_ref(span, tref, impl_item)
668 })?
669 .erase()
670 .expect("parent trait should be dyn compatible");
671 let global = Box::new(ConstantExpr {
672 kind: ConstantExprKind::Global(vtable_instance_ref),
673 ty: fn_ptr_ty,
674 });
675 ConstantExprKind::Ref(global)
676 }
677 _ => ConstantExprKind::Opaque("missing supertrait vtable".into()),
679 };
680 mk_field(kind);
681 }
682 Ok(())
683 }
684
685 fn gen_vtable_instance_init_body(
693 &mut self,
694 span: Span,
695 impl_def: &hax::FullDef,
696 vtable_struct_ref: TypeDeclRef,
697 ) -> Result<Body, Error> {
698 let hax::FullDefKind::TraitImpl {
699 trait_pred, items, ..
700 } = impl_def.kind()
701 else {
702 unreachable!()
703 };
704 let trait_def = self.hax_def(&trait_pred.trait_ref)?;
705 let implemented_trait = self.translate_trait_decl_ref(span, &trait_pred.trait_ref)?;
706 let self_ty = &implemented_trait.generics.types[0];
708
709 let mut builder = BodyBuilder::new(span, 0);
710 let ret_ty = Ty::new(TyKind::Adt(vtable_struct_ref.clone()));
711 let ret_place = builder.new_var(Some("ret".into()), ret_ty.clone());
712
713 let field_tys = {
716 let vtable_decl_id = vtable_struct_ref.id.as_adt().unwrap().clone();
717 let ItemRef::Type(vtable_def) = self.t_ctx.get_or_translate(vtable_decl_id.into())?
718 else {
719 unreachable!()
720 };
721 let TypeDeclKind::Struct(fields) = &vtable_def.kind else {
722 unreachable!()
723 };
724 fields
725 .iter()
726 .map(|f| &f.ty)
727 .cloned()
728 .map(|ty| ty.substitute(&vtable_struct_ref.generics))
729 .collect_vec()
730 };
731
732 let mut aggregate_fields = vec![];
733 let mut field_ty_iter = field_tys.into_iter();
735
736 let size_ty = field_ty_iter.next().unwrap();
737 let size_local = builder.new_var(Some("size".to_string()), size_ty);
738 builder.push_statement(StatementKind::Assign(
739 size_local.clone(),
740 Rvalue::NullaryOp(NullOp::SizeOf, self_ty.clone()),
741 ));
742 aggregate_fields.push(Operand::Move(size_local));
743
744 let align_ty = field_ty_iter.next().unwrap();
745 let align_local = builder.new_var(Some("align".to_string()), align_ty);
746 builder.push_statement(StatementKind::Assign(
747 align_local.clone(),
748 Rvalue::NullaryOp(NullOp::AlignOf, self_ty.clone()),
749 ));
750 aggregate_fields.push(Operand::Move(align_local));
751
752 let mut mk_field = |kind| {
754 let ty = field_ty_iter.next().unwrap();
755 aggregate_fields.push(Operand::Const(Box::new(ConstantExpr { kind, ty })));
756 };
757
758 let fn_ptr = {
771 let drop_trait = self.tcx.lang_items().drop_trait().unwrap();
773 let drop_impl_expr: hax::ImplExpr = {
774 let s = self.hax_state_with_id();
775 let rustc_trait_args = trait_pred.trait_ref.rustc_args(s);
776 let generics = self.tcx.mk_args(&rustc_trait_args[..1]); let drop_tref =
778 rustc_middle::ty::TraitRef::new_from_args(self.tcx, drop_trait, generics);
779 hax::solve_trait(s, rustc_middle::ty::Binder::dummy(drop_tref))
780 };
781 let drop_tref = self.translate_trait_impl_expr(span, &drop_impl_expr)?;
782 let method_id = self.register_item(
783 span,
784 drop_impl_expr.r#trait.hax_skip_binder_ref(),
785 TransItemSourceKind::DropInPlaceMethod(None),
786 );
787 let item_name = TraitItemName("drop_in_place".to_string());
788 FnPtr::new(
789 FnPtrKind::Trait(drop_tref, item_name, method_id),
790 GenericArgs::empty(),
791 )
792 };
793 mk_field(ConstantExprKind::FnPtr(fn_ptr));
794
795 for item in items {
796 self.add_method_to_vtable_value(span, impl_def, item, &mut mk_field)?;
797 }
798
799 self.add_supertraits_to_vtable_value(span, &trait_def, impl_def, &mut mk_field)?;
800
801 if field_ty_iter.next().is_some() {
802 raise_error!(
803 self,
804 span,
805 "Missed some fields in vtable value construction"
806 )
807 }
808
809 builder.push_statement(StatementKind::Assign(
811 ret_place,
812 Rvalue::Aggregate(
813 AggregateKind::Adt(vtable_struct_ref.clone(), None, None),
814 aggregate_fields,
815 ),
816 ));
817
818 Ok(Body::Unstructured(builder.build()))
819 }
820
821 pub(crate) fn translate_vtable_instance_init(
822 mut self,
823 init_func_id: FunDeclId,
824 item_meta: ItemMeta,
825 impl_def: &hax::FullDef,
826 impl_kind: &TraitImplSource,
827 ) -> Result<FunDecl, Error> {
828 let span = item_meta.span;
829 self.translate_def_generics(span, impl_def)?;
830 self.check_no_monomorphize(span)?;
831
832 let (impl_ref, vtable_struct_ref) =
833 self.get_vtable_instance_info(span, impl_def, impl_kind)?;
834 let init_for = self.register_item(
835 span,
836 impl_def.this(),
837 TransItemSourceKind::VTableInstance(*impl_kind),
838 );
839
840 let sig = FunSig {
842 is_unsafe: false,
843 generics: self.the_only_binder().params.clone(),
844 inputs: vec![],
845 output: Ty::new(TyKind::Adt(vtable_struct_ref.clone())),
846 };
847
848 let body = match impl_kind {
849 TraitImplSource::Normal => {
850 let body = self.gen_vtable_instance_init_body(span, impl_def, vtable_struct_ref)?;
851 Ok(body)
852 }
853 _ => {
854 raise_error!(
855 self,
856 span,
857 "Don't know how to generate a vtable for a virtual impl {impl_kind:?}"
858 );
859 }
860 };
861
862 Ok(FunDecl {
863 def_id: init_func_id,
864 item_meta: item_meta,
865 signature: sig,
866 src: ItemSource::VTableInstance { impl_ref },
867 is_global_initializer: Some(init_for),
868 body,
869 })
870 }
871
872 fn translate_vtable_shim_body(
890 &mut self,
891 span: Span,
892 target_receiver: &Ty,
893 shim_signature: &FunSig,
894 impl_func_def: &hax::FullDef,
895 ) -> Result<Body, Error> {
896 let mut builder = BodyBuilder::new(span, shim_signature.inputs.len());
897
898 let ret_place = builder.new_var(None, shim_signature.output.clone());
899 let mut method_args = shim_signature
900 .inputs
901 .iter()
902 .map(|ty| builder.new_var(None, ty.clone()))
903 .collect_vec();
904 let target_self = builder.new_var(None, target_receiver.clone());
905
906 let shim_self = mem::replace(&mut method_args[0], target_self.clone());
908
909 let rval = Rvalue::UnaryOp(
913 UnOp::Cast(CastKind::Concretize(
914 shim_self.ty().clone(),
915 target_self.ty().clone(),
916 )),
917 Operand::Move(shim_self.clone()),
918 );
919 builder.push_statement(StatementKind::Assign(target_self.clone(), rval));
920
921 let fun_id = self.register_item(span, &impl_func_def.this(), TransItemSourceKind::Fun);
922 let generics = self.outermost_binder().params.identity_args();
923 builder.call(Call {
924 func: FnOperand::Regular(FnPtr::new(FnPtrKind::Fun(fun_id), generics)),
925 args: method_args
926 .into_iter()
927 .map(|arg| Operand::Move(arg))
928 .collect(),
929 dest: ret_place,
930 });
931
932 Ok(Body::Unstructured(builder.build()))
933 }
934
935 pub(crate) fn translate_vtable_shim(
936 mut self,
937 fun_id: FunDeclId,
938 item_meta: ItemMeta,
939 impl_func_def: &hax::FullDef,
940 ) -> Result<FunDecl, Error> {
941 let span = item_meta.span;
942 self.check_no_monomorphize(span)?;
943
944 let hax::FullDefKind::AssocFn {
945 vtable_sig: Some(vtable_sig),
946 sig: target_signature,
947 ..
948 } = impl_func_def.kind()
949 else {
950 raise_error!(
951 self,
952 span,
953 "Trying to generate a vtable shim for a non-vtable-safe method"
954 );
955 };
956
957 let shim_func_def = {
961 let mut def = impl_func_def.clone();
962 let hax::FullDefKind::AssocFn { sig, .. } = &mut def.kind else {
963 unreachable!()
964 };
965 *sig = vtable_sig.clone();
966 def
967 };
968
969 let signature = self.translate_function_signature(&shim_func_def, &item_meta)?;
971
972 let target_receiver = self.translate_ty(span, &target_signature.value.inputs[0])?;
973
974 trace!(
975 "[VtableShim] Obtained dyn signature with receiver type: {}",
976 signature.inputs[0].with_ctx(&self.into_fmt())
977 );
978
979 let body =
980 self.translate_vtable_shim_body(span, &target_receiver, &signature, impl_func_def)?;
981
982 Ok(FunDecl {
983 def_id: fun_id,
984 item_meta,
985 signature,
986 src: ItemSource::VTableMethodShim,
987 is_global_initializer: None,
988 body: Ok(body),
989 })
990 }
991}