@@ -356,75 +356,71 @@ mod flux_specs {
356356 }
357357
358358 // ======= RingBuffer spec ===========
359- use crate :: collections;
360- #[ flux:: specs {
361- mod collections {
362- mod ring_buffer {
363- // Specify well-formedness for RingBuffer<T>.
364- // Flux will raise an error if 1) any RingBuffer implementation violates these rules,
365- // Or 2) Any Tock code attempts to create a RingBuffer that violates these rules.
366- // At the bottom of this spec, we have included some example
367- // test code that raises Flux errors for both of these cases.
368- #[ refined_by( ring_len: int, hd: int, tl: int) ]
369- struct RingBuffer <T > {
370- ring: { & mut [ T ] [ ring_len] | ring_len > 1 } ,
371- head: { usize [ hd] | hd < ring_len} ,
372- tail: { usize [ tl] | tl < ring_len} ,
373- }
359+ use crate :: collections:: list:: ListIterator ;
360+ use crate :: collections:: queue:: Queue ;
361+ use crate :: collections:: ring_buffer:: RingBuffer ;
362+ use core:: iter:: Iterator ;
374363
375- impl RingBuffer <T > {
376- // Example of a function-level spec.
377- // It has a precondition that the input slice is length > 1, so
378- // every time RingBuffer::new() is called (throughout Tock),
379- // Flux will ensure the slice passed in has length > 1.
380- //
381- // It also has a postcondition that the output RingBuffer has a head and tail of zero.
382- // Flux will check the implementation of `new` to ensure this is true.
383- //
384- // Design note: This contract has the strongest possible postcondition (head == 0 and tail == 0),
385- // but we could also make the postcondition something "weaker" like `result.head == result.tail`.
386- // Weaker vs stronger contracts is a design decision: it is easier to prove that a weak contract
387- // holds in the implementation, but it lets you prove less in the rest of Tock (e.g., if there was code
388- // that was only safe if head/tail was 0 after it called new, we could prove its safety only with the stronger contract).
389- fn new( { & mut [ T ] [ @ring_len] | ring_len > 1 } ) -> RingBuffer <T >[ ring_len, 0 , 0 ] ;
390- }
391- }
364+ #[ flux:: specs {
365+ // Specify well-formedness for RingBuffer<T>.
366+ // Flux will raise an error if 1) any RingBuffer implementation violates these rules,
367+ // Or 2) Any Tock code attempts to create a RingBuffer that violates these rules.
368+ // At the bottom of this spec, we have included some example
369+ // test code that raises Flux errors for both of these cases.
370+ #[ refined_by( ring_len: int, hd: int, tl: int) ]
371+ struct RingBuffer <T > {
372+ ring: { & mut [ T ] [ ring_len] | ring_len > 1 } ,
373+ head: { usize [ hd] | hd < ring_len} ,
374+ tail: { usize [ tl] | tl < ring_len} ,
375+ }
392376
393- mod queue {
394- impl Queue <T > for collections:: ring_buffer:: RingBuffer <T > {
395- // Simple function-level contract.
396- // See `new` example above for a discussion of contract design.
397- fn empty( self : & mut RingBuffer <T >[ @old] )
398- ensures self : RingBuffer <T >[ old. ring_len, 0 , 0 ] ;
399-
400- // These specs of the form: `(self: RingBuffer) ensures RingBuffer`
401- // are present to compensate for a current technical limitation of Flux,
402- // and should be gone in the near future.
403- fn enqueue( self : & mut RingBuffer <T >, val: T ) -> bool
404- ensures self : RingBuffer <T >;
405-
406- fn push( self : & mut RingBuffer <T >, val: T ) -> Option <T >
407- ensures self : RingBuffer <T >;
408-
409- fn dequeue( self : & mut RingBuffer <T >) -> Option <T >
410- ensures self : RingBuffer <T >;
411-
412- fn remove_first_matching<F >( self : & mut RingBuffer <T >, _) -> Option <T >
413- ensures self : RingBuffer <T >;
414-
415- fn retain<F >( self : & mut RingBuffer <T >, _)
416- ensures self : RingBuffer <T >;
417- }
418-
419- }
377+ impl RingBuffer <T > {
378+ // Example of a function-level spec.
379+ // It has a precondition that the input slice is length > 1, so
380+ // every time RingBuffer::new() is called (throughout Tock),
381+ // Flux will ensure the slice passed in has length > 1.
382+ //
383+ // It also has a postcondition that the output RingBuffer has a head and tail of zero.
384+ // Flux will check the implementation of `new` to ensure this is true.
385+ //
386+ // Design note: This contract has the strongest possible postcondition (head == 0 and tail == 0),
387+ // but we could also make the postcondition something "weaker" like `result.head == result.tail`.
388+ // Weaker vs stronger contracts is a design decision: it is easier to prove that a weak contract
389+ // holds in the implementation, but it lets you prove less in the rest of Tock (e.g., if there was code
390+ // that was only safe if head/tail was 0 after it called new, we could prove its safety only with the stronger contract).
391+ fn new( { & mut [ T ] [ @ring_len] | ring_len > 1 } ) -> RingBuffer <T >[ ring_len, 0 , 0 ] ;
392+ }
393+
394+ impl Queue <T > for RingBuffer <T > {
395+ // Simple function-level contract.
396+ // See `new` example above for a discussion of contract design.
397+ fn empty( self : & mut RingBuffer <T >[ @old] )
398+ ensures self : RingBuffer <T >[ old. ring_len, 0 , 0 ] ;
399+
400+ // These specs of the form: `(self: RingBuffer) ensures RingBuffer`
401+ // are present to compensate for a current technical limitation of Flux,
402+ // and should be gone in the near future.
403+ fn enqueue( self : & mut RingBuffer <T >, val: T ) -> bool
404+ ensures self : RingBuffer <T >;
405+
406+ fn push( self : & mut RingBuffer <T >, val: T ) -> Option <T >
407+ ensures self : RingBuffer <T >;
408+
409+ fn dequeue( self : & mut RingBuffer <T >) -> Option <T >
410+ ensures self : RingBuffer <T >;
411+
412+ fn remove_first_matching<F >( self : & mut RingBuffer <T >, _) -> Option <T >
413+ ensures self : RingBuffer <T >;
414+
415+ fn retain<F >( self : & mut RingBuffer <T >, _)
416+ ensures self : RingBuffer <T >;
417+ }
420418
421- mod list {
422- impl Iterator for collections:: list:: ListIterator <T > {
423- fn next( self : & mut ListIterator <T >) -> Option <& T >
424- ensures self : ListIterator <T >;
425- }
426- }
419+ impl Iterator for ListIterator <T > {
420+ fn next( self : & mut ListIterator <T >) -> Option <& T >
421+ ensures self : ListIterator <T >;
427422 }
423+
428424 } ]
429425 const _: ( ) = ( ) ;
430426
@@ -434,9 +430,6 @@ mod flux_specs {
434430 // 1. Bad usage of the RingBuffer API that leads to kernel panics
435431 // 2. Bad implementation of the RingBuffer API that leads to kernel panics
436432
437- use crate :: collections:: queue:: Queue ;
438- use crate :: collections:: ring_buffer:: RingBuffer ;
439-
440433 // 1. Flux will prevent Tock from using the RingBuffer API incorrectly, leading to panics
441434 #[ allow( dead_code) ]
442435 #[ flux_rs:: should_fail]
0 commit comments