Skip to content

Commit 9c89768

Browse files
committed
fix(annot_fn): wrap closure receiver in Mut/Box for FnMut/Fn
1 parent 2458b2e commit 9c89768

1 file changed

Lines changed: 29 additions & 2 deletions

File tree

src/analyze/annot_fn.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,33 @@ impl<'a, 'tcx> AnnotFnTranslator<'a, 'tcx> {
425425
}
426426
}
427427

428+
/// Wraps a closure receiver term to match the closure's "self" type.
429+
///
430+
/// For `FnOnce` the receiver is the closure value itself, so the term is returned
431+
/// unchanged. For `Fn` the receiver is `&T` (sort `Box<T>`), and for `FnMut` it is
432+
/// `&mut T` (sort `Mut<T>`); the term is wrapped accordingly so that it matches
433+
/// the sort expected by the registered pre/post forall predicates.
434+
fn wrap_closure_receiver(
435+
&self,
436+
receiver: &'tcx rustc_hir::Expr<'tcx>,
437+
fn_ty: &rty::FunctionType,
438+
) -> chc::Term<rty::FunctionParamIdx> {
439+
let receiver_term = self.to_term(receiver);
440+
let first_param = &fn_ty.params[rty::FunctionParamIdx::from_usize(0)];
441+
match first_param.ty.as_pointer() {
442+
Some(p) if p.is_mut() => chc::Term::mut_(receiver_term.clone(), receiver_term),
443+
Some(p)
444+
if matches!(
445+
p.kind,
446+
rty::PointerKind::Own | rty::PointerKind::Ref(rty::RefKind::Immut)
447+
) =>
448+
{
449+
chc::Term::box_(receiver_term)
450+
}
451+
_ => receiver_term,
452+
}
453+
}
454+
428455
/// The values of a closure's parameters: the closure's first (RustCall) parameter is its
429456
/// environment, which is the closure value itself, followed by the logical arguments.
430457
fn translate_closure_precondition(
@@ -450,7 +477,7 @@ impl<'a, 'tcx> AnnotFnTranslator<'a, 'tcx> {
450477
"closure precondition arity mismatch: closure takes {} argument(s)",
451478
fn_ty.params.len() - 1
452479
);
453-
let param_args: Vec<_> = std::iter::once(self.to_term(receiver))
480+
let param_args: Vec<_> = std::iter::once(self.wrap_closure_receiver(receiver, &fn_ty))
454481
.chain(logical_args)
455482
.collect();
456483
FormulaOrTerm::Formula(fn_ty.precondition_formula(&param_args))
@@ -480,7 +507,7 @@ impl<'a, 'tcx> AnnotFnTranslator<'a, 'tcx> {
480507
"closure postcondition arity mismatch: closure takes {} argument(s)",
481508
fn_ty.params.len() - 1
482509
);
483-
let param_args: Vec<_> = std::iter::once(self.to_term(receiver))
510+
let param_args: Vec<_> = std::iter::once(self.wrap_closure_receiver(receiver, &fn_ty))
484511
.chain(logical_args)
485512
.collect();
486513
let result = self.to_term(result);

0 commit comments

Comments
 (0)