]>
Commit | Line | Data |
---|---|---|
60c5eb7d XL |
1 | A borrow of a constant containing interior mutability was attempted. |
2 | ||
3 | Erroneous code example: | |
4 | ||
5 | ```compile_fail,E0492 | |
6 | use std::sync::atomic::AtomicUsize; | |
7 | ||
8 | const A: AtomicUsize = AtomicUsize::new(0); | |
9 | static B: &'static AtomicUsize = &A; | |
10 | // error: cannot borrow a constant which may contain interior mutability, | |
11 | // create a static instead | |
12 | ``` | |
13 | ||
14 | A `const` represents a constant value that should never change. If one takes | |
15 | a `&` reference to the constant, then one is taking a pointer to some memory | |
16 | location containing the value. Normally this is perfectly fine: most values | |
17 | can't be changed via a shared `&` pointer, but interior mutability would allow | |
18 | it. That is, a constant value could be mutated. On the other hand, a `static` is | |
19 | explicitly a single memory location, which can be mutated at will. | |
20 | ||
21 | So, in order to solve this error, either use statics which are `Sync`: | |
22 | ||
23 | ``` | |
24 | use std::sync::atomic::AtomicUsize; | |
25 | ||
26 | static A: AtomicUsize = AtomicUsize::new(0); | |
27 | static B: &'static AtomicUsize = &A; // ok! | |
28 | ``` | |
29 | ||
30 | You can also have this error while using a cell type: | |
31 | ||
32 | ```compile_fail,E0492 | |
33 | use std::cell::Cell; | |
34 | ||
35 | const A: Cell<usize> = Cell::new(1); | |
36 | const B: &Cell<usize> = &A; | |
37 | // error: cannot borrow a constant which may contain interior mutability, | |
38 | // create a static instead | |
39 | ||
40 | // or: | |
41 | struct C { a: Cell<usize> } | |
42 | ||
43 | const D: C = C { a: Cell::new(1) }; | |
44 | const E: &Cell<usize> = &D.a; // error | |
45 | ||
46 | // or: | |
47 | const F: &C = &D; // error | |
48 | ``` | |
49 | ||
50 | This is because cell types do operations that are not thread-safe. Due to this, | |
51 | they don't implement Sync and thus can't be placed in statics. | |
52 | ||
53 | However, if you still wish to use these types, you can achieve this by an unsafe | |
54 | wrapper: | |
55 | ||
56 | ``` | |
57 | use std::cell::Cell; | |
58 | use std::marker::Sync; | |
59 | ||
60 | struct NotThreadSafe<T> { | |
61 | value: Cell<T>, | |
62 | } | |
63 | ||
64 | unsafe impl<T> Sync for NotThreadSafe<T> {} | |
65 | ||
66 | static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) }; | |
67 | static B: &'static NotThreadSafe<usize> = &A; // ok! | |
68 | ``` | |
69 | ||
70 | Remember this solution is unsafe! You will have to ensure that accesses to the | |
71 | cell are synchronized. |