1use crate::hax;
45use itertools::Itertools;
46use std::mem;
47
48use super::translate_crate::TransItemSourceKind;
49use super::translate_ctx::*;
50use charon_lib::ullbc_ast::*;
51
52pub fn translate_closure_kind(kind: &hax::ClosureKind) -> ClosureKind {
53 match kind {
54 hax::ClosureKind::Fn => ClosureKind::Fn,
55 hax::ClosureKind::FnMut => ClosureKind::FnMut,
56 hax::ClosureKind::FnOnce => ClosureKind::FnOnce,
57 }
58}
59
60pub fn recognize_fn_trait_impl_proof(
63 trait_proof: &hax::TraitProof,
64) -> Option<(hax::Binder<&hax::Ty>, ClosureKind)> {
65 let hax::TraitProofKind::Builtin {
66 trait_data: hax::BuiltinTraitData::Other(lang_item),
67 ..
68 } = &trait_proof.kind
69 else {
70 return None;
71 };
72 let kind = match lang_item {
73 hax::SolverTraitLangItem::FnOnce => ClosureKind::FnOnce,
74 hax::SolverTraitLangItem::FnMut => ClosureKind::FnMut,
75 hax::SolverTraitLangItem::Fn => ClosureKind::Fn,
76 _ => return None,
77 };
78 let Some(hax::GenericArg::Type(self_ty)) =
79 trait_proof.pred.hax_skip_binder_ref().generic_args.first()
80 else {
81 unreachable!("no `Self` type arg on a `Fn*` trait ref")
82 };
83 Some((trait_proof.pred.rebind(self_ty), kind))
84}
85
86pub fn callable_virtual_impl<'a>(
88 def: &'a hax::FullDef<'_>,
89 target_kind: ClosureKind,
90) -> &'a hax::VirtualTraitImpl {
91 CallableFnImpls::from_def(def)
92 .and_then(|impls| impls.vimpl(target_kind))
93 .expect("expected a callable with a Fn* impl")
94}
95
96#[derive(Clone, Copy)]
97enum Callable<'a> {
98 Closure(&'a hax::ClosureArgs),
99 FnDef {
100 item: &'a hax::ItemRef,
101 sig: &'a hax::PolyFnSig,
102 tupled_args_ty: &'a hax::Binder<hax::Ty>,
104 },
105}
106
107impl<'a> Callable<'a> {
108 fn item(self) -> &'a hax::ItemRef {
109 match self {
110 Callable::Closure(args) => &args.item,
111 Callable::FnDef { item, .. } => item,
112 }
113 }
114
115 fn sig(self) -> &'a hax::PolyFnSig {
116 match self {
117 Callable::Closure(args) => &args.fn_sig,
118 Callable::FnDef { sig, .. } => sig,
119 }
120 }
121
122 fn tupled_args_ty(self) -> &'a hax::Ty {
125 match self {
126 Callable::Closure(args) => args.tupled_args_ty.hax_skip_binder_ref(),
127 Callable::FnDef { tupled_args_ty, .. } => tupled_args_ty.hax_skip_binder_ref(),
128 }
129 }
130}
131
132#[derive(Clone, Copy)]
133struct CallableFnImpls<'a> {
134 callable: Callable<'a>,
135 fn_once_impl: Option<&'a hax::VirtualTraitImpl>,
136 fn_mut_impl: Option<&'a hax::VirtualTraitImpl>,
137 fn_impl: Option<&'a hax::VirtualTraitImpl>,
138}
139
140impl<'a> CallableFnImpls<'a> {
141 fn from_def(def: &'a hax::FullDef<'_>) -> Option<Self> {
142 match def.kind() {
143 hax::FullDefKind::Closure {
144 args,
145 fn_once_impl,
146 fn_mut_impl,
147 fn_impl,
148 ..
149 } => Some(Self {
150 callable: Callable::Closure(args),
151 fn_once_impl: Some(fn_once_impl),
152 fn_mut_impl: fn_mut_impl.as_deref(),
153 fn_impl: fn_impl.as_deref(),
154 }),
155 hax::FullDefKind::Fn {
156 sig,
157 tupled_args_ty,
158 fn_once_impl,
159 fn_mut_impl,
160 fn_impl,
161 ..
162 }
163 | hax::FullDefKind::AssocFn {
164 sig,
165 tupled_args_ty,
166 fn_once_impl,
167 fn_mut_impl,
168 fn_impl,
169 ..
170 }
171 | hax::FullDefKind::Ctor {
172 sig,
173 tupled_args_ty,
174 fn_once_impl,
175 fn_mut_impl,
176 fn_impl,
177 ..
178 } => Some(Self {
179 callable: Callable::FnDef {
180 item: def.this(),
181 sig,
182 tupled_args_ty: tupled_args_ty.as_ref()?,
183 },
184 fn_once_impl: fn_once_impl.as_deref(),
185 fn_mut_impl: fn_mut_impl.as_deref(),
186 fn_impl: fn_impl.as_deref(),
187 }),
188 _ => None,
189 }
190 }
191
192 fn vimpl(self, target_kind: ClosureKind) -> Option<&'a hax::VirtualTraitImpl> {
193 match target_kind {
194 ClosureKind::FnOnce => self.fn_once_impl,
195 ClosureKind::FnMut => self.fn_mut_impl,
196 ClosureKind::Fn => self.fn_impl,
197 }
198 }
199}
200
201impl<'tcx> ItemTransCtx<'tcx, '_> {
206 fn translate_callable_bound_ref_with_late_bound(
209 &mut self,
210 span: Span,
211 callable: Callable<'_>,
212 kind: TransItemSourceKind,
213 ) -> Result<RegionBinder<DeclRef<ItemId>>, Error> {
214 if !matches!(
215 kind,
216 TransItemSourceKind::TraitImpl(..) | TransItemSourceKind::ClosureAsFnCast
217 ) {
218 raise_error!(
219 self,
220 span,
221 "Called `translate_callable_bound_ref_with_late_bound` on a `{kind:?}`; \
222 use `translate_closure_ref_with_upvars` \
223 or `translate_callable_bound_ref_with_method_bound` instead"
224 )
225 }
226 let dref: DeclRef<ItemId> = self.translate_item(span, callable.item(), kind)?;
227 self.translate_region_binder(span, callable.sig(), |ctx, _| {
228 let mut dref = dref.move_under_binder();
229 for (a, b) in dref.generics.regions.iter_mut().rev().zip(
231 ctx.innermost_binder()
232 .params
233 .identity_args()
234 .regions
235 .into_iter()
236 .rev(),
237 ) {
238 *a = b;
239 }
240 Ok(dref)
241 })
242 }
243
244 fn translate_callable_bound_ref_with_method_bound(
248 &mut self,
249 span: Span,
250 item: &hax::ItemRef,
251 kind: TransItemSourceKind,
252 target_kind: ClosureKind,
253 ) -> Result<RegionBinder<DeclRef<ItemId>>, Error> {
254 if !matches!(kind, TransItemSourceKind::CallableMethod(..)) {
255 raise_error!(
256 self,
257 span,
258 "Called `translate_callable_bound_ref_with_method_bound` on a `{kind:?}`; \
259 use `translate_closure_ref_with_upvars` \
260 or `translate_callable_bound_ref_with_late_bound` instead"
261 )
262 }
263 let dref: DeclRef<ItemId> = self.translate_item(span, item, kind)?;
264 let mut dref = dref.move_under_binder();
265 let mut regions = IndexVec::new();
266 match target_kind {
267 ClosureKind::FnOnce => {}
268 ClosureKind::FnMut | ClosureKind::Fn => {
269 let rid =
270 regions.push_with(|index| RegionParam::new(index, None, Variance::Covariant));
271 *dref.generics.regions.iter_mut().last().unwrap() =
272 Region::Var(DeBruijnVar::new_at_zero(rid));
273 }
274 }
275 Ok(RegionBinder {
276 regions,
277 skip_binder: dref,
278 })
279 }
280
281 pub fn recognize_callable_impl_proof(
285 &self,
286 trait_proof: &hax::TraitProof,
287 ) -> Option<(hax::ItemRef, ClosureKind)> {
288 let hax::TraitProofKind::Builtin {
289 trait_data: hax::BuiltinTraitData::Other(lang_item),
290 ..
291 } = &trait_proof.kind
292 else {
293 return None;
294 };
295 let target_kind = match lang_item {
296 hax::SolverTraitLangItem::FnOnce => ClosureKind::FnOnce,
297 hax::SolverTraitLangItem::FnMut => ClosureKind::FnMut,
298 hax::SolverTraitLangItem::Fn => ClosureKind::Fn,
299 _ => return None,
300 };
301 let hax::GenericArg::Type(callable_ty) = trait_proof
303 .pred
304 .hax_skip_binder_ref()
305 .generic_args
306 .first()?
307 else {
308 return None;
309 };
310 let item = match callable_ty.kind() {
311 hax::TyKind::Closure(closure_args) => &closure_args.item,
312 hax::TyKind::FnDef { item, .. } => item,
313 _ => return None,
314 };
315 Some((item.erase(self.hax_state_with_id()), target_kind))
316 }
317
318 pub(crate) fn translate_callable_method_fn_ptr(
319 &mut self,
320 span: Span,
321 item: &hax::ItemRef,
322 ) -> Result<Option<RegionBinder<FnPtr>>, Error> {
323 if !self.monomorphize() {
324 return Ok(None);
325 }
326 let Some(in_trait) = &item.in_trait else {
327 return Ok(None);
328 };
329 let Some((callable, target_kind)) = self.recognize_callable_impl_proof(in_trait) else {
330 return Ok(None);
331 };
332 let kind = TransItemSourceKind::CallableMethod(target_kind);
333 let bound_ref = self.translate_callable_bound_ref_with_method_bound(
334 span,
335 &callable,
336 kind,
337 target_kind,
338 )?;
339 Ok(Some(bound_ref.map(|dref| {
340 let fn_ref: FunDeclRef = dref.try_into().unwrap();
341 FnPtr::new(FnPtrKind::Fun(fn_ref.id), fn_ref.generics)
342 })))
343 }
344}
345
346impl<'tcx> ItemTransCtx<'tcx, '_> {
347 pub fn translate_closure_type_ref(
349 &mut self,
350 span: Span,
351 closure: &hax::ClosureArgs,
352 ) -> Result<TypeDeclRef, Error> {
353 self.translate_type_decl_ref(span, &closure.item)
354 }
355
356 pub fn translate_stateless_closure_as_fn_ref(
360 &mut self,
361 span: Span,
362 closure: &hax::ClosureArgs,
363 ) -> Result<RegionBinder<FunDeclRef>, Error> {
364 let kind = TransItemSourceKind::ClosureAsFnCast;
365 let bound_dref = self.translate_callable_bound_ref_with_late_bound(
366 span,
367 Callable::Closure(closure),
368 kind,
369 )?;
370 Ok(bound_dref.map(|dref| dref.try_into().unwrap()))
371 }
372
373 pub fn translate_closure_bound_impl_ref(
377 &mut self,
378 span: Span,
379 closure: &hax::ClosureArgs,
380 target_kind: ClosureKind,
381 ) -> Result<RegionBinder<TraitImplRef>, Error> {
382 let kind = TransItemSourceKind::TraitImpl(TransImplSource::Callable(target_kind));
383 let bound_dref = self.translate_callable_bound_ref_with_late_bound(
384 span,
385 Callable::Closure(closure),
386 kind,
387 )?;
388 Ok(bound_dref.map(|dref| dref.try_into().unwrap()))
389 }
390
391 pub fn translate_callable_impl_ref(
393 &mut self,
394 span: Span,
395 item: &hax::ItemRef,
396 target_kind: ClosureKind,
397 ) -> Result<TraitImplRef, Error> {
398 self.translate_item(
399 span,
400 item,
401 TransItemSourceKind::TraitImpl(TransImplSource::Callable(target_kind)),
402 )
403 }
404
405 pub fn translate_closure_info(
406 &mut self,
407 span: Span,
408 args: &hax::ClosureArgs,
409 ) -> Result<ClosureInfo, Error> {
410 use ClosureKind::*;
411 let kind = translate_closure_kind(&args.kind);
412
413 let fn_once_impl = self.translate_closure_bound_impl_ref(span, args, FnOnce)?;
414 let fn_mut_impl = if matches!(kind, FnMut | Fn) {
415 Some(self.translate_closure_bound_impl_ref(span, args, FnMut)?)
416 } else {
417 None
418 };
419 let fn_impl = if matches!(kind, Fn) {
420 Some(self.translate_closure_bound_impl_ref(span, args, Fn)?)
421 } else {
422 None
423 };
424 let signature = self.translate_poly_fun_sig(span, &args.fn_sig)?;
425 Ok(ClosureInfo {
426 kind,
427 fn_once_impl,
428 fn_mut_impl,
429 fn_impl,
430 signature,
431 })
432 }
433
434 fn get_callable_state_ty(&mut self, span: Span, callable: Callable<'_>) -> Result<Ty, Error> {
435 Ok(match callable {
436 Callable::Closure(args) => {
437 let tref = self.translate_closure_type_ref(span, args)?;
438 TyKind::Adt(tref).into_ty()
439 }
440 Callable::FnDef { item, .. } => {
441 let fn_ref = self.translate_bound_fn_ptr(span, item, TransItemSourceKind::Fun)?;
442 TyKind::FnDef(fn_ref).into_ty()
443 }
444 })
445 }
446
447 pub fn translate_closure_upvar_tys(
451 &mut self,
452 span: Span,
453 args: &hax::ClosureArgs,
454 ) -> Result<IndexVec<FieldId, Ty>, Error> {
455 args.upvar_tys
456 .iter()
457 .map(|ty| self.translate_ty(span, ty))
458 .try_collect()
459 }
460
461 pub fn translate_closure_adt(
462 &mut self,
463 span: Span,
464 _args: &hax::ClosureArgs,
465 ) -> Result<TypeDeclKind, Error> {
466 let fields: IndexVec<FieldId, Field> = self
467 .the_only_binder()
468 .closure_upvar_tys
469 .as_ref()
470 .unwrap()
471 .iter()
472 .cloned()
473 .enumerate()
474 .map(|(field_id, ty)| Field {
475 span,
476 attr_info: AttrInfo::dummy_private(),
477 name: format!("_{field_id}"),
478 is_positional: true,
479 ty,
480 })
481 .collect();
482 Ok(TypeDeclKind::Struct(fields))
483 }
484
485 fn translate_callable_method_sig(
488 &mut self,
489 def: &hax::FullDef<'tcx>,
490 span: Span,
491 callable: Callable,
492 target_kind: ClosureKind,
493 ) -> Result<RegionBinder<FunSig>, Error> {
494 let signature = callable.sig();
495 trace!(
496 "signature of callable {:?}:\n{:?}",
497 def.def_id(),
498 signature.value,
499 );
500
501 let mut bound_regions = IndexVec::new();
502 let mut fun_sig = self
503 .translate_fun_sig(span, signature.hax_skip_binder_ref())?
504 .move_under_binder();
505 let state_ty = self
506 .get_callable_state_ty(span, callable)?
507 .move_under_binder();
508
509 let state_ty = match target_kind {
511 ClosureKind::FnOnce => state_ty,
512 ClosureKind::Fn | ClosureKind::FnMut => {
513 let rid = bound_regions
514 .push_with(|index| RegionParam::new(index, None, Variance::Covariant));
515 let r = Region::Var(DeBruijnVar::new_at_zero(rid));
516 let mutability = if target_kind == ClosureKind::Fn {
517 RefKind::Shared
518 } else {
519 RefKind::Mut
520 };
521 TyKind::Ref(r, state_ty, mutability).into_ty()
522 }
523 };
524
525 let tupled_args_ty = self
526 .translate_ty(span, callable.tupled_args_ty())?
527 .move_under_binder();
528 fun_sig.inputs = vec![state_ty, tupled_args_ty];
529
530 Ok(RegionBinder {
531 regions: bound_regions,
532 skip_binder: fun_sig,
533 })
534 }
535
536 fn translate_callable_method_body(
537 &mut self,
538 span: Span,
539 def: &hax::FullDef<'tcx>,
540 target_kind: ClosureKind,
541 callable: Callable,
542 signature: &FunSig,
543 ) -> Result<Body, Error> {
544 match callable {
545 Callable::Closure(args) => {
546 self.translate_closure_method_body(span, def, target_kind, args, signature)
547 }
548 Callable::FnDef { item, .. } => {
549 self.translate_fn_def_method_body(span, item, signature)
550 }
551 }
552 }
553
554 fn translate_closure_method_body(
555 &mut self,
556 span: Span,
557 def: &hax::FullDef<'tcx>,
558 target_kind: ClosureKind,
559 args: &hax::ClosureArgs,
560 signature: &FunSig,
561 ) -> Result<Body, Error> {
562 use ClosureKind::*;
563 let closure_kind = translate_closure_kind(&args.kind);
564 Ok(match (target_kind, closure_kind) {
565 (Fn, Fn) | (FnMut, FnMut) | (FnOnce, FnOnce) => {
566 let mut body = self.translate_def_body(span, def);
568 let Body::Unstructured(GExprBody {
577 locals,
578 body: blocks,
579 ..
580 }) = &mut body
581 else {
582 return Ok(body);
583 };
584
585 let tupled_ty = &signature.inputs[1];
587
588 blocks.dyn_visit_mut(|local: &mut LocalId| {
589 if local.index() >= 2 {
590 *local += 1;
591 }
592 });
593
594 let closure_arg_count = locals.arg_count - 1;
596 let mut old_locals = mem::take(&mut locals.locals).into_iter();
597 locals.arg_count = 2;
598 locals.locals.push(old_locals.next().unwrap()); locals.locals.push(old_locals.next().unwrap()); let tupled_arg = locals.new_var(Some("tupled_args".to_string()), tupled_ty.clone());
601 locals.locals.extend(old_locals.map(|mut l| {
602 l.index += 1;
603 l
604 }));
605
606 let untupled_args = locals
607 .locals
608 .iter()
609 .skip(3)
610 .take(closure_arg_count)
611 .map(|l| &l.ty)
612 .cloned();
613 let new_stts = untupled_args.enumerate().map(|(i, ty)| {
614 let nth_field = tupled_arg
615 .clone()
616 .project(ProjectionElem::Field(None, FieldId::new(i)), ty);
617 let local_id = LocalId::new(i + 3);
618 Statement::new(
619 span,
620 StatementKind::Assign(
621 locals.place_for_var(local_id),
622 Rvalue::Use(Operand::Move(nth_field), WithRetag::No),
623 ),
624 )
625 });
626 blocks[BlockId::ZERO].statements.splice(0..0, new_stts);
627
628 body
629 }
630 (FnOnce, Fn | FnMut) => {
640 let Some(body) = def.this.closure_once_shim(self.hax_state()) else {
642 panic!("missing shim for closure")
643 };
644 self.translate_body(span, body, &def.source_text)
645 }
646 (FnMut, Fn) => {
653 let fun_id: FunDeclId = self.register_item(
654 span,
655 def.this(),
656 TransItemSourceKind::CallableMethod(closure_kind),
657 );
658 let impl_ref = self.translate_callable_impl_ref(span, &args.item, closure_kind)?;
659 let fn_op = FnOperand::Regular(FnPtr::new(
662 fun_id.into(),
663 impl_ref.generics.concat(&GenericArgs {
664 regions: vec![self.translate_erased_region()].into(),
665 ..GenericArgs::empty()
666 }),
667 ));
668
669 let mut builder = BodyBuilder::new(span, 2);
670
671 let output = builder.new_var(None, signature.output.clone());
672 let state = builder.new_var(Some("state".to_string()), signature.inputs[0].clone());
673 let args = builder.new_var(Some("args".to_string()), signature.inputs[1].clone());
674 let deref_state = state.deref();
675 let reborrow_ty = TyKind::Ref(
676 self.translate_erased_region(),
677 deref_state.ty.clone(),
678 RefKind::Shared,
679 )
680 .into_ty();
681 let reborrow = builder.new_var(None, reborrow_ty);
682
683 builder.push_statement(StatementKind::Assign(
684 reborrow.clone(),
685 Rvalue::Ref {
686 place: deref_state,
687 kind: BorrowKind::Shared,
688 ptr_metadata: Operand::mk_const_unit(),
690 },
691 ));
692
693 builder.call(Call {
694 func: fn_op,
695 args: vec![Operand::Move(reborrow), Operand::Move(args)],
696 dest: output,
697 });
698
699 Body::Unstructured(builder.build())
700 }
701 (Fn, FnOnce) | (Fn, FnMut) | (FnMut, FnOnce) => {
702 panic!(
703 "Can't make a closure body for a more restrictive kind \
704 than the closure kind"
705 )
706 }
707 })
708 }
709
710 fn translate_fn_def_method_body(
711 &mut self,
712 span: Span,
713 item: &hax::ItemRef,
714 signature: &FunSig,
715 ) -> Result<Body, Error> {
716 let late_bound_regions = self
717 .innermost_binder()
718 .bound_region_vars
719 .iter()
720 .map(|rid| Region::Var(DeBruijnVar::new_at_zero(*rid)))
721 .collect();
722 let fn_ptr = self
723 .translate_bound_fn_ptr(span, item, TransItemSourceKind::Fun)?
724 .apply(late_bound_regions);
725 let fn_op = FnOperand::Regular(fn_ptr);
726
727 let mut builder = BodyBuilder::new(span, 2);
728
729 let output = builder.new_var(None, signature.output.clone());
730 let _state = builder.new_var(Some("state".to_string()), signature.inputs[0].clone());
731 let tupled_args_ty = &signature.inputs[1];
732 let tupled_args = builder.new_var(Some("args".to_string()), tupled_args_ty.clone());
733
734 let tuple_id = tupled_args_ty.as_adt().unwrap().id;
737 let _ = self.get_or_translate(ItemId::Type(tuple_id))?;
738 let arg_tys = tupled_args_ty.as_tuple_fields(&self.t_ctx.translated);
739
740 let args = arg_tys
741 .into_iter()
742 .enumerate()
743 .map(|(i, ty)| {
744 let nth_field = tupled_args
745 .clone()
746 .project(ProjectionElem::Field(None, FieldId::new(i)), ty);
747 Operand::Move(nth_field)
748 })
749 .collect();
750
751 builder.call(Call {
752 func: fn_op,
753 args,
754 dest: output,
755 });
756
757 Ok(Body::Unstructured(builder.build()))
758 }
759
760 #[tracing::instrument(skip(self, item_meta))]
763 pub fn translate_closure_method(
764 mut self,
765 def_id: FunDeclId,
766 item_meta: ItemMeta,
767 def: &hax::FullDef<'tcx>,
768 target_kind: ClosureKind,
769 ) -> Result<FunDecl, Error> {
770 let span = item_meta.span;
771 let callable_impls = CallableFnImpls::from_def(def).unwrap();
772 let callable = callable_impls.callable;
773
774 let vimpl = callable_impls.vimpl(target_kind).unwrap();
776 let implemented_trait = self.translate_trait_predicate(span, &vimpl.trait_pred)?;
777 let method_id =
778 self.translate_trait_method_id(implemented_trait.id, &vimpl.methods[0].0)?;
779
780 let impl_ref = self.translate_callable_impl_ref(span, callable.item(), target_kind)?;
781 let src = FunSource::TraitImpl {
782 impl_ref,
783 trait_ref: implemented_trait.clone(),
784 item_id: method_id,
785 reuses_default: false,
786 };
787
788 let bound_sig = self.translate_callable_method_sig(def, span, callable, target_kind)?;
790 let signature = bound_sig.apply(
792 self.the_only_binder()
793 .closure_call_method_region
794 .iter()
795 .map(|r| Region::Var(DeBruijnVar::new_at_zero(*r)))
796 .collect(),
797 );
798
799 let body = if item_meta.opacity.with_private_contents().is_opaque() {
800 Body::Opaque
801 } else {
802 self.translate_callable_method_body(span, def, target_kind, callable, &signature)?
803 };
804
805 Ok(FunDecl {
806 def_id,
807 item_meta,
808 generics: self.into_generics(),
809 signature: Box::new(signature),
810 src,
811 body,
812 })
813 }
814
815 #[tracing::instrument(skip(self, item_meta))]
816 pub fn translate_closure_trait_impl(
817 mut self,
818 def_id: TraitImplId,
819 item_meta: ItemMeta,
820 def: &hax::FullDef<'tcx>,
821 target_kind: ClosureKind,
822 ) -> Result<TraitImpl, Error> {
823 let span = item_meta.span;
824 let callable_impls = CallableFnImpls::from_def(def).unwrap();
825 let callable = callable_impls.callable;
826
827 let vimpl = callable_impls.vimpl(target_kind).unwrap();
829 let mut timpl = self.translate_virtual_trait_impl(
830 def_id,
831 item_meta,
832 callable.item(),
833 TransImplSource::Callable(target_kind),
834 vimpl,
835 )?;
836
837 let trait_decl_id = timpl.impl_trait.id;
839 let trait_method_id = self.translate_trait_method_id(trait_decl_id, &vimpl.methods[0].0)?;
840 let call_fn_binder = {
841 let kind = TransItemSourceKind::CallableMethod(target_kind);
842 let bound_method_ref: RegionBinder<DeclRef<ItemId>> = self
843 .translate_callable_bound_ref_with_method_bound(
844 span,
845 callable.item(),
846 kind,
847 target_kind,
848 )?;
849 let params = GenericParams {
850 regions: bound_method_ref.regions,
851 ..GenericParams::empty()
852 };
853 let fn_decl_ref: FunDeclRef = bound_method_ref.skip_binder.try_into().unwrap();
854 Binder::new(
855 BinderKind::TraitMethod(trait_decl_id, trait_method_id),
856 params,
857 fn_decl_ref,
858 )
859 };
860 if self.monomorphize() {
861 return Ok(timpl);
862 }
863 timpl
864 .methods
865 .set_slot_extend(trait_method_id, call_fn_binder);
866
867 Ok(timpl)
868 }
869
870 #[tracing::instrument(skip(self, item_meta))]
873 pub fn translate_stateless_closure_as_fn(
874 mut self,
875 def_id: FunDeclId,
876 item_meta: ItemMeta,
877 def: &hax::FullDef<'tcx>,
878 ) -> Result<FunDecl, Error> {
879 let span = item_meta.span;
880 let hax::FullDefKind::Closure { args: closure, .. } = &def.kind else {
881 unreachable!()
882 };
883
884 trace!("About to translate closure as fn:\n{:?}", def.def_id());
885
886 assert!(
887 closure.upvar_tys.is_empty(),
888 "Only stateless closures can be translated as functions"
889 );
890
891 let signature = self.translate_fun_sig(span, closure.fn_sig.hax_skip_binder_ref())?;
893 let state_ty = self.get_callable_state_ty(span, Callable::Closure(closure))?;
894
895 let body = if item_meta.opacity.with_private_contents().is_opaque() {
896 Body::Opaque
897 } else {
898 let fun_id: FunDeclId = self.register_item(
906 span,
907 def.this(),
908 TransItemSourceKind::CallableMethod(ClosureKind::FnOnce),
909 );
910 let impl_ref =
911 self.translate_callable_impl_ref(span, &closure.item, ClosureKind::FnOnce)?;
912 let fn_op = FnOperand::Regular(FnPtr::new(fun_id.into(), impl_ref.generics.clone()));
913
914 let mut builder = BodyBuilder::new(span, signature.inputs.len());
915
916 let output = builder.new_var(None, signature.output.clone());
917 let args: Vec<Place> = signature
918 .inputs
919 .iter()
920 .enumerate()
921 .map(|(i, ty)| builder.new_var(Some(format!("arg{}", i + 1)), ty.clone()))
922 .collect();
923 let args_tupled_ty =
924 self.translate_ty(span, closure.tupled_args_ty.hax_skip_binder_ref())?;
925 let args_tupled = builder.new_var(Some("args".to_string()), args_tupled_ty.clone());
926 let state = builder.new_var(Some("state".to_string()), state_ty.clone());
927
928 builder.push_statement(StatementKind::Assign(
929 args_tupled.clone(),
930 Rvalue::Aggregate(
931 AggregateKind::Adt(args_tupled_ty.as_adt().unwrap().clone(), None, None),
932 args.into_iter().map(Operand::Move).collect(),
933 ),
934 ));
935
936 let state_ty_adt = state_ty.as_adt().unwrap();
937 builder.push_statement(StatementKind::Assign(
938 state.clone(),
939 Rvalue::Aggregate(AggregateKind::Adt(state_ty_adt.clone(), None, None), vec![]),
940 ));
941
942 builder.call(Call {
943 func: fn_op,
944 args: vec![Operand::Move(state), Operand::Move(args_tupled)],
945 dest: output,
946 });
947
948 Body::Unstructured(builder.build())
949 };
950
951 Ok(FunDecl {
952 def_id,
953 item_meta,
954 generics: self.into_generics(),
955 signature: Box::new(signature),
956 src: FunSource::Normal,
957 body,
958 })
959 }
960}