1#![allow(deprecated)]
2#![allow(unused_imports)]
3
4use core::cell::UnsafeCell;
5use core::marker;
6use core::{mem, mem::MaybeUninit};
7
8use super::invariant::*;
9use super::modes::*;
10use super::pervasive::*;
11use super::prelude::*;
12pub use super::raw_ptr::MemContents;
13use super::set::*;
14use super::*;
15
16pub mod invcell;
17pub mod pcell;
18pub mod pcell_maybe_uninit;
19
20verus! {
23
24broadcast use {super::map::group_map_axioms, super::set::group_set_axioms};
25
26#[cfg_attr(not(verus_verify_core), deprecated = "use `vstd::cell::pcell::PCell` or `vstd::cell::pcell_maybe_uninit::PCell` instead")]
63#[verifier::external_body]
64#[verifier::accept_recursive_types(V)]
65pub struct PCell<V> {
66 ucell: UnsafeCell<MaybeUninit<V>>,
67}
68
69#[verifier::external]
72unsafe impl<T> Sync for PCell<T> {
73
74}
75
76#[verifier::external]
77unsafe impl<T> Send for PCell<T> {
78
79}
80
81#[verifier::external_body]
88#[verifier::reject_recursive_types_in_ground_variants(V)]
89pub tracked struct PointsTo<V> {
90 phantom: marker::PhantomData<V>,
91 no_copy: NoCopy,
92}
93
94pub ghost struct PointsToData<V> {
95 pub pcell: CellId,
96 pub mem_contents: MemContents<V>,
97}
98
99#[doc(hidden)]
100#[macro_export]
101macro_rules! pcell_points_internal {
102 [$pcell:expr => $val:expr] => {
103 $crate::vstd::cell::PointsToData {
104 pcell: $pcell,
105 mem_contents: $val,
106 }
107 };
108}
109
110#[macro_export]
111macro_rules! pcell_points {
112 [$($tail:tt)*] => {
113 $crate::vstd::prelude::verus_proof_macro_exprs!(
114 $crate::vstd::cell::pcell_points_internal!($($tail)*)
115 )
116 }
117}
118
119pub use pcell_points_internal;
120pub use pcell_points;
121
122#[verifier::external_body]
123pub struct CellId {
124 id: int,
125}
126
127impl<V> PointsTo<V> {
128 pub uninterp spec fn id(&self) -> CellId;
130
131 pub uninterp spec fn mem_contents(&self) -> MemContents<V>;
133
134 pub open spec fn view(self) -> PointsToData<V> {
135 PointsToData { pcell: self.id(), mem_contents: self.mem_contents() }
136 }
137
138 #[verifier::inline]
140 pub open spec fn is_init(&self) -> bool {
141 self.mem_contents().is_init()
142 }
143
144 #[verifier::inline]
146 pub open spec fn is_uninit(&self) -> bool {
147 self.mem_contents().is_uninit()
148 }
149
150 #[verifier::inline]
152 pub open spec fn value(&self) -> V
153 recommends
154 self.is_init(),
155 {
156 self.mem_contents().value()
157 }
158}
159
160#[cfg_attr(not(verus_verify_core), deprecated = "use `vstd::cell::pcell::PCell` or `vstd::cell::pcell_maybe_uninit::PCell` instead")]
161impl<V> PCell<V> {
162 pub uninterp spec fn id(&self) -> CellId;
164
165 #[inline(always)]
167 #[verifier::external_body]
168 pub const fn empty() -> (pt: (PCell<V>, Tracked<PointsTo<V>>))
169 ensures
170 pt.1@@ == pcell_points![ pt.0.id() => MemContents::Uninit ],
171 {
172 let p = PCell { ucell: UnsafeCell::new(MaybeUninit::uninit()) };
173 (p, Tracked::assume_new())
174 }
175
176 #[inline(always)]
177 #[verifier::external_body]
178 pub const fn new(v: V) -> (pt: (PCell<V>, Tracked<PointsTo<V>>))
179 ensures
180 pt.1@@ == pcell_points! [ pt.0.id() => MemContents::Init(v) ],
181 {
182 let p = PCell { ucell: UnsafeCell::new(MaybeUninit::new(v)) };
183 (p, Tracked::assume_new())
184 }
185
186 #[inline(always)]
187 #[verifier::external_body]
188 pub fn put(&self, Tracked(perm): Tracked<&mut PointsTo<V>>, v: V)
189 requires
190 old(perm)@ == pcell_points![ self.id() => MemContents::Uninit ],
191 ensures
192 final(perm)@ == pcell_points![ self.id() => MemContents::Init(v) ],
193 opens_invariants none
194 no_unwind
195 {
196 unsafe {
197 *(self.ucell.get()) = MaybeUninit::new(v);
198 }
199 }
200
201 #[inline(always)]
202 #[verifier::external_body]
203 pub fn take(&self, Tracked(perm): Tracked<&mut PointsTo<V>>) -> (v: V)
204 requires
205 self.id() == old(perm)@.pcell,
206 old(perm).is_init(),
207 ensures
208 final(perm).id() == old(perm)@.pcell,
209 final(perm).mem_contents() == MemContents::Uninit,
210 v == old(perm).value(),
211 opens_invariants none
212 no_unwind
213 {
214 unsafe {
215 let mut m = MaybeUninit::uninit();
216 mem::swap(&mut m, &mut *self.ucell.get());
217 m.assume_init()
218 }
219 }
220
221 #[inline(always)]
222 #[verifier::external_body]
223 pub fn replace(&self, Tracked(perm): Tracked<&mut PointsTo<V>>, in_v: V) -> (out_v: V)
224 requires
225 self.id() == old(perm)@.pcell,
226 old(perm).is_init(),
227 ensures
228 final(perm).id() == old(perm)@.pcell,
229 final(perm).mem_contents() == MemContents::Init(in_v),
230 out_v == old(perm).value(),
231 opens_invariants none
232 no_unwind
233 {
234 unsafe {
235 let mut m = MaybeUninit::new(in_v);
236 mem::swap(&mut m, &mut *self.ucell.get());
237 m.assume_init()
238 }
239 }
240
241 #[inline(always)]
245 #[verifier::external_body]
246 pub fn borrow<'a>(&'a self, Tracked(perm): Tracked<&'a PointsTo<V>>) -> (v: &'a V)
247 requires
248 self.id() == perm@.pcell,
249 perm.is_init(),
250 ensures
251 *v == perm.value(),
252 opens_invariants none
253 no_unwind
254 {
255 unsafe { (*self.ucell.get()).assume_init_ref() }
256 }
257
258 #[inline(always)]
261 pub fn into_inner(self, Tracked(perm): Tracked<PointsTo<V>>) -> (v: V)
262 requires
263 self.id() == perm@.pcell,
264 perm.is_init(),
265 ensures
266 v == perm.value(),
267 opens_invariants none
268 no_unwind
269 {
270 let tracked mut perm = perm;
271 self.take(Tracked(&mut perm))
272 }
273
274 #[doc(hidden)]
275 #[inline(always)]
276 #[verifier::external_body]
277 pub fn borrow_mut<'a>(&'a self, Tracked(perm): Tracked<&'a mut PointsTo<V>>) -> (v: &'a mut V)
278 requires
279 self.id() == perm@.pcell,
280 perm.is_init(),
281 ensures
282 *v == old(perm).value(),
283 final(perm).id() == old(perm).id(),
284 final(perm).is_init(),
285 final(perm).value() == *final(v),
286 opens_invariants none
287 no_unwind
288 {
289 unsafe { (*self.ucell.get()).assume_init_mut() }
290 }
291}
292
293#[cfg_attr(not(verus_verify_core), deprecated = "use `vstd::cell::pcell::PCell` or `vstd::cell::pcell_maybe_uninit::PCell` instead")]
294impl<V: Copy> PCell<V> {
295 #[inline(always)]
296 #[verifier::external_body]
297 pub fn write(&self, Tracked(perm): Tracked<&mut PointsTo<V>>, in_v: V)
298 requires
299 self.id() == old(perm)@.pcell,
300 old(perm).is_init(),
301 ensures
302 final(perm).id() == old(perm)@.pcell,
303 final(perm).mem_contents() == MemContents::Init(in_v),
304 opens_invariants none
305 no_unwind
306 {
307 let _out = self.replace(Tracked(&mut *perm), in_v);
308 }
309}
310
311struct InvCellPred {}
312
313impl<T> InvariantPredicate<(Set<T>, PCell<T>), PointsTo<T>> for InvCellPred {
314 closed spec fn inv(k: (Set<T>, PCell<T>), perm: PointsTo<T>) -> bool {
315 let (possible_values, pcell) = k;
316 {
317 &&& perm.is_init()
318 &&& possible_values.contains(perm.value())
319 &&& pcell.id() == perm@.pcell
320 }
321 }
322}
323
324#[cfg_attr(not(verus_verify_core), deprecated = "use `vstd::cell::invcell::InvCell` instead")]
326#[verifier::reject_recursive_types(T)]
327pub struct InvCell<T> {
328 possible_values: Ghost<Set<T>>,
329 pcell: PCell<T>,
330 perm_inv: Tracked<LocalInvariant<(Set<T>, PCell<T>), PointsTo<T>, InvCellPred>>,
331}
332
333#[cfg_attr(not(verus_verify_core), deprecated = "use `vstd::cell::invcell::InvCell` instead")]
334impl<T> InvCell<T> {
335 #[verifier::type_invariant]
336 closed spec fn wf(&self) -> bool {
337 &&& self.perm_inv@.constant() == (self.possible_values@, self.pcell)
338 }
339
340 pub closed spec fn inv(&self, val: T) -> bool {
341 &&& self.possible_values@.contains(val)
342 }
343
344 pub fn new(val: T, Ghost(f): Ghost<spec_fn(T) -> bool>) -> (cell: Self)
345 requires
346 f(val),
347 ensures
348 forall|v| f(v) <==> cell.inv(v),
349 {
350 let (pcell, Tracked(perm)) = PCell::new(val);
351 let ghost possible_values = Set::new(f);
352 let tracked perm_inv = LocalInvariant::new((possible_values, pcell), perm, 0);
353 InvCell { possible_values: Ghost(possible_values), pcell, perm_inv: Tracked(perm_inv) }
354 }
355}
356
357#[cfg_attr(not(verus_verify_core), deprecated = "use `vstd::cell::invcell::InvCell` instead")]
358impl<T> InvCell<T> {
359 pub fn replace(&self, val: T) -> (old_val: T)
360 requires
361 self.inv(val),
362 ensures
363 self.inv(old_val),
364 {
365 proof {
366 use_type_invariant(self);
367 }
368 let r;
369 open_local_invariant!(self.perm_inv.borrow() => perm => {
370 r = self.pcell.replace(Tracked(&mut perm), val);
371 });
372 r
373 }
374}
375
376#[cfg_attr(not(verus_verify_core), deprecated = "use `vstd::cell::invcell::InvCell` instead")]
377impl<T: Copy> InvCell<T> {
378 pub fn get(&self) -> (val: T)
379 ensures
380 self.inv(val),
381 {
382 proof {
383 use_type_invariant(self);
384 }
385 let r;
386 open_local_invariant!(self.perm_inv.borrow() => perm => {
387 r = *self.pcell.borrow(Tracked(&perm));
388 });
389 r
390 }
391}
392
393}