vstd_extra/external/
smart_ptr.rs1use crate::ownership::*;
2use crate::raw_ptr_extra::*;
3use alloc::sync::Arc;
4use vstd::layout::valid_layout;
5use vstd::prelude::*;
6use vstd::raw_ptr::*;
7
8verus! {
10
11pub tracked struct BoxPointsTo<T> {
14 pub perm: PointsTowithDealloc<T>,
15}
16
17pub tracked struct ArcPointsTo<T: 'static> {
21 pub perm: &'static PointsTo<T>,
22}
23
24pub tracked enum SmartPtrPointsTo<T: 'static> {
25 Box(BoxPointsTo<T>),
26 Arc(ArcPointsTo<T>),
27}
28
29impl<T> BoxPointsTo<T> {
30 pub open spec fn perm(self) -> PointsTowithDealloc<T> {
31 self.perm
32 }
33
34 pub open spec fn ptr(self) -> *mut T {
35 self.perm.ptr()
36 }
37
38 pub open spec fn addr(self) -> usize {
39 self.ptr().addr()
40 }
41
42 pub open spec fn is_uninit(self) -> bool {
43 self.perm.is_uninit()
44 }
45
46 pub open spec fn is_init(self) -> bool {
47 self.perm.is_init()
48 }
49
50 pub open spec fn value(self) -> T {
51 self.perm.value()
52 }
53
54 pub proof fn tracked_get_points_to_with_dealloc(tracked self) -> (tracked ret:
55 PointsTowithDealloc<T>)
56 returns
57 self.perm,
58 {
59 self.perm
60 }
61
62 pub proof fn tracked_borrow_points_to_with_dealloc(tracked &self) -> (tracked ret:
63 &PointsTowithDealloc<T>)
64 returns
65 &self.perm,
66 {
67 &self.perm
68 }
69
70 pub proof fn tracked_get_points_to(tracked self) -> (tracked ret: PointsTo<T>)
71 returns
72 self.perm.points_to,
73 {
74 self.tracked_get_points_to_with_dealloc().tracked_get_points_to()
75 }
76
77 pub proof fn tracked_borrow_points_to(tracked &self) -> (tracked ret: &PointsTo<T>)
78 returns
79 &self.perm.points_to,
80 {
81 &self.tracked_borrow_points_to_with_dealloc().tracked_borrow_points_to()
82 }
83}
84
85impl<T> ArcPointsTo<T> {
86 pub open spec fn perm(self) -> &'static PointsTo<T> {
87 self.perm
88 }
89
90 pub open spec fn ptr(self) -> *mut T {
91 self.perm.ptr()
92 }
93
94 pub open spec fn addr(self) -> usize {
95 self.ptr().addr()
96 }
97
98 pub open spec fn is_uninit(self) -> bool {
99 self.perm.is_uninit()
100 }
101
102 pub open spec fn is_init(self) -> bool {
103 self.perm.is_init()
104 }
105
106 pub open spec fn value(self) -> T {
107 self.perm.value()
108 }
109
110 pub proof fn tracked_borrow_points_to(tracked &self) -> (tracked ret: &'static PointsTo<T>)
111 returns
112 self.perm,
113 {
114 self.perm
115 }
116}
117
118impl<T> Inv for BoxPointsTo<T> {
119 open spec fn inv(self) -> bool {
120 &&& self.perm.inv()
121 &&& self.perm.dealloc_aligned()
122 &&& self.is_init()
123 }
124}
125
126impl<T> Inv for ArcPointsTo<T> {
127 open spec fn inv(self) -> bool {
128 &&& self.addr() != 0
129 &&& self.addr() as int % vstd::layout::align_of::<T>() as int == 0
130 &&& self.is_init()
131 }
132}
133
134impl<T> Inv for SmartPtrPointsTo<T> {
135 open spec fn inv(self) -> bool {
136 match self {
137 SmartPtrPointsTo::Box(b) => { b.inv() },
138 SmartPtrPointsTo::Arc(a) => { a.inv() },
139 }
140 }
141}
142
143impl<T> SmartPtrPointsTo<T> {
144 pub open spec fn ptr(self) -> *mut T {
145 match self {
146 SmartPtrPointsTo::Box(b) => b.ptr(),
147 SmartPtrPointsTo::Arc(a) => a.ptr(),
148 }
149 }
150
151 pub open spec fn addr(self) -> usize {
152 self.ptr().addr()
153 }
154
155 pub open spec fn is_init(self) -> bool {
156 match self {
157 SmartPtrPointsTo::Box(b) => b.is_init(),
158 SmartPtrPointsTo::Arc(a) => a.is_init(),
159 }
160 }
161
162 pub open spec fn is_uninit(self) -> bool {
163 match self {
164 SmartPtrPointsTo::Box(b) => b.is_uninit(),
165 SmartPtrPointsTo::Arc(a) => a.is_uninit(),
166 }
167 }
168
169 pub proof fn get_box_points_to(tracked self) -> (tracked ret: BoxPointsTo<T>)
170 requires
171 self is Box,
172 returns
173 self->Box_0,
174 {
175 match self {
176 SmartPtrPointsTo::Box(p) => p,
177 _ => proof_from_false(),
178 }
179 }
180
181 pub proof fn get_arc_points_to(tracked self) -> (tracked ret: ArcPointsTo<T>)
182 requires
183 self is Arc,
184 returns
185 self->Arc_0,
186 {
187 match self {
188 SmartPtrPointsTo::Arc(p) => p,
189 _ => proof_from_false(),
190 }
191 }
192
193 pub proof fn new_box_points_to(
194 tracked points_to: PointsTo<T>,
195 tracked dealloc: Option<Dealloc>,
196 ) -> (tracked ret: SmartPtrPointsTo<T>)
197 requires
198 points_to.is_init(),
199 match dealloc {
200 Some(dealloc) => {
201 &&& vstd::layout::size_of::<T>() > 0
202 &&& valid_layout(size_of::<T>(), dealloc.align() as usize)
203 &&& points_to.ptr().addr() == dealloc.addr()
204 &&& points_to.ptr()@.provenance == dealloc.provenance()
205 &&& dealloc.size() == vstd::layout::size_of::<T>()
206 &&& dealloc.align() == vstd::layout::align_of::<T>()
207 },
208 None => { vstd::layout::size_of::<T>() == 0 },
209 },
210 ensures
211 ret.inv(),
212 ret is Box,
213 returns
214 (SmartPtrPointsTo::Box(
215 BoxPointsTo { perm: PointsTowithDealloc { points_to, dealloc } },
216 )),
217 {
218 let tracked box_points_to = BoxPointsTo {
219 perm: PointsTowithDealloc::new(points_to, dealloc),
220 };
221 SmartPtrPointsTo::Box(box_points_to)
222 }
223
224 pub proof fn new_arc_points_to(tracked points_to: &'static PointsTo<T>) -> (tracked ret:
225 SmartPtrPointsTo<T>)
226 requires
227 points_to.is_init(),
228 points_to.ptr().addr() != 0,
229 points_to.ptr().addr() as int % vstd::layout::align_of::<T>() as int == 0,
230 ensures
231 ret.inv(),
232 ret is Arc,
233 returns
234 (SmartPtrPointsTo::Arc(ArcPointsTo { perm: points_to })),
235 {
236 let tracked arc_points_to = ArcPointsTo { perm: points_to };
237 SmartPtrPointsTo::Arc(arc_points_to)
238 }
239}
240
241pub uninterp spec fn box_pointer_spec<T>(b: Box<T>) -> *mut T;
242
243#[verifier::external_body]
251pub fn box_into_raw<T>(b: Box<T>) -> (ret: (*mut T, Tracked<PointsTo<T>>, Tracked<Option<Dealloc>>))
252 ensures
253 ret.0 == box_pointer_spec(b),
254 ret.0 == ret.1@.ptr(),
255 ret.1@.ptr().addr() != 0,
256 ret.1@.is_init(),
257 ret.1@.ptr().addr() as int % vstd::layout::align_of::<T>() as int == 0,
258 match ret.2@ {
259 Some(dealloc) => {
260 &&& vstd::layout::size_of::<T>() > 0
261 &&& dealloc.addr() == ret.1@.ptr().addr()
262 &&& dealloc.size() == vstd::layout::size_of::<T>()
263 &&& dealloc.align() == vstd::layout::align_of::<T>()
264 &&& dealloc.provenance() == ret.1@.ptr()@.provenance
265 &&& valid_layout(size_of::<T>(), align_of::<T>())
266 },
267 None => { &&& vstd::layout::size_of::<T>() == 0 },
268 },
269{
270 (Box::into_raw(b), Tracked::assume_new(), Tracked::assume_new())
271}
272
273#[verifier::external_body]
274pub unsafe fn box_from_raw<T>(
275 ptr: *mut T,
276 tracked points_to: Tracked<PointsTo<T>>,
277 tracked dealloc: Tracked<Option<Dealloc>>,
278) -> (ret: Box<T>)
279 requires
280 ptr@.addr != 0,
281 points_to@.ptr() == ptr,
282 points_to@.is_init(),
283 points_to@.ptr().addr() as int % vstd::layout::align_of::<T>() as int == 0,
284 match dealloc@ {
285 Some(dealloc) => {
286 &&& vstd::layout::size_of::<T>() > 0
287 &&& dealloc.addr() == ptr@.addr
288 &&& dealloc.size() == vstd::layout::size_of::<T>()
289 &&& dealloc.align() == vstd::layout::align_of::<T>()
290 &&& dealloc.provenance() == ptr@.provenance
291 &&& valid_layout(size_of::<T>(), align_of::<T>())
292 },
293 None => { &&& vstd::layout::size_of::<T>() == 0 },
294 },
295 ensures
296 box_pointer_spec(ret) == ptr,
297{
298 unsafe { Box::from_raw(ptr) }
299}
300
301pub uninterp spec fn arc_pointer_spec<T>(a: Arc<T>) -> *const T;
302
303#[verifier::external_body]
306pub fn arc_into_raw<T>(p: Arc<T>) -> (ret: (*const T, Tracked<ArcPointsTo<T>>))
307 ensures
308 ret.0 == arc_pointer_spec(p),
309 ret.0 == ret.1@.ptr(),
310 ret.1@.ptr().addr() != 0,
311 ret.1@.is_init(),
312 ret.1@.ptr().addr() as int % vstd::layout::align_of::<T>() as int == 0,
313{
314 (Arc::into_raw(p), Tracked::assume_new())
315}
316
317#[verifier::external_body]
318pub unsafe fn arc_from_raw<T>(ptr: *const T, tracked points_to: Tracked<ArcPointsTo<T>>) -> (ret:
321 Arc<T>)
322 requires
323 ptr@.addr != 0,
324 points_to@.ptr() == ptr,
325 points_to@.is_init(),
326 points_to@.ptr().addr() as int % vstd::layout::align_of::<T>() as int == 0,
327 ensures
328 arc_pointer_spec(ret) == ptr,
329{
330 unsafe { Arc::from_raw(ptr) }
331}
332
333}