vstd_extra/external/
nonnull.rs1use super::nonzero::NonZeroUsize;
2use core::marker::PointeeSized;
3use core::ptr::NonNull;
4use vstd::prelude::*;
5use vstd::raw_ptr::*;
6use vstd::std_specs::cmp::*;
7
8verus! {
9
10#[verifier::external_type_specification]
11#[verifier::reject_recursive_types(T)]
12#[verifier::external_body]
13pub struct ExNonNull<T: PointeeSized>(NonNull<T>);
14
15pub trait NonNullAdditionalFns<T: PointeeSized> {
16 spec fn view_ptr_mut(self) -> *mut T;
19
20 spec fn cast_spec<U>(self) -> NonNull<U>;
22
23 spec fn dangling_spec() -> NonNull<T>;
25
26 broadcast proof fn lemma_addr_is_nonnull(self)
28 ensures
29 !(#[trigger] self.view_ptr_mut()).is_null(),
30 ;
31
32 spec fn addr_spec(self) -> NonZeroUsize;
33
34 broadcast proof fn lemma_addr_view_eq_view_ptr_mut(self)
35 ensures
36 (#[trigger] self.addr_spec()).view() == self.view_ptr_mut().addr(),
37 ;
38
39 fn addr_v(self) -> NonZeroUsize
41 returns
42 self.addr_spec(),
43 ;
44}
45
46impl<T: PointeeSized> NonNullAdditionalFns<T> for NonNull<T> {
47 uninterp spec fn view_ptr_mut(self) -> *mut T;
48
49 uninterp spec fn cast_spec<U>(self) -> NonNull<U>;
50
51 uninterp spec fn dangling_spec() -> NonNull<T>;
52
53 axiom fn lemma_addr_is_nonnull(self);
54
55 open spec fn addr_spec(self) -> NonZeroUsize {
56 NonZeroUsize::nonzero_usize_from_usize(self.view_ptr_mut()@.addr)
57 }
58
59 axiom fn lemma_addr_view_eq_view_ptr_mut(self);
60
61 #[verifier::external_body]
62 #[verifier::when_used_as_spec(nonnull_addr_spec_wrapper)]
63 fn addr_v(self) -> NonZeroUsize {
64 unimplemented!()
65 }
66}
67
68#[verifier::inline]
69pub open spec fn nonnull_addr_spec_wrapper<T: PointeeSized>(ptr: NonNull<T>) -> NonZeroUsize {
70 ptr.addr_spec()
71}
72
73#[verifier::inline]
74pub open spec fn nonnull_view_ptr_mut_wrapper<T: PointeeSized>(ptr: NonNull<T>) -> *mut T {
75 ptr.view_ptr_mut()
76}
77
78#[verifier::inline]
79pub open spec fn nonnull_cast_spec_wrapper<T: PointeeSized, U>(ptr: NonNull<T>) -> NonNull<U> {
80 ptr.cast_spec::<U>()
81}
82
83pub uninterp spec fn nonnull_from_ptr_mut_spec<T: PointeeSized>(ptr: *mut T) -> NonNull<T>;
85
86#[verifier::inline]
87pub open spec fn nonnull_new_spec<T: PointeeSized>(ptr: *mut T) -> Option<NonNull<T>> {
88 if ptr.is_null() {
89 None
90 } else {
91 Some(nonnull_from_ptr_mut_spec(ptr))
92 }
93}
94
95pub broadcast axiom fn axiom_nonnull_from_ptr_mut_spec_eq<T: PointeeSized>(ptr: *mut T)
97 requires
98 !ptr.is_null(),
99 ensures
100 (#[trigger] nonnull_from_ptr_mut_spec(ptr)).view_ptr_mut() == ptr,
101;
102
103pub broadcast axiom fn axiom_view_ptr_mut_eq<T: PointeeSized>(a: NonNull<T>)
106 ensures
107 nonnull_from_ptr_mut_spec(#[trigger] a.view_ptr_mut()) == a,
108;
109
110pub broadcast axiom fn axiom_cast_spec_eq<T: PointeeSized, U>(ptr: NonNull<T>)
113 ensures
114 (#[trigger] ptr.cast_spec::<U>()).view_ptr_mut() == ptr.view_ptr_mut() as *mut U,
115;
116
117#[verifier::when_used_as_spec(nonnull_from_ptr_mut_spec)]
118pub assume_specification<T: PointeeSized>[ NonNull::new_unchecked ](ptr: *mut T) -> (ret: NonNull<
119 T,
120>)
121 requires
122 !ptr.is_null(),
123 ensures
124 ret.view_ptr_mut() == ptr,
125 returns
126 nonnull_from_ptr_mut_spec(ptr),
127;
128
129#[verifier::when_used_as_spec(nonnull_new_spec)]
130pub assume_specification<T: PointeeSized>[ core::ptr::NonNull::<T>::new ](ptr: *mut T) -> (ret:
131 core::option::Option<core::ptr::NonNull<T>>)
132 ensures
133 ret matches Some(nn) ==> nn.view_ptr_mut() == ptr,
134 returns
135 nonnull_new_spec(ptr),
136;
137
138#[verifier::when_used_as_spec(nonnull_view_ptr_mut_wrapper)]
139pub assume_specification<T: PointeeSized>[ NonNull::as_ptr ](ptr: NonNull<T>) -> (ret: *mut T)
140 ensures
141 !ret.is_null(),
142 ptr.view_ptr_mut() == ret,
143;
144
145#[verifier::when_used_as_spec(nonnull_cast_spec_wrapper)]
146pub assume_specification<T: PointeeSized, U>[ NonNull::<T>::cast::<U> ](ptr: NonNull<T>) -> (ret:
147 NonNull<U>)
148 ensures
149 ret.view_ptr_mut() == ptr.view_ptr_mut() as *mut U,
150 returns
151 ptr.cast_spec::<U>(),
152;
153
154pub uninterp spec fn nonnull_dangling_spec<T>() -> NonNull<T>;
157
158#[verifier::when_used_as_spec(nonnull_dangling_spec)]
159pub assume_specification<T>[ NonNull::dangling ]() -> (ret: NonNull<T>)
160 ensures
161 ret.view_ptr_mut()@.addr as nat % align_of::<T>() as nat == 0,
162 ret.view_ptr_mut()@.provenance == Provenance::null(),
163 returns
164 nonnull_dangling_spec::<T>(),
165;
166
167#[verifier::inline]
168pub open spec fn nonnull_with_addr_spec_wrapper<T: PointeeSized>(
169 ptr: NonNull<T>,
170 addr: NonZeroUsize,
171) -> NonNull<T> {
172 ptr.with_addr_spec(addr)
173}
174
175pub trait NonNullAdditionalFnsMore<T>: NonNullAdditionalFns<T> where T: PointeeSized {
177 spec fn with_addr_spec(self, addr: NonZeroUsize) -> NonNull<T>;
178
179 proof fn lemma_with_addr_properties(self, addr: NonZeroUsize)
180 ensures
181 self.with_addr_spec(addr).view_ptr_mut()@.metadata == self.view_ptr_mut()@.metadata,
182 self.with_addr_spec(addr).view_ptr_mut()@.provenance == self.view_ptr_mut()@.provenance,
183 self.with_addr_spec(addr).view_ptr_mut()@.addr == addr.view(),
184 ;
185
186 fn with_addr_v(self, addr: NonZeroUsize) -> (ret: NonNull<T>)
187 returns
188 self.with_addr_spec(addr),
189 ;
190
191 fn map_addr_v<F: FnOnce(NonZeroUsize) -> NonZeroUsize>(self, f: F) -> (ret: NonNull<T>)
193 requires
194 f.requires((self.addr_spec(),)),
195 ensures
196 ret.view_ptr_mut()@.metadata == self.view_ptr_mut()@.metadata,
197 ret.view_ptr_mut()@.provenance == self.view_ptr_mut()@.provenance,
198 f.ensures((self.addr_spec(),), ret.addr_spec()),
199 ;
200}
201
202impl<T: PointeeSized> NonNullAdditionalFnsMore<T> for NonNull<T> {
203 #[verifier::external_body]
204 fn map_addr_v<F: FnOnce(NonZeroUsize) -> NonZeroUsize>(self, f: F) -> (ret: NonNull<T>) {
205 unimplemented!()
206 }
207
208 uninterp spec fn with_addr_spec(self, addr: NonZeroUsize) -> NonNull<T>;
209
210 axiom fn lemma_with_addr_properties(self, addr: NonZeroUsize);
211
212 #[verifier::external_body]
213 #[verifier::when_used_as_spec(nonnull_with_addr_spec_wrapper)]
214 fn with_addr_v(self, addr: NonZeroUsize) -> (ret: NonNull<T>) {
215 unimplemented!()
216 }
217}
218
219pub broadcast group group_nonull_axioms {
220 axiom_nonnull_from_ptr_mut_spec_eq,
221 axiom_cast_spec_eq,
222 axiom_view_ptr_mut_eq,
223 NonNullAdditionalFns::lemma_addr_view_eq_view_ptr_mut,
224 NonNullAdditionalFns::lemma_addr_is_nonnull,
225}
226
227}