@@ -305,338 +305,4 @@ impl<T> FracGhost<T> {
305305 }
306306}
307307
308- /////// Fractional tokens that allow borrowing of resources
309- enum FractionalCarrierOpt <T > {
310- Value { v: Option <T >, frac: real } ,
311- Empty ,
312- Invalid ,
313- }
314-
315- impl <T > Protocol <( ) , T > for FractionalCarrierOpt <T > {
316- closed spec fn op( self , other: Self ) -> Self {
317- match self {
318- FractionalCarrierOpt :: Invalid => FractionalCarrierOpt :: Invalid ,
319- FractionalCarrierOpt :: Empty => other,
320- FractionalCarrierOpt :: Value { v: sv, frac: s_frac } => match other {
321- FractionalCarrierOpt :: Invalid => FractionalCarrierOpt :: Invalid ,
322- FractionalCarrierOpt :: Empty => self ,
323- FractionalCarrierOpt :: Value { v: ov, frac: o_frac } => {
324- if sv != ov {
325- FractionalCarrierOpt :: Invalid
326- } else if s_frac <= 0 as real || o_frac <= 0 as real || s_frac + o_frac
327- > 1 as real {
328- FractionalCarrierOpt :: Invalid
329- } else {
330- FractionalCarrierOpt :: Value { v: sv, frac: s_frac + o_frac }
331- }
332- } ,
333- } ,
334- }
335- }
336-
337- closed spec fn rel( self , s: Map <( ) , T >) -> bool {
338- match self {
339- FractionalCarrierOpt :: Value { v, frac } => {
340- ( match v {
341- Some ( v0) => s. dom( ) . contains( ( ) ) && s[ ( ) ] == v0,
342- None => s =~= map![ ] ,
343- } ) && frac == 1 as real
344- } ,
345- FractionalCarrierOpt :: Empty => false ,
346- FractionalCarrierOpt :: Invalid => false ,
347- }
348- }
349-
350- closed spec fn unit( ) -> Self {
351- FractionalCarrierOpt :: Empty
352- }
353-
354- proof fn commutative( a: Self , b: Self ) {
355- }
356-
357- proof fn associative( a: Self , b: Self , c: Self ) {
358- }
359-
360- proof fn op_unit( a: Self ) {
361- }
362- }
363-
364- /// Token that maintains fractional access to some resource.
365- /// This allows multiple clients to obtain shared references to some resource
366- /// via `borrow`.
367- pub struct Frac <T > {
368- r: StorageResource <( ) , T , FractionalCarrierOpt <T >>,
369- }
370-
371- /// Token that represents the "empty" state of a fractional resource system.
372- /// See [`Frac`] for more information.
373- pub struct Empty <T > {
374- r: StorageResource <( ) , T , FractionalCarrierOpt <T >>,
375- }
376-
377- impl <T > Frac <T > {
378- #[ verifier:: type_invariant]
379- spec fn inv( self ) -> bool {
380- self . r. value( ) matches FractionalCarrierOpt :: Value { v: Some ( _) , .. }
381- }
382-
383- pub closed spec fn id( self ) -> Loc {
384- self . r. loc( )
385- }
386-
387- pub closed spec fn resource( self ) -> T {
388- self . r. value( ) ->v. unwrap( )
389- }
390-
391- pub closed spec fn frac( self ) -> real {
392- self . r. value( ) ->frac
393- }
394-
395- pub open spec fn valid( self , id: Loc , frac: real) -> bool {
396- &&& self . id( ) == id
397- &&& self . frac( ) == frac
398- }
399-
400- /// Create a fractional token that maintains shared access to the input resource.
401- pub proof fn new( tracked v: T ) -> ( tracked result: Self )
402- ensures
403- result. frac( ) == 1 as real,
404- result. resource( ) == v,
405- {
406- let f = FractionalCarrierOpt :: <T >:: Value { v: Some ( v) , frac: 1 as real } ;
407- let tracked mut m = Map :: <( ) , T >:: tracked_empty( ) ;
408- m. tracked_insert( ( ) , v) ;
409- let tracked r = StorageResource :: alloc( f, m) ;
410- Self { r }
411- }
412-
413- /// Two tokens agree on values of the underlying resource.
414- pub proof fn agree( tracked self : & Self , tracked other: & Self )
415- requires
416- self . id( ) == other. id( ) ,
417- ensures
418- self . resource( ) == other. resource( ) ,
419- {
420- use_type_invariant( self ) ;
421- use_type_invariant( other) ;
422- let tracked joined = self . r. join_shared( & other. r) ;
423- joined. validate( ) ;
424- }
425-
426- // This helper is needed to bypass the type invariant temporarily
427- proof fn split_to_helper(
428- tracked r: & mut StorageResource <( ) , T , FractionalCarrierOpt <T >>,
429- frac: real,
430- ) -> ( tracked result: Self )
431- requires
432- ( 0 as real) < frac < old( r) . value( ) ->frac,
433- old( r) . value( ) matches FractionalCarrierOpt :: Value { v: Some ( _) , .. } ,
434- ensures
435- r. loc( ) == old( r) . loc( ) ,
436- result. id( ) == old( r) . loc( ) ,
437- r. value( ) ->v. unwrap( ) == old( r) . value( ) ->v. unwrap( ) ,
438- result. resource( ) == old( r) . value( ) ->v. unwrap( ) ,
439- r. value( ) ->frac + result. frac( ) == old( r) . value( ) ->frac,
440- result. frac( ) == frac,
441- r. value( ) matches FractionalCarrierOpt :: Value { v: Some ( _) , .. } ,
442- {
443- r. validate( ) ;
444- let tracked mut r1 = StorageResource :: alloc(
445- FractionalCarrierOpt :: Value { v: None , frac: 1 as real } ,
446- Map :: tracked_empty( ) ,
447- ) ;
448- tracked_swap( r, & mut r1) ;
449- let tracked ( r1, r2) = r1. split(
450- FractionalCarrierOpt :: Value { v: r1. value( ) ->v, frac: r1. value( ) ->frac - frac } ,
451- FractionalCarrierOpt :: Value { v: r1. value( ) ->v, frac: frac } ,
452- ) ;
453- * r = r1;
454- Self { r: r2 }
455- }
456-
457- /// Split one resource into two resources whose quantities sum to the original.
458- /// The returned token has quantity `result_frac`; the new value of the input token has
459- /// quantity `old(self).frac() - result_frac`.
460- pub proof fn split_to( tracked & mut self , result_frac: real) -> ( tracked result: Self )
461- requires
462- 0 as real < result_frac < old( self ) . frac( ) ,
463- ensures
464- self . id( ) == old( self ) . id( ) ,
465- result. id( ) == old( self ) . id( ) ,
466- self . resource( ) == old( self ) . resource( ) ,
467- result. resource( ) == old( self ) . resource( ) ,
468- self . frac( ) == old( self ) . frac( ) - result_frac,
469- result. frac( ) == result_frac,
470- {
471- use_type_invariant( & * self ) ;
472- Self :: split_to_helper( & mut self . r, result_frac)
473- }
474-
475- /// Split one resource by half into two resources whose quantities sum to the original.
476- /// The returned token has quantity `n`; the new value of the input token has
477- /// quantity `old(self).frac() - n`.
478- pub proof fn split( tracked & mut self ) -> ( tracked result: Self )
479- ensures
480- self . id( ) == old( self ) . id( ) ,
481- result. id( ) == old( self ) . id( ) ,
482- self . resource( ) == old( self ) . resource( ) ,
483- result. resource( ) == old( self ) . resource( ) ,
484- self . frac( ) == old( self ) . frac( ) / 2 as real,
485- result. frac( ) == old( self ) . frac( ) / 2 as real,
486- {
487- use_type_invariant( & * self ) ;
488- self . r. validate( ) ;
489- self . split_to( self . frac( ) / 2 as real)
490- }
491-
492- /// Combine two tokens, summing their quantities.
493- pub proof fn combine( tracked & mut self , tracked other: Self )
494- requires
495- old( self ) . id( ) == other. id( ) ,
496- ensures
497- self . id( ) == old( self ) . id( ) ,
498- self . resource( ) == old( self ) . resource( ) ,
499- self . resource( ) == other. resource( ) ,
500- self . frac( ) == old( self ) . frac( ) + other. frac( ) ,
501- {
502- use_type_invariant( & * self ) ;
503- Self :: combine_helper( & mut self . r, other) ;
504- }
505-
506- // This helper is needed to temporarily bypass the type invariant
507- proof fn combine_helper(
508- tracked r: & mut StorageResource <( ) , T , FractionalCarrierOpt <T >>,
509- tracked other: Self ,
510- )
511- requires
512- old( r) . loc( ) == other. id( ) ,
513- old( r) . value( ) matches FractionalCarrierOpt :: Value { v: Some ( _) , .. } ,
514- ensures
515- r. loc( ) == old( r) . loc( ) ,
516- r. value( ) ->v. unwrap( ) == old( r) . value( ) ->v. unwrap( ) ,
517- r. value( ) ->v. unwrap( ) == other. resource( ) ,
518- r. value( ) ->frac == old( r) . value( ) ->frac + other. frac( ) ,
519- r. value( ) matches FractionalCarrierOpt :: Value { v: Some ( _) , .. } ,
520- {
521- use_type_invariant( & other) ;
522- r. validate( ) ;
523- let tracked mut r1 = StorageResource :: alloc(
524- FractionalCarrierOpt :: Value { v: None , frac: 1 as real } ,
525- Map :: tracked_empty( ) ,
526- ) ;
527- tracked_swap( r, & mut r1) ;
528- r1. validate_with_shared( & other. r) ;
529- * r = StorageResource :: join( r1, other. r) ;
530- }
531-
532- /// Allowed values for a token's quantity.
533- pub proof fn bounded( tracked & self )
534- ensures
535- 0 as real < self . frac( ) <= 1 as real,
536- {
537- use_type_invariant( self ) ;
538- let ( x, _) = self . r. validate( ) ;
539- }
540-
541- /// Obtain shared access to the underlying resource.
542- pub proof fn borrow( tracked & self ) -> ( tracked ret: & T )
543- ensures
544- ret == self . resource( ) ,
545- {
546- use_type_invariant( self ) ;
547- StorageResource :: guard( & self . r, map![ ( ) => self . resource( ) ] ) . tracked_borrow( ( ) )
548- }
549-
550- /// Reclaim full ownership of the underlying resource.
551- pub proof fn take_resource( tracked self ) -> ( tracked pair: ( T , Empty <T >) )
552- requires
553- self . frac( ) == 1 as real,
554- ensures
555- pair. 0 == self . resource( ) ,
556- pair. 1 . id( ) == self . id( ) ,
557- {
558- use_type_invariant( & self ) ;
559- self . r. validate( ) ;
560-
561- let p1 = self . r. value( ) ;
562- let p2 = FractionalCarrierOpt :: Value { v: None , frac: 1 as real } ;
563- let b2 = map![ ( ) => self . resource( ) ] ;
564- assert forall|q: FractionalCarrierOpt <T >, t1: Map <( ) , T >|
565- #![ all_triggers]
566- FractionalCarrierOpt :: rel( FractionalCarrierOpt :: op( p1, q) , t1) implies exists|
567- t2: Map <( ) , T >,
568- |
569- #![ all_triggers]
570- FractionalCarrierOpt :: rel( FractionalCarrierOpt :: op( p2, q) , t2) && t2. dom( ) . disjoint(
571- b2. dom( ) ,
572- ) && t1 =~= t2. union_prefer_right( b2) by {
573- let t2 = map![ ] ;
574- assert( FractionalCarrierOpt :: rel( FractionalCarrierOpt :: op( p2, q) , t2) ) ;
575- assert( t2. dom( ) . disjoint( b2. dom( ) ) ) ;
576- assert( t1 =~= t2. union_prefer_right( b2) ) ;
577- }
578-
579- let tracked Self { r } = self ;
580- let tracked ( new_r, mut m) = r. withdraw( p2, b2) ;
581- let tracked emp = Empty { r: new_r } ;
582- let tracked resource = m. tracked_remove( ( ) ) ;
583- ( resource, emp)
584- }
585- }
586-
587- impl <T > Empty <T > {
588- #[ verifier:: type_invariant]
589- spec fn inv( self ) -> bool {
590- &&& self . r. value( ) matches FractionalCarrierOpt :: Value { v: None , frac }
591- &&& frac == 1 as real
592- }
593-
594- pub closed spec fn id( self ) -> Loc {
595- self . r. loc( )
596- }
597-
598- pub proof fn new( tracked v: T ) -> ( tracked result: Self ) {
599- let f = FractionalCarrierOpt :: <T >:: Value { v: None , frac: 1 as real } ;
600- let tracked mut m = Map :: <( ) , T >:: tracked_empty( ) ;
601- let tracked r = StorageResource :: alloc( f, m) ;
602- Self { r }
603- }
604-
605- /// Give up ownership of a resource and obtain a [`Frac`] token.
606- pub proof fn put_resource( tracked self , tracked resource: T ) -> ( tracked frac: Frac <T >)
607- ensures
608- frac. id( ) == self . id( ) ,
609- frac. resource( ) == resource,
610- frac. frac( ) == 1 as real,
611- {
612- use_type_invariant( & self ) ;
613- self . r. validate( ) ;
614-
615- let p1 = self . r. value( ) ;
616- let b1 = map![ ( ) => resource] ;
617- let p2 = FractionalCarrierOpt :: Value { v: Some ( resource) , frac: 1 as real } ;
618-
619- assert forall|q: FractionalCarrierOpt <T >, t1: Map <( ) , T >|
620- #![ all_triggers]
621- FractionalCarrierOpt :: rel( FractionalCarrierOpt :: op( p1, q) , t1) implies exists|
622- t2: Map <( ) , T >,
623- |
624- #![ all_triggers]
625- FractionalCarrierOpt :: rel( FractionalCarrierOpt :: op( p2, q) , t2) && t1. dom( ) . disjoint(
626- b1. dom( ) ,
627- ) && t1. union_prefer_right( b1) =~= t2 by {
628- let t2 = map![ ( ) => resource] ;
629- assert( FractionalCarrierOpt :: rel( FractionalCarrierOpt :: op( p2, q) , t2)
630- && t1. dom( ) . disjoint( b1. dom( ) ) && t1. union_prefer_right( b1) =~= t2) ;
631- }
632-
633- let tracked mut m = Map :: tracked_empty( ) ;
634- m. tracked_insert( ( ) , resource) ;
635- let tracked Self { r } = self ;
636- let tracked new_r = r. deposit( m, p2) ;
637- let tracked f = Frac { r: new_r } ;
638- f
639- }
640- }
641-
642308} // verus!
0 commit comments