qcell/
doctest_tcell.rs

1// Run ./update-compiletest-from-doctest.pl in crate base directory
2// after making any modification to compile_fail tests here.
3
4//! This tests the `TCell` implementation.
5//!
6//! It's not possible to have two simultaneous owners for the same
7//! marker type:
8//!
9//! ```should_panic
10//!# use qcell::{TCell, TCellOwner};
11//!# use std::rc::Rc;
12//! struct Marker;
13//! type ACellOwner = TCellOwner<Marker>;
14//! let mut owner1 = ACellOwner::new();
15//! let mut owner2 = ACellOwner::new();  // Panics here
16//! ```
17//!
18//! You can test if another owner exists using `TCellOwner::try_new()`:
19//!
20//! ```
21//!# use qcell::{TCell, TCellOwner};
22//!# use std::rc::Rc;
23//! struct Marker;
24//! type ACellOwner = TCellOwner<Marker>;
25//! let mut owner1 = ACellOwner::try_new();
26//! assert!(owner1.is_some());
27//! let mut owner2 = ACellOwner::try_new();
28//! assert!(owner2.is_none());
29//! ```
30//!
31//! When you try to create a second owner using
32//! `TCellOwner::wait_for_new`, it will block until the first owner is
33//! dropped:
34//!
35//! ```
36//!# use qcell::{TCell, TCellOwner};
37//!# use std::sync::Arc;
38//! struct Marker;
39//! type ACell<T> = TCell<Marker, T>;
40//! type ACellOwner = TCellOwner<Marker>;
41//! let mut owner1 = ACellOwner::wait_for_new();
42//! let cell_arc1 = Arc::new(ACell::new(123));
43//! let cell_arc2 = cell_arc1.clone();
44//! let thread = std::thread::spawn(move || {
45//!     // blocks until owner1 is dropped
46//!     let mut owner2 = ACellOwner::wait_for_new();
47//!     assert_eq!(*owner2.ro(&*cell_arc2), 456);
48//! });
49//! std::thread::sleep(std::time::Duration::from_millis(100));
50//! *owner1.rw(&*cell_arc1) = 456;
51//! drop(owner1);
52//! assert!(thread.join().is_ok());
53//! ```
54//!
55//! It should be impossible to copy a `TCellOwner`:
56//!
57//! ```compile_fail
58//!# use qcell::{TCell, TCellOwner};
59//!# use std::rc::Rc;
60//!# struct Marker;
61//! type ACell<T> = TCell<Marker, T>;
62//! type ACellOwner = TCellOwner<Marker>;
63//! let mut owner1 = ACellOwner::new();
64//! let mut owner2 = owner1;
65//! let rc = Rc::new(owner1.cell(100u32));  // Compile fail
66//! ```
67//!
68//! It should be impossible to clone a `TCellOwner`:
69//!
70//! ```compile_fail
71//!# use qcell::{TCell, TCellOwner};
72//!# use std::rc::Rc;
73//!# struct Marker;
74//!# type ACellOwner = TCellOwner<Marker>;
75//! let mut owner1 = ACellOwner::new();
76//! let owner2 = owner1.clone();  // Compile fail
77//! ```
78//!
79//! Two different owners can't borrow each other's cells immutably:
80//!
81//! ```compile_fail
82//!# use qcell::{TCell, TCellOwner};
83//!# use std::rc::Rc;
84//! struct MarkerA;
85//! type ACellOwner = TCellOwner<MarkerA>;
86//! type ACell<T> = TCell<MarkerA, T>;
87//! struct MarkerB;
88//! type BCellOwner = TCellOwner<MarkerB>;
89//! type BCell<T> = TCell<MarkerB, T>;
90//!
91//! let mut owner_a = ACellOwner::new();
92//! let mut owner_b = BCellOwner::new();
93//! let c1 = Rc::new(ACell::new(100u32));
94//!
95//! let c1ref = owner_b.ro(&*c1);   // Compile error
96//! println!("{}", *c1ref);
97//! ```
98//!
99//! Or mutably:
100//!
101//! ```compile_fail
102//!# use qcell::{TCell, TCellOwner};
103//!# use std::rc::Rc;
104//!# struct MarkerA;
105//!# type ACellOwner = TCellOwner<MarkerA>;
106//!# type ACell<T> = TCell<MarkerA, T>;
107//!# struct MarkerB;
108//!# type BCellOwner = TCellOwner<MarkerB>;
109//!# type BCell<T> = TCell<MarkerB, T>;
110//! let mut owner_a = ACellOwner::new();
111//! let mut owner_b = BCellOwner::new();
112//! let c1 = Rc::new(ACell::new(100u32));
113//!
114//! let c1mutref = owner_b.rw(&*c1);    // Compile error
115//! println!("{}", *c1mutref);
116//! ```
117//!
118//! You can't have two separate mutable borrows active on the same
119//! owner at the same time:
120//!
121//! ```compile_fail
122//!# use qcell::{TCell, TCellOwner};
123//!# use std::rc::Rc;
124//!# struct Marker;
125//!# type ACellOwner = TCellOwner<Marker>;
126//!# type ACell<T> = TCell<Marker, T>;
127//! let mut owner = ACellOwner::new();
128//! let c1 = Rc::new(ACell::new(100u32));
129//! let c2 = Rc::new(ACell::new(200u32));
130//!
131//! let c1mutref = owner.rw(&c1);
132//! let c2mutref = owner.rw(&c2);  // Compile error
133//! *c1mutref += 1;
134//! *c2mutref += 2;
135//! ```
136//!
137//! However with `rw2()` you can do two mutable borrows at the
138//! same time, since this call checks at runtime that the two
139//! references don't refer to the same memory:
140//!
141//! ```
142//!# use qcell::{TCell, TCellOwner};
143//!# use std::rc::Rc;
144//!# struct Marker;
145//!# type ACellOwner = TCellOwner<Marker>;
146//!# type ACell<T> = TCell<Marker, T>;
147//!# let mut owner = ACellOwner::new();
148//! let c1 = Rc::new(ACell::new(100u32));
149//! let c2 = Rc::new(ACell::new(200u32));
150//!
151//! let (c1mutref, c2mutref) = owner.rw2(&c1, &c2);
152//! *c1mutref += 1;
153//! *c2mutref += 2;
154//! assert_eq!(303, owner.ro(&c1) + owner.ro(&c2));   // Success!
155//! ```
156//!
157//! You can't have a mutable borrow at the same time as an immutable
158//! borrow:
159//!
160//! ```compile_fail
161//!# use qcell::{TCell, TCellOwner};
162//!# use std::rc::Rc;
163//!# struct Marker;
164//!# type ACellOwner = TCellOwner<Marker>;
165//!# type ACell<T> = TCell<Marker, T>;
166//!# let mut owner = ACellOwner::new();
167//! let c1 = Rc::new(ACell::new(100u32));
168//! let c2 = Rc::new(ACell::new(200u32));
169//!
170//! let c1ref = owner.ro(&c1);
171//! let c1mutref = owner.rw(&c1);    // Compile error
172//! println!("{}", *c1ref);
173//! ```
174//!
175//! Not even if it's borrowing a different object:
176//!
177//! ```compile_fail
178//!# use qcell::{TCell, TCellOwner};
179//!# use std::rc::Rc;
180//!# struct Marker;
181//!# type ACellOwner = TCellOwner<Marker>;
182//!# type ACell<T> = TCell<Marker, T>;
183//!# let mut owner = ACellOwner::new();
184//! let c1 = Rc::new(ACell::new(100u32));
185//! let c2 = Rc::new(ACell::new(200u32));
186//!
187//! let c1mutref = owner.rw(&c1);
188//! let c2ref = owner.ro(&c2);    // Compile error
189//! *c1mutref += 1;
190//! ```
191//!
192//! Many immutable borrows at the same time is fine:
193//!
194//! ```
195//!# use qcell::{TCell, TCellOwner};
196//!# use std::rc::Rc;
197//!# struct Marker;
198//!# type ACellOwner = TCellOwner<Marker>;
199//!# type ACell<T> = TCell<Marker, T>;
200//!# let mut owner = ACellOwner::new();
201//! let c1 = Rc::new(ACell::new(100u32));
202//! let c2 = Rc::new(ACell::new(200u32));
203//!
204//! let c1ref = owner.ro(&c1);
205//! let c2ref = owner.ro(&c2);
206//! let c1ref2 = owner.ro(&c1);
207//! let c2ref2 = owner.ro(&c2);
208//! assert_eq!(600, *c1ref + *c2ref + *c1ref2 + *c2ref2);   // Success!
209//! ```
210//!
211//! Whilst a reference is active, it's impossible to drop the `Rc`:
212//!
213//! ```compile_fail
214//!# use qcell::{TCell, TCellOwner};
215//!# use std::rc::Rc;
216//!# struct Marker;
217//!# type ACellOwner = TCellOwner<Marker>;
218//!# type ACell<T> = TCell<Marker, T>;
219//!# let mut owner = ACellOwner::new();
220//! let c1 = Rc::new(ACell::new(100u32));
221//! let c2 = Rc::new(ACell::new(200u32));
222//!
223//! let c1ref = owner.ro(&c1);
224//! drop(c1);    // Compile error
225//! println!("{}", *c1ref);
226//! ```
227//!
228//! Also, whilst a reference is active, it's impossible to call
229//! anything else that uses the `owner` in an incompatible way,
230//! e.g. `&mut` when there's a `&` reference:
231//!
232//! ```compile_fail
233//!# use qcell::{TCell, TCellOwner};
234//!# use std::rc::Rc;
235//!# struct Marker;
236//!# type ACellOwner = TCellOwner<Marker>;
237//!# type ACell<T> = TCell<Marker, T>;
238//!# let mut owner = ACellOwner::new();
239//! let c1 = Rc::new(ACell::new(100u32));
240//! let c2 = Rc::new(ACell::new(200u32));
241//!
242//! fn test(o: &mut ACellOwner) {}
243//!
244//! let c1ref = owner.ro(&c1);
245//! test(&mut owner);    // Compile error
246//! println!("{}", *c1ref);
247//! ```
248//!
249//! Or `&` when there's a `&mut` reference:
250//!
251//! ```compile_fail
252//!# use qcell::{TCell, TCellOwner};
253//!# use std::rc::Rc;
254//!# struct Marker;
255//!# type ACellOwner = TCellOwner<Marker>;
256//!# type ACell<T> = TCell<Marker, T>;
257//!# let mut owner = ACellOwner::new();
258//! let c1 = Rc::new(ACell::new(100u32));
259//! let c2 = Rc::new(ACell::new(200u32));
260//!
261//! fn test(o: &ACellOwner) {}
262//!
263//! let c1mutref = owner.rw(&c1);
264//! test(&owner);    // Compile error
265//! *c1mutref += 1;
266//! ```
267//!
268//! `TCellOwner` and `TCell` should be both `Send` and `Sync` by default:
269//!
270//! ```
271//!# use qcell::{TCellOwner, TCell};
272//! struct Marker;
273//! fn is_send_sync<T: Send + Sync>() {}
274//! is_send_sync::<TCellOwner<Marker>>();
275//! is_send_sync::<TCell<Marker, ()>>();
276//! ```
277//!
278//! So for example we can share a cell ref between threads (Sync), and
279//! pass an owner back and forth (Send):
280//!
281//! ```
282//!# use qcell::{TCellOwner, TCell};
283//!# struct Marker;
284//! type ACellOwner = TCellOwner<Marker>;
285//! type ACell = TCell<Marker, i32>;
286//!
287//! let mut owner = ACellOwner::new();
288//! let cell = ACell::new(100);
289//!
290//! *owner.rw(&cell) += 1;
291//! let cell_ref = &cell;
292//! let mut owner = crossbeam::scope(move |s| {
293//!     s.spawn(move |_| {
294//!         *owner.rw(cell_ref) += 2;
295//!         owner
296//!     }).join().unwrap()
297//! }).unwrap();
298//! *owner.rw(&cell) += 4;
299//! assert_eq!(*owner.ro(&cell), 107);
300//! ```
301//!
302//! However you can't send a cell that's still borrowed:
303//!
304//! ```compile_fail
305//!# use qcell::{TCellOwner, TCell};
306//!# struct Marker;
307//!# type ACellOwner = TCellOwner<Marker>;
308//!# type ACell = TCell<Marker, i32>;
309//! let owner = ACellOwner::new();
310//! let cell = ACell::new(100);
311//! let val_ref = owner.ro(&cell);
312//! std::thread::spawn(move || {
313//!     assert_eq!(*owner.ro(&cell), 100);
314//! }).join();
315//! assert_eq!(*val_ref, 100);
316//! ```
317//!
318//! If the contained type isn't `Sync`, though, then `TCell` shouldn't
319//! be `Sync` either:
320//!
321//! ```compile_fail
322//!# use qcell::TCell;
323//!# use std::cell::Cell;
324//!# struct Marker;
325//! fn is_sync<T: Sync>() {}
326//! is_sync::<TCell<Marker, Cell<i32>>>();  // Compile fail
327//! ```
328//!
329//! ```compile_fail
330//!# use qcell::{TCell, TCellOwner};
331//!# use std::cell::Cell;
332//!# struct Marker;
333//! type ACellOwner = TCellOwner<Marker>;
334//! type ACell = TCell<Marker, Cell<i32>>;
335//!
336//! let owner = ACellOwner::new();
337//! let cell = ACell::new(Cell::new(100));
338//!
339//! // This would be a data race if the compiler permitted it, but it doesn't
340//! std::thread::spawn(|| owner.ro(&cell).set(200));  // Compile fail
341//! owner.ro(&cell).set(300);
342//! ```
343//!
344//! If the contained type isn't `Send`, the `TCell` should be neither
345//! `Sync` nor `Send`:
346//!
347//! ```compile_fail
348//!# use qcell::TCell;
349//!# use std::rc::Rc;
350//!# struct Marker;
351//! fn is_sync<T: Sync>() {}
352//! is_sync::<TCell<Marker, Rc<()>>>();  // Compile fail
353//! ```
354//!
355//! ```compile_fail
356//!# use qcell::TCell;
357//!# use std::rc::Rc;
358//!# struct Marker;
359//! fn is_send<T: Send>() {}
360//! is_send::<TCell<Marker, Rc<()>>>();  // Compile fail
361//! ```
362//!
363//! ```compile_fail
364//!# use qcell::{TCell, TCellOwner};
365//!# use std::rc::Rc;
366//!# struct Marker;
367//! type ACellOwner = TCellOwner<Marker>;
368//! type ACell = TCell<Marker, Rc<i32>>;
369//!
370//! let owner = ACellOwner::new();
371//! let cell = ACell::new(Rc::new(100));
372//!
373//! // We aren't permitted to move the Rc to another thread
374//! std::thread::spawn(move || {    // Compile fail
375//!     assert_eq!(100, **owner.ro(&cell));
376//! }).join();
377//! ```
378//!
379//! Covariant subtypes can't be used to cheat the owner singleton
380//! check.  (This code incorrectly succeeds before qcell version
381//! 0.4.3.)
382//!
383//! ```compile_fail
384//!# use qcell::{TCell, TCellOwner};
385//! type MarkerA = fn(&());
386//! type MarkerB = fn(&'static ());
387//!
388//! let mut owner1 = TCellOwner::<MarkerA>::new() as TCellOwner<MarkerB>;  // Compile fail
389//! let mut owner2 = TCellOwner::<MarkerB>::new();
390//! let cell = TCell::<MarkerB, u32>::new(1234);
391//! let ref1 = owner1.rw(&cell);
392//! let ref2 = owner2.rw(&cell);
393//! *ref1 = 1;  // Two mutable refs at the same time!  Unsound!
394//! *ref2 = 2;
395//! ```
396//!
397//! A reference obtained using `get_mut` should exclude any other kind
398//! of borrowing.
399//!
400//! ```compile_fail
401//!# use qcell::{TCell, TCellOwner};
402//!# struct Marker;
403//!# type ACell<T> = TCell<Marker, T>;
404//!# type ACellOwner = TCellOwner<Marker>;
405//! let owner = ACellOwner::new();
406//! let mut cell = ACell::new(100);
407//! let cell_ref = cell.get_mut();
408//! assert_eq!(100, *owner.ro(&cell)); // Compile fail
409//! *cell_ref = 50;
410//! ```
411//!
412//! ```compile_fail
413//!# use qcell::{TCell, TCellOwner};
414//!# struct Marker;
415//!# type ACell<T> = TCell<Marker, T>;
416//!# type ACellOwner = TCellOwner<Marker>;
417//! let mut owner = ACellOwner::new();
418//! let mut cell = ACell::new(100);
419//! let cell_ref = cell.get_mut();
420//! assert_eq!(100, *owner.rw(&cell)); // Compile fail
421//! *cell_ref = 50;
422//! ```
423//!
424//! ```compile_fail
425//!# use qcell::{TCell, TCellOwner};
426//!# struct Marker;
427//!# type ACell<T> = TCell<Marker, T>;
428//!# type ACellOwner = TCellOwner<Marker>;
429//! let owner = ACellOwner::new();
430//! let mut cell = ACell::new(100);
431//! let cell_ref = owner.ro(&cell);
432//! *cell.get_mut() = 50; // Compile fail
433//! assert_eq!(100, *cell_ref);
434//! ```
435//!
436//! ```compile_fail
437//!# use qcell::{TCell, TCellOwner};
438//!# struct Marker;
439//!# type ACell<T> = TCell<Marker, T>;
440//!# type ACellOwner = TCellOwner<Marker>;
441//! let mut owner = ACellOwner::new();
442//! let mut cell = ACell::new(100);
443//! let cell_ref = owner.rw(&cell);
444//! *cell.get_mut() = 50; // Compile fail
445//! assert_eq!(100, *cell_ref);
446//! ```
447//!
448//! `Default` is implemented, but only if the enclosed type has a
449//! default:
450//!
451//! ```
452//!# use qcell::{TCell, TCellOwner};
453//!# struct Marker;
454//!# type ACell<T> = TCell<Marker, T>;
455//!# type ACellOwner = TCellOwner<Marker>;
456//! let mut owner = ACellOwner::new();
457//! let mut cell: ACell<i32> = ACell::default();
458//! assert_eq!(0, *owner.ro(&cell));
459//! ```
460//!
461//! ```compile_fail
462//!# use qcell::{TCell, TCellOwner};
463//!# struct Marker;
464//!# type ACell<T> = TCell<Marker, T>;
465//!# type ACellOwner = TCellOwner<Marker>;
466//! struct NoDefault(i32);
467//! let mut owner = ACellOwner::new();
468//! let mut cell: ACell<NoDefault> = ACell::default(); // Compile fail
469//! assert_eq!(0, owner.ro(&cell).0);
470//! ```