44//
55// Based on https://github.com/voultapher/tiny-sort-rs.
66
7+ #![ feature( ub_checks) ]
78use alloc:: alloc:: { Layout , alloc, dealloc} ;
9+ #[ cfg( kani) ]
10+ #[ unstable( feature = "kani" , issue = "none" ) ]
11+ use core:: kani;
12+ #[ allow( unused_imports) ]
13+ #[ unstable( feature = "ub_checks" , issue = "none" ) ]
14+ use core:: ub_checks:: * ;
815use std:: ptr;
916
17+ use safety:: requires;
18+
1019/// Sort `v` preserving initial order of equal elements.
1120///
1221/// - Guaranteed O(N * log(N)) worst case perf
@@ -48,6 +57,7 @@ fn stable_sort<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], mut is_less: F) {
4857///
4958/// SAFETY: The caller has to ensure that len is > 0 and that T is not a ZST.
5059#[ inline( never) ]
60+ #[ requires( len > 0 && size_of:: <T >( ) > 0 ) ]
5161unsafe fn mergesort_main < T , F : FnMut ( & T , & T ) -> bool > ( v : & mut [ T ] , is_less : & mut F ) {
5262 // While it would be nice to have a merge implementation that only requires N / 2 auxiliary
5363 // memory. Doing so would make the merge implementation significantly more complex and
@@ -66,6 +76,7 @@ unsafe fn mergesort_main<T, F: FnMut(&T, &T) -> bool>(v: &mut [T], is_less: &mut
6676///
6777/// Buffer as pointed to by `scratch` must have space for `v.len()` writes. And must not alias `v`.
6878#[ inline( always) ]
79+ #[ requires( can_dereference( scratch_ptr) && !same_allocation( scratch_ptr, v. as_ptr( ) ) ) ]
6980unsafe fn mergesort_core < T , F : FnMut ( & T , & T ) -> bool > (
7081 v : & mut [ T ] ,
7182 scratch_ptr : * mut T ,
@@ -97,6 +108,7 @@ unsafe fn mergesort_core<T, F: FnMut(&T, &T) -> bool>(
97108/// SAFETY: The caller must ensure that `scratch_ptr` is valid for `v.len()` writes. And that mid is
98109/// in-bounds.
99110#[ inline( always) ]
111+ #[ requires( mid <= len && can_dereference( scratch_ptr) && !same_allocation( scratch_ptr, v. as_ptr( ) ) ) ]
100112unsafe fn merge < T , F > ( v : & mut [ T ] , scratch_ptr : * mut T , is_less : & mut F , mid : usize )
101113where
102114 F : FnMut ( & T , & T ) -> bool ,
@@ -143,6 +155,7 @@ where
143155}
144156
145157// SAFETY: The caller has to ensure that Option is Some, UB otherwise.
158+ #[ requires( opt_val. is_some( ) ) ]
146159unsafe fn unwrap_unchecked < T > ( opt_val : Option < T > ) -> T {
147160 match opt_val {
148161 Some ( val) => val,
@@ -165,6 +178,7 @@ struct BufGuard<T> {
165178
166179impl < T > BufGuard < T > {
167180 // SAFETY: The caller has to ensure that len is not 0 and that T is not a ZST.
181+ #[ requires( len > 0 && size_of:: <T >( ) > 0 ) ]
168182 unsafe fn new ( len : usize ) -> Self {
169183 debug_assert ! ( len > 0 && size_of:: <T >( ) > 0 ) ;
170184
0 commit comments