@@ -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