@@ -103,7 +103,7 @@ impl<T> PCM for FractionalCarrier<T> {
103103///
104104/// let tracked mut a = FracGhost::<u32>::new(5);
105105/// assert(a@ == 5);
106- /// assert(a.frac() == 2 );
106+ /// assert(a.frac() == 1real );
107107/// let tracked mut b = a.split();
108108/// assert(a.frac() == (0.5 as real));
109109/// assert(b.frac() == (0.5 as real));
@@ -305,121 +305,6 @@ impl<T> FracGhost<T> {
305305 }
306306}
307307
308- /// See [`GhostVarAuth<T>`] for more information.
309- pub struct GhostVar <T > {
310- frac: FracGhost <T >,
311- }
312-
313- impl <T > GhostVar <T > {
314- #[ verifier:: type_invariant]
315- spec fn inv( self ) -> bool {
316- self . frac. frac( ) == 1 as real
317- }
318-
319- pub closed spec fn id( self ) -> Loc {
320- self . frac. id( )
321- }
322-
323- pub closed spec fn view( self ) -> T {
324- self . frac. view( )
325- }
326- }
327-
328- /** `GhostVarAuth<T>` is one half of a pair of tokens—the other being [`GhostVar<T>`].
329- These tokens each track a value, and they can only be allocated or updated together.
330- Thus, the pair of tokens always agree on the value, but they can be owned separately.
331-
332- One possible application is to have a library which
333- keeps `GhostVarAuth<T>` and maintains an invariant relating the implementation's
334- abstract state to the value of `GhostVarAuth<T>`. Both `GhostVarAuth<T>`
335- and [`GhostVar<T>`] are needed together to update the value, but either one alone
336- allows reasoning about the current state.
337-
338- These tokens can be implemented using fractional permissions, e.g., [`FracGhost`].
339-
340- ### Example
341-
342- ```
343- fn example() {
344- let tracked (mut gauth, mut gvar) = GhostVarAuth::<u64>::new(1);
345- assert(gauth@ == 1);
346- assert(gvar@ == 1);
347- proof {
348- gauth.update(&mut gvar, 2);
349- }
350- assert(gauth@ == 2);
351- assert(gvar@ == 2);
352- }
353- ```
354- */
355-
356- pub struct GhostVarAuth <T > {
357- frac: FracGhost <T >,
358- }
359-
360- impl <T > GhostVarAuth <T > {
361- #[ verifier:: type_invariant]
362- spec fn inv( self ) -> bool {
363- self . frac. frac( ) == 1 as real
364- }
365-
366- pub closed spec fn id( self ) -> Loc {
367- self . frac. id( )
368- }
369-
370- pub closed spec fn view( self ) -> T {
371- self . frac. view( )
372- }
373-
374- /// Allocate a new pair of tokens, each initialized to the given value.
375- pub proof fn new( v: T ) -> ( tracked result: ( GhostVarAuth <T >, GhostVar <T >) )
376- ensures
377- result. 0 . id( ) == result. 1 . id( ) ,
378- result. 0 @ == v,
379- result. 1 @ == v,
380- {
381- let tracked mut f = FracGhost :: <T >:: new( v) ;
382- let tracked v = GhostVar :: <T > { frac: f. split( ) } ;
383- let tracked a = GhostVarAuth :: <T > { frac: f } ;
384- ( a, v)
385- }
386-
387- /// Ensure that both tokens agree on the value.
388- pub proof fn agree( tracked & self , tracked v: & GhostVar <T >)
389- requires
390- self . id( ) == v. id( ) ,
391- ensures
392- self @ == v@,
393- {
394- self . frac. agree( & v. frac)
395- }
396-
397- /// Update the value on each token.
398- pub proof fn update( tracked & mut self , tracked v: & mut GhostVar <T >, new_val: T )
399- requires
400- old( self ) . id( ) == old( v) . id( ) ,
401- ensures
402- self . id( ) == old( self ) . id( ) ,
403- v. id( ) == old( v) . id( ) ,
404- old( self ) @ == old( v) @,
405- self @ == new_val,
406- v@ == new_val,
407- {
408- let tracked ( mut ms, mut mv) = Self :: new( new_val) ;
409- tracked_swap( self , & mut ms) ;
410- tracked_swap( v, & mut mv) ;
411- use_type_invariant( & ms) ;
412- use_type_invariant( & mv) ;
413- let tracked mut msfrac = ms. frac;
414- msfrac. combine( mv. frac) ;
415- msfrac. update( new_val) ;
416- let tracked mut nv = GhostVar :: <T > { frac: msfrac. split( ) } ;
417- let tracked mut ns = Self { frac: msfrac } ;
418- tracked_swap( self , & mut ns) ;
419- tracked_swap( v, & mut nv) ;
420- }
421- }
422-
423308/////// Fractional tokens that allow borrowing of resources
424309enum FractionalCarrierOpt <T > {
425310 Value { v: Option <T >, frac: real } ,
0 commit comments