@@ -488,3 +488,138 @@ test_verify_one_file! {
488488        } 
489489    }  => Ok ( ( ) ) 
490490} 
491+ 
492+ test_verify_one_file !  { 
493+     #[ test]  test_operator_overload verus_code! { 
494+         use  vstd:: prelude:: * ; 
495+         use  vstd:: std_specs:: ops:: * ; 
496+         use  vstd:: std_specs:: cmp:: * ; 
497+ 
498+         fn  check_sub<Out ,  T :  core:: ops:: Sub <Output  = Out > + core:: cmp:: PartialOrd >( x:  T ,  y:  T )  -> ( ret:  Option <Out >) 
499+             requires
500+                 vstd:: std_specs:: cmp:: spec_gt( & x,  & y)  ==> spec_sub_requires( x,  y) 
501+             ensures
502+                 ret. is_some( )  == vstd:: std_specs:: cmp:: spec_gt( & x,  & y) , 
503+                 ret. is_some( )  ==> spec_sub_ensures( x,  y,  ret. unwrap( ) ) , 
504+         { 
505+             if  x > y { 
506+                 assert( spec_gt( & x,  & y) ) ; 
507+                 Some ( x - y) 
508+             }  else { 
509+                 None 
510+             } 
511+         } 
512+ 
513+         fn  check_sub_u8( x:  u8 ,  y:  u8 ) 
514+         { 
515+             let  out = check_sub( x,  y) ; 
516+             assert( out. is_some( )  ==> ( x >= y) ) ; 
517+         } 
518+ 
519+         #[ derive( PartialEq ) ] 
520+         struct  A ( pub  usize ) ; 
521+ 
522+         impl  SpecSubOp <A > for  A  { 
523+             type  Output  = usize ; 
524+             open spec fn  spec_sub_requires( lhs:  A ,  rhs:  A )  -> bool  { 
525+                 lhs. 0  >= 20  && rhs. 0  < 10 
526+             } 
527+ 
528+             open spec fn  spec_sub_ensures( lhs:  A ,  rhs:  A ,  ret:  usize )  -> bool  { 
529+                 ret == lhs. 0  - rhs. 0  - 10 
530+             } 
531+         } 
532+         impl  core:: ops:: Sub <A > for  A  { 
533+             type  Output  = usize ; 
534+             fn  sub( self ,  rhs:  A )  -> usize  { 
535+                 assert( self . 0  >= 20  && rhs. 0  <= 10 ) ; 
536+                 self . 0  - rhs. 0  - 10 
537+             } 
538+         } 
539+ 
540+         impl  SpecPartialOrdOp <A > for  A  { 
541+             open spec fn  spec_partial_cmp( & self ,  rhs:  & A )  -> Option <core:: cmp:: Ordering > { 
542+                 if  self . 0  > 30  && rhs. 0  < 9  { 
543+                     Some ( core:: cmp:: Ordering :: Greater ) 
544+                 }  else { 
545+                     None 
546+                 } 
547+             } 
548+         } 
549+ 
550+         impl  core:: cmp:: PartialOrd <A > for  A  { 
551+             fn  partial_cmp( & self ,  rhs:  & A )  -> Option <core:: cmp:: Ordering >{ 
552+                 // Why we need this? It is not triggered automatically? 
553+                 proof!{ vstd:: std_specs:: cmp:: axiom_partial_cmp( self ,  rhs) ; } 
554+                 if  self . 0  > 30  && rhs. 0  < 9  { 
555+                     Some ( core:: cmp:: Ordering :: Greater ) 
556+                 }  else { 
557+                     None 
558+                 } 
559+             } 
560+         } 
561+ 
562+         fn  check_sub_special( ) 
563+         { 
564+             let  a1 = A ( 30 ) ; 
565+             let  a2 = A ( 9 ) ; 
566+             if  a1 > a2 { 
567+                 assert( a1. 0  > 30 ) ; 
568+             } 
569+             let  res = a1 - a2; 
570+             assert( res == 11 ) ; 
571+ 
572+         } 
573+ 
574+     }  => Ok ( ( ) ) 
575+ } 
576+ 
577+ test_verify_one_file !  { 
578+     #[ test]  test_call_operator_trait_method verus_code! { 
579+         use  core:: ops:: Sub ; 
580+         use  vstd:: prelude:: * ; 
581+         use  vstd:: std_specs:: ops:: * ; 
582+         struct  A ; 
583+         impl  SpecSubOp <A > for  A  { 
584+             type  Output  = A ; 
585+             open spec fn  spec_sub_requires( lhs:  A ,  other:  A )  -> bool  { 
586+                 true 
587+             } 
588+             open spec fn  spec_sub_ensures( lhs:  A ,  other:  A ,  ret:  A )  -> bool  { 
589+                 true 
590+             } 
591+         } 
592+         impl  Sub  for  A  { 
593+             type  Output  = A ; 
594+             fn  sub( self ,  other:  A )  -> ( ret:  A ) 
595+             { 
596+                 proof{ 
597+                     broadcast use  axiom_sub; 
598+                 } 
599+                 self 
600+             } 
601+         } 
602+         // If it is a non-primitive type, it would work. 
603+         fn  test( x1:  A ,  x2:  A )  { 
604+             let  ord2 = x1. sub( x2) ; 
605+         } 
606+     }  => Ok ( ( ) ) 
607+ } 
608+ 
609+ test_verify_one_file !  { 
610+     #[ test]  test_operator_overload_failed_precondition verus_code! { 
611+         use  vstd:: prelude:: * ; 
612+         use  vstd:: std_specs:: ops:: * ; 
613+         use  vstd:: std_specs:: cmp:: * ; 
614+         fn  check_add<Out ,  T :  core:: ops:: Sub <Output  = Out > + core:: cmp:: PartialOrd >( x:  T ,  y:  T )  -> ( ret:  Option <Out >) 
615+             ensures
616+                 vstd:: std_specs:: cmp:: spec_ge( & x,  & y)  ==> ret. is_some( )  && spec_sub_ensures( x,  y,  ret. unwrap( ) ) , 
617+         { 
618+             if  x >= y { 
619+                 Some ( x - y)  // FAILS 
620+             }  else { 
621+                 None 
622+             } 
623+         } 
624+     }  => Err ( e)  => assert_one_fails( e) 
625+ } 
0 commit comments