@@ -201,6 +201,13 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
201201 self . tcx . normalize_erasing_regions ( param_env, instantiated)
202202 }
203203
204+ fn pat_ty ( & self , pat : & ' tcx rustc_hir:: Pat < ' tcx > ) -> mir_ty:: Ty < ' tcx > {
205+ let ty = self . typeck . pat_ty ( pat) ;
206+ let instantiated = mir_ty:: EarlyBinder :: bind ( ty) . instantiate ( self . tcx , self . generic_args ) ;
207+ let param_env = mir_ty:: ParamEnv :: reveal_all ( ) ;
208+ self . tcx . normalize_erasing_regions ( param_env, instantiated)
209+ }
210+
204211 pub fn to_formula_fn ( & self ) -> FormulaFn < ' tcx > {
205212 let formula = self . to_formula ( self . body . value ) ;
206213 let params = self
@@ -376,6 +383,52 @@ impl<'tcx> AnnotFnTranslator<'tcx> {
376383 if let ExprKind :: Path ( qpath) = & func_expr. kind {
377384 let res = self . typeck . qpath_res ( qpath, func_expr. hir_id ) ;
378385 if let rustc_hir:: def:: Res :: Def ( def_kind, def_id) = res {
386+ if Some ( def_id) == self . def_ids . exists ( ) {
387+ assert_eq ! ( args. len( ) , 1 , "exists takes exactly 1 argument" ) ;
388+ let ExprKind :: Closure ( closure) = args[ 0 ] . kind else {
389+ unimplemented ! ( "exists argument must be a closure" ) ;
390+ } ;
391+ let closure_body = self . tcx . hir ( ) . body ( closure. body ) ;
392+ let mut inner = self . env . clone ( ) ;
393+ let mut vars = Vec :: new ( ) ;
394+ for param in closure_body. params {
395+ let rustc_hir:: PatKind :: Binding ( _, hir_id, ident, None ) =
396+ param. pat . kind
397+ else {
398+ unimplemented ! (
399+ "exists closure parameter must be a simple binding: {:?}" ,
400+ param. pat
401+ ) ;
402+ } ;
403+ let param_ty = self . pat_ty ( param. pat ) ;
404+ let sort = self . type_builder . build ( param_ty) . to_sort ( ) ;
405+ let var_term = chc:: Term :: FormulaExistentialVar (
406+ sort. clone ( ) ,
407+ ident. name . to_string ( ) ,
408+ ) ;
409+ inner. insert ( hir_id, var_term) ;
410+ vars. push ( ( ident. name . to_string ( ) , sort) ) ;
411+ }
412+ let inner_translator = Self {
413+ env : inner,
414+ tcx : self . tcx ,
415+ local_def_id : self . local_def_id ,
416+ typeck : self . typeck ,
417+ body : self . body ,
418+ generic_args : self . generic_args ,
419+ def_ids : self . def_ids . clone ( ) ,
420+ type_builder : TypeBuilder :: new (
421+ self . tcx ,
422+ self . def_ids . clone ( ) ,
423+ self . local_def_id . to_def_id ( ) ,
424+ ) ,
425+ } ;
426+ let body_formula = inner_translator. to_formula ( closure_body. value ) ;
427+ return FormulaOrTerm :: Formula ( chc:: Formula :: exists (
428+ vars,
429+ body_formula,
430+ ) ) ;
431+ }
379432 if Some ( def_id) == self . def_ids . mut_model_new ( ) {
380433 assert_eq ! ( args. len( ) , 2 , "Mut::new takes exactly 2 arguments" ) ;
381434 let t1 = self . to_term ( & args[ 0 ] ) ;
0 commit comments