@@ -84,16 +84,54 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
8484 ) -> Vec < chc:: Clause > {
8585 let mut clauses = Vec :: new ( ) ;
8686
87- if expected_args. is_empty ( ) {
88- // elaboration: we need at least one predicate variable in parameter (see mir_function_ty_impl)
89- expected_args. push ( rty:: RefinedType :: unrefined ( rty:: Type :: unit ( ) ) . vacuous ( ) ) ;
90- }
9187 tracing:: debug!(
9288 got = %got. display( ) ,
9389 expected = %crate :: pretty:: FunctionType :: new( & expected_args, & expected_ret) . display( ) ,
9490 "fn_sub_type"
9591 ) ;
9692
93+ match got. abi {
94+ rty:: FunctionAbi :: Rust => {
95+ if expected_args. is_empty ( ) {
96+ // elaboration: we need at least one predicate variable in parameter (see mir_function_ty_impl)
97+ expected_args. push ( rty:: RefinedType :: unrefined ( rty:: Type :: unit ( ) ) . vacuous ( ) ) ;
98+ }
99+ }
100+ rty:: FunctionAbi :: RustCall => {
101+ // &Closure, { v: (own i32, own bool) | v = (<0>, <false>) }
102+ // =>
103+ // &Closure, { v: i32 | (<v>, _) = (<0>, <false>) }, { v: bool | (_, <v>) = (<0>, <false>) }
104+
105+ let rty:: RefinedType { ty, mut refinement } =
106+ expected_args. pop ( ) . expect ( "rust-call last arg" ) ;
107+ let ty = ty. into_tuple ( ) . expect ( "rust-call last arg is tuple" ) ;
108+ let mut replacement_tuple = Vec :: new ( ) ; // will be (<v>, _) or (_, <v>)
109+ for elem in & ty. elems {
110+ let existential = refinement. existentials . push ( elem. ty . to_sort ( ) ) ;
111+ replacement_tuple. push ( chc:: Term :: var ( rty:: RefinedTypeVar :: Existential (
112+ existential,
113+ ) ) ) ;
114+ }
115+
116+ for ( i, elem) in ty. elems . into_iter ( ) . enumerate ( ) {
117+ let mut param_ty = elem. deref ( ) ;
118+ param_ty
119+ . refinement
120+ . push_conj ( refinement. clone ( ) . subst_value_var ( || {
121+ let mut value_elems = replacement_tuple. clone ( ) ;
122+ value_elems[ i] = chc:: Term :: var ( rty:: RefinedTypeVar :: Value ) . boxed ( ) ;
123+ chc:: Term :: tuple ( value_elems)
124+ } ) ) ;
125+ expected_args. push ( param_ty) ;
126+ }
127+
128+ tracing:: info!(
129+ expected = %crate :: pretty:: FunctionType :: new( & expected_args, & expected_ret) . display( ) ,
130+ "rust-call expanded" ,
131+ ) ;
132+ }
133+ }
134+
97135 // TODO: check sty and length is equal
98136 let mut builder = self . env . build_clause ( ) ;
99137 for ( param_idx, param_rty) in got. params . iter_enumerated ( ) {
0 commit comments