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