11use crate :: encoders:: {
2- domain:: { DomainBuilder , DomainEnc , DomainEncOutputRef , DomainEncSpecifics } , predicate:: { PredicateBuilder , PredicateEncData } , rust_ty_snapshots:: RustTySnapshotsEnc , snapshot:: SnapshotEncOutput , PredicateEnc , PredicateEncOutputRef
2+ domain:: { DomainBuilder , DomainEnc , DomainEncOutputRef , DomainEncSpecifics } , predicate:: { PredicateBuilder , PredicateEncData } , rust_ty_snapshots:: RustTySnapshotsEnc , snapshot:: SnapshotEncOutput , GenericEnc , PredicateEnc , PredicateEncOutputRef
33} ;
44use prusti_rustc_interface:: middle:: ty;
55use task_encoder:: { EncodeFullError , TaskEncoder , TaskEncoderDependencies } ;
6- use vir:: { FunctionIdent , ToKnownArity , UnaryArity } ;
6+ use vir:: { FunctionIdent , MethodIdent , ToKnownArity , UnaryArity , UnknownArity } ;
77
88#[ derive( Clone , Copy , Debug ) ]
99pub struct DomainDataArray < ' vir > {
@@ -24,21 +24,27 @@ impl<'vir> DomainEncSpecifics<'vir> {
2424 }
2525}
2626
27- // TODO: PredicateEncDataArray
27+ #[ derive( Clone , Copy , Debug ) ]
28+ pub struct PredicateEncDataArray < ' vir > {
29+ pub snap_data : DomainDataArray < ' vir > ,
30+ pub index_access : FunctionIdent < ' vir , UnknownArity < ' vir > > ,
31+ pub unfold_index : MethodIdent < ' vir , UnknownArity < ' vir > > ,
32+ pub fold_index : MethodIdent < ' vir , UnknownArity < ' vir > > ,
33+ }
2834
2935impl < ' vir > PredicateEncOutputRef < ' vir > {
3036 #[ track_caller]
31- pub fn expect_array ( & self ) -> DomainDataArray < ' vir > {
32- match self . specifics {
33- PredicateEncData :: Array ( prim ) => prim ,
37+ pub fn expect_array ( & self ) -> & PredicateEncDataArray < ' vir > {
38+ match & self . specifics {
39+ PredicateEncData :: Array ( data ) => data ,
3440 s => panic ! ( "expected array predicate data (got {s:?})" ) ,
3541 }
3642 }
3743}
3844
3945pub ( crate ) fn domain < ' vir > (
4046 task_key : <DomainEnc as TaskEncoder >:: TaskKey < ' vir > ,
41- output_ref : & DomainEncOutputRef < ' vir > ,
47+ _output_ref : & DomainEncOutputRef < ' vir > ,
4248 deps : & mut TaskEncoderDependencies < ' vir , DomainEnc > ,
4349 builder : & mut DomainBuilder < ' vir > ,
4450) -> Result < DomainEncSpecifics < ' vir > , EncodeFullError < ' vir , DomainEnc > > {
@@ -68,7 +74,7 @@ pub(crate) fn domain<'vir>(
6874pub ( crate ) fn predicate < ' vir > (
6975 _task_key : <PredicateEnc as TaskEncoder >:: TaskKey < ' vir > ,
7076 snap : SnapshotEncOutput < ' vir > ,
71- _deps : & mut TaskEncoderDependencies < ' vir , PredicateEnc > ,
77+ deps : & mut TaskEncoderDependencies < ' vir , PredicateEnc > ,
7278 generic_decls : & [ vir:: LocalDecl < ' vir > ] ,
7379 generic_exprs : & [ vir:: Expr < ' vir > ] ,
7480 builder : & mut PredicateBuilder < ' vir > ,
@@ -83,45 +89,131 @@ pub(crate) fn predicate<'vir>(
8389 // let ty_kind = ty.kind();
8490
8591 let snap_type = snap. snapshot ;
92+ let snap_data = snap. specifics . expect_array ( ) ;
8693
8794 let ref_self = builder. vcx . mk_local ( "self" , & vir:: TypeData :: Ref ) ;
8895 let ref_self_decl = builder. vcx . mk_local_decl_local ( ref_self) ;
8996
90- // fields
91- // let prim_field = builder.field("val", snap_type);
92-
9397 // main predicate
9498 let self_pred = builder. predicate (
9599 "" ,
96100 & [ ref_self_decl]
97101 . into_iter ( )
98102 . chain ( generic_decls. iter ( ) . cloned ( ) )
99103 . collect :: < Vec < _ > > ( ) ,
100- None , // Some(vir::expr! { acc_field([prim_field](ref_self)) }),
104+ None ,
101105 ) ;
102106
103107 // Ref-to-snap
104- builder. function_snap = Some (
105- builder
106- . mk_function (
107- "snap" ,
108- & [ ref_self_decl]
109- . into_iter ( )
110- . chain ( generic_decls. iter ( ) . cloned ( ) )
111- . collect :: < Vec < _ > > ( ) ,
112- snap_type,
113- & [ vir:: expr! { acc_wildcard( [ self_pred] ( ref_self, ..[ generic_exprs] ) ) } ] ,
114- & [ ] ,
115- None ,
116- // Some(vir::expr! {
117- // unfolding_wildcard ([self_pred](ref_self)) in ([prim_field](ref_self))
118- // }),
119- )
120- . 1 ,
108+ let ( snap_ident, snap_func) = builder. mk_function (
109+ "snap" ,
110+ & [ ref_self_decl]
111+ . into_iter ( )
112+ . chain ( generic_decls. iter ( ) . cloned ( ) )
113+ . collect :: < Vec < _ > > ( ) ,
114+ snap_type,
115+ & [ vir:: expr! { acc_wildcard( [ self_pred] ( ref_self, ..[ generic_exprs] ) ) } ] ,
116+ & [ ] ,
117+ None ,
118+ ) ;
119+ builder. function_snap = Some ( snap_func) ;
120+
121+ // "borrowed" predicate, to frame across index accesses
122+ let borrowed_pred = builder. predicate (
123+ "borrowed" ,
124+ & [ ref_self_decl]
125+ . into_iter ( )
126+ . chain ( generic_decls. iter ( ) . cloned ( ) )
127+ . collect :: < Vec < _ > > ( ) ,
128+ None ,
129+ ) ;
130+ let borrowed_snap = builder. function (
131+ "borrowed_snap" ,
132+ & [ ref_self_decl]
133+ . into_iter ( )
134+ . chain ( generic_decls. iter ( ) . cloned ( ) )
135+ . collect :: < Vec < _ > > ( ) ,
136+ snap_type,
137+ & [ vir:: expr! { acc_wildcard( [ borrowed_pred] ( ref_self, ..[ generic_exprs] ) ) } ] ,
138+ & [ ] ,
139+ None ,
140+ ) ;
141+
142+ let index_access = builder. function (
143+ "index" ,
144+ & [ ref_self_decl] . into_iter ( )
145+ . chain ( generic_decls. iter ( ) . cloned ( ) )
146+ . collect :: < Vec < _ > > ( ) ,
147+ & vir:: TypeData :: Ref ,
148+ & [ ] , // TODO: should have a read permission here!
149+ & [ ] ,
150+ None ,
151+ ) ;
152+
153+ // unfold/fold index
154+ let self_snap = vir:: expr! { [ snap_ident] ( ref_self, ..[ generic_exprs] ) } ;
155+ let self_val = vir:: expr! { [ snap_data. snap_to_prim] ( self_snap) } ;
156+ let index = builder. vcx . mk_local ( "index" , & vir:: TypeData :: Int ) ;
157+ let index_decl = builder. vcx . mk_local_decl_local ( index) ;
158+ let generic_enc = deps. require_ref :: < GenericEnc > ( ( ) ) ?;
159+ let index_val = builder. vcx . mk_bin_op_expr ( vir:: BinOpKind :: SeqIndex , self_val, vir:: expr! { index } ) ;
160+
161+ let unfold_index = builder. method (
162+ "unfold_index" ,
163+ & [ index_decl, ref_self_decl]
164+ . into_iter ( )
165+ . chain ( generic_decls. iter ( ) . cloned ( ) )
166+ . collect :: < Vec < _ > > ( ) ,
167+ & [ ] ,
168+ & [
169+ vir:: expr! { acc( [ self_pred] ( ref_self, ..[ generic_exprs] ) ) } ,
170+ vir:: expr! { ( ( 0 ) <= ( index) ) && ( ( index) < ( vpr_seq_len( self_val) ) ) } ,
171+ ] ,
172+ & [
173+ vir:: expr! { acc( [ borrowed_pred] ( ref_self, ..[ generic_exprs] ) ) } ,
174+ vir:: expr! { acc( [ generic_enc. ref_to_pred] ( [ index_access] ( ref_self, ..[ generic_exprs] ) , ..[ generic_exprs] ) ) } ,
175+ vir:: expr! { ( [ borrowed_snap] ( ref_self, ..[ generic_exprs] ) ) == ( old( self_snap) ) } ,
176+ vir:: expr! { ( [ generic_enc. ref_to_snap] ( [ index_access] ( ref_self, ..[ generic_exprs] ) , ..[ generic_exprs] ) ) == ( old( index_val) ) } ,
177+ ] ,
178+ ) ;
179+
180+ let fold_index = builder. method (
181+ "fold_index" ,
182+ & [ index_decl, ref_self_decl]
183+ . into_iter ( )
184+ . chain ( generic_decls. iter ( ) . cloned ( ) )
185+ . collect :: < Vec < _ > > ( ) ,
186+ & [ ] ,
187+ & [
188+ vir:: expr! { acc( [ borrowed_pred] ( ref_self, ..[ generic_exprs] ) ) } ,
189+ vir:: expr! { acc( [ generic_enc. ref_to_pred] ( [ index_access] ( ref_self, ..[ generic_exprs] ) , ..[ generic_exprs] ) ) } ,
190+ vir:: expr! { ( ( 0 ) <= ( index) ) && ( ( index) < ( vpr_seq_len( [ snap_data. snap_to_prim] ( [ borrowed_snap] ( ref_self, ..[ generic_exprs] ) ) ) ) ) } ,
191+ ] ,
192+ & [
193+ vir:: expr! { acc( [ self_pred] ( ref_self, ..[ generic_exprs] ) ) } ,
194+ vir:: expr! { ( vpr_seq_len( self_val) ) == ( old( vpr_seq_len( [ snap_data. snap_to_prim] ( [ borrowed_snap] ( ref_self, ..[ generic_exprs] ) ) ) ) ) } ,
195+ vir:: expr! {
196+ forall i: [ & vir:: TypeData :: Int ] :: { [ builder. vcx. mk_bin_op_expr( vir:: BinOpKind :: SeqIndex , self_val, vir:: expr! { i } ) ] } ( ( ( 0 ) <= ( i) ) && ( ( i) < ( vpr_seq_len( self_val) ) ) )
197+ ==> ( ( [ builder. vcx. mk_bin_op_expr( vir:: BinOpKind :: SeqIndex , self_val, vir:: expr! { i } ) ] ) == ( [ builder. vcx. mk_ternary_expr(
198+ vir:: expr! { ( i) == ( index) } ,
199+ vir:: expr! { old( [ generic_enc. ref_to_snap] ( [ index_access] ( ref_self, ..[ generic_exprs] ) , ..[ generic_exprs] ) ) } ,
200+ vir:: expr! { old( [ builder. vcx. mk_bin_op_expr(
201+ vir:: BinOpKind :: SeqIndex ,
202+ vir:: expr! { [ snap_data. snap_to_prim] ( [ borrowed_snap] ( ref_self, ..[ generic_exprs] ) ) } ,
203+ vir:: expr! { i } ,
204+ ) ] ) } ,
205+ ) ] ) )
206+ } ,
207+ ] ,
121208 ) ;
122209
123210 Ok ( (
124- PredicateEncData :: Array ( snap. specifics . expect_array ( ) ) ,
211+ PredicateEncData :: Array ( PredicateEncDataArray {
212+ snap_data : snap. specifics . expect_array ( ) ,
213+ index_access,
214+ unfold_index,
215+ fold_index,
216+ } ) ,
125217 None ,
126218 ) )
127219}
0 commit comments