4
4
//
5
5
// Based on https://github.com/voultapher/tiny-sort-rs.
6
6
7
+ #![ feature( ub_checks) ]
7
8
use 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:: * ;
8
15
use std:: ptr;
9
16
17
+ use safety:: requires;
18
+
10
19
/// Sort `v` preserving initial order of equal elements.
11
20
///
12
21
/// - 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) {
48
57
///
49
58
/// SAFETY: The caller has to ensure that len is > 0 and that T is not a ZST.
50
59
#[ inline( never) ]
60
+ #[ requires( len > 0 && size_of:: <T >( ) > 0 ) ]
51
61
unsafe fn mergesort_main < T , F : FnMut ( & T , & T ) -> bool > ( v : & mut [ T ] , is_less : & mut F ) {
52
62
// While it would be nice to have a merge implementation that only requires N / 2 auxiliary
53
63
// 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
66
76
///
67
77
/// Buffer as pointed to by `scratch` must have space for `v.len()` writes. And must not alias `v`.
68
78
#[ inline( always) ]
79
+ #[ requires( can_dereference( scratch_ptr) && !same_allocation( scratch_ptr, v. as_ptr( ) ) ) ]
69
80
unsafe fn mergesort_core < T , F : FnMut ( & T , & T ) -> bool > (
70
81
v : & mut [ T ] ,
71
82
scratch_ptr : * mut T ,
@@ -97,6 +108,7 @@ unsafe fn mergesort_core<T, F: FnMut(&T, &T) -> bool>(
97
108
/// SAFETY: The caller must ensure that `scratch_ptr` is valid for `v.len()` writes. And that mid is
98
109
/// in-bounds.
99
110
#[ inline( always) ]
111
+ #[ requires( mid <= len && can_dereference( scratch_ptr) && !same_allocation( scratch_ptr, v. as_ptr( ) ) ) ]
100
112
unsafe fn merge < T , F > ( v : & mut [ T ] , scratch_ptr : * mut T , is_less : & mut F , mid : usize )
101
113
where
102
114
F : FnMut ( & T , & T ) -> bool ,
@@ -143,6 +155,7 @@ where
143
155
}
144
156
145
157
// SAFETY: The caller has to ensure that Option is Some, UB otherwise.
158
+ #[ requires( opt_val. is_some( ) ) ]
146
159
unsafe fn unwrap_unchecked < T > ( opt_val : Option < T > ) -> T {
147
160
match opt_val {
148
161
Some ( val) => val,
@@ -165,6 +178,7 @@ struct BufGuard<T> {
165
178
166
179
impl < T > BufGuard < T > {
167
180
// 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 ) ]
168
182
unsafe fn new ( len : usize ) -> Self {
169
183
debug_assert ! ( len > 0 && size_of:: <T >( ) > 0 ) ;
170
184
0 commit comments