@@ -119,6 +119,7 @@ impl<T> FormulaOrTerm<T> {
119119 }
120120}
121121
122+ #[ derive( Clone ) ]
122123pub struct AnnotFnTranslator < ' tcx > {
123124 tcx : TyCtxt < ' tcx > ,
124125 local_def_id : LocalDefId ,
@@ -201,6 +202,13 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
201202 self . tcx . normalize_erasing_regions ( param_env, instantiated)
202203 }
203204
205+ fn pat_ty ( & self , pat : & ' tcx rustc_hir:: Pat < ' tcx > ) -> mir_ty:: Ty < ' tcx > {
206+ let ty = self . typeck . pat_ty ( pat) ;
207+ let instantiated = mir_ty:: EarlyBinder :: bind ( ty) . instantiate ( self . tcx , self . generic_args ) ;
208+ let param_env = mir_ty:: ParamEnv :: reveal_all ( ) ;
209+ self . tcx . normalize_erasing_regions ( param_env, instantiated)
210+ }
211+
204212 pub fn to_formula_fn ( & self ) -> FormulaFn < ' tcx > {
205213 let formula = self . to_formula ( self . body . value ) ;
206214 let params = self
@@ -377,6 +385,39 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
377385 if let ExprKind :: Path ( qpath) = & func_expr. kind {
378386 let res = self . typeck . qpath_res ( qpath, func_expr. hir_id ) ;
379387 if let rustc_hir:: def:: Res :: Def ( def_kind, def_id) = res {
388+ if Some ( def_id) == self . def_ids . exists ( ) {
389+ assert_eq ! ( args. len( ) , 1 , "exists takes exactly 1 argument" ) ;
390+ let ExprKind :: Closure ( closure) = args[ 0 ] . kind else {
391+ panic ! ( "exists argument must be a closure" ) ;
392+ } ;
393+ let closure_body = self . tcx . hir ( ) . body ( closure. body ) ;
394+
395+ let mut inner_translator = self . clone ( ) ;
396+ let mut vars = Vec :: new ( ) ;
397+ for param in closure_body. params {
398+ let rustc_hir:: PatKind :: Binding ( _, hir_id, ident, None ) =
399+ param. pat . kind
400+ else {
401+ panic ! (
402+ "exists closure parameter must be a simple binding: {:?}" ,
403+ param. pat
404+ ) ;
405+ } ;
406+ let param_ty = self . pat_ty ( param. pat ) ;
407+ let sort = self . type_builder . build ( param_ty) . to_sort ( ) ;
408+ let var_term = chc:: Term :: FormulaExistentialVar (
409+ sort. clone ( ) ,
410+ ident. name . to_string ( ) ,
411+ ) ;
412+ inner_translator. env . insert ( hir_id, var_term) ;
413+ vars. push ( ( ident. name . to_string ( ) , sort) ) ;
414+ }
415+ let body_formula = inner_translator. to_formula ( closure_body. value ) ;
416+ return FormulaOrTerm :: Formula ( chc:: Formula :: exists (
417+ vars,
418+ body_formula,
419+ ) ) ;
420+ }
380421 if Some ( def_id) == self . def_ids . mut_model_new ( ) {
381422 assert_eq ! ( args. len( ) , 2 , "Mut::new takes exactly 2 arguments" ) ;
382423 let t1 = self . to_term ( & args[ 0 ] ) ;
0 commit comments