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