core/cell/covariant_unsafe_cell.rs
1use crate::cell::UnsafeCell;
2use crate::fmt;
3use crate::ops::CoerceUnsized;
4use crate::ptr::{self, NonNull};
5
6/// **Co**variant version of [`UnsafeCell`].
7#[unstable(feature = "covariant_unsafe_cell", issue = "159735")]
8#[repr(transparent)]
9#[rustc_pub_transparent]
10// Implementation note:
11//
12// We could make `CovariantUnsafeCell` be the canonical lang item and make `UnsafeCell` a wrapper
13// over it, with `PhantomData<*mut T>`. That would however be a huge compiler change, without clear
14// benefit.
15//
16// As such, `CovariantUnsafeCell` is wrapping `UnsafeCell` instead. It is a lang-item only to
17// hardcode its variance to be **co**variant in `T`, even though it is wrapping `UnsafeCell` which
18// is **in**variant in `T`.
19#[lang = "covariant_unsafe_cell"]
20pub struct CovariantUnsafeCell<T: ?Sized>(UnsafeCell<T>);
21
22#[unstable(feature = "covariant_unsafe_cell", issue = "159735")]
23impl<T: ?Sized> !Sync for CovariantUnsafeCell<T> {}
24
25impl<T> CovariantUnsafeCell<T> {
26 /// Constructs a new instance of `CovariantUnsafeCell` which will wrap the specified value.
27 ///
28 /// All access to the inner value through `&CovariantUnsafeCell<T>` requires `unsafe` code.
29 ///
30 /// # Examples
31 ///
32 /// ```
33 /// #![feature(covariant_unsafe_cell)]
34 /// use std::cell::CovariantUnsafeCell;
35 ///
36 /// let uc = CovariantUnsafeCell::new(5);
37 /// ```
38 #[unstable(feature = "covariant_unsafe_cell", issue = "159735")]
39 #[rustc_const_unstable(feature = "covariant_unsafe_cell", issue = "159735")]
40 #[inline(always)]
41 pub const fn new(value: T) -> CovariantUnsafeCell<T> {
42 CovariantUnsafeCell(UnsafeCell::new(value))
43 }
44
45 /// Unwraps the value, consuming the cell.
46 ///
47 /// # Examples
48 ///
49 /// ```
50 /// #![feature(covariant_unsafe_cell)]
51 /// use std::cell::CovariantUnsafeCell;
52 ///
53 /// let uc = CovariantUnsafeCell::new(5);
54 ///
55 /// let five = uc.into_inner();
56 /// ```
57 #[inline(always)]
58 #[unstable(feature = "covariant_unsafe_cell", issue = "159735")]
59 #[rustc_const_unstable(feature = "covariant_unsafe_cell", issue = "159735")]
60 pub const fn into_inner(self) -> T {
61 self.0.into_inner()
62 }
63}
64
65impl<T: ?Sized> CovariantUnsafeCell<T> {
66 /// Gets a mutable non-null pointer to the wrapped value.
67 ///
68 /// This can be cast to a pointer of any kind. When creating (shared or mutable) references, you
69 /// must uphold the aliasing rules; see [the `UnsafeCell` type-level docs] for more discussion
70 /// and caveats.
71 ///
72 /// [the `UnsafeCell` type-level docs]: super::UnsafeCell#aliasing-rules
73 ///
74 /// # Examples
75 ///
76 /// ```
77 /// #![feature(covariant_unsafe_cell)]
78 /// use std::cell::CovariantUnsafeCell;
79 /// use std::ptr::NonNull;
80 ///
81 /// let uc = CovariantUnsafeCell::new(5);
82 ///
83 /// let ptr: NonNull<i32> = uc.get();
84 /// ```
85 #[inline(always)]
86 #[rustc_as_ptr]
87 #[rustc_should_not_be_called_on_const_items]
88 #[unstable(feature = "covariant_unsafe_cell", issue = "159735")]
89 #[rustc_const_unstable(feature = "covariant_unsafe_cell", issue = "159735")]
90 pub const fn get(&self) -> NonNull<T> {
91 // We can just cast the pointer from `CovariantUnsafeCell<T>` to `T` because of
92 // #[repr(transparent)].
93 //
94 // Note that this is also known to be allowed for user code as per
95 // `#[rustc_pub_transparent]`.
96 // SAFETY: the pointer is not null, as it comes from a reference
97 unsafe { NonNull::new_unchecked(ptr::from_ref(self).cast_mut() as *mut T) }
98 }
99
100 /// Returns a mutable reference to the underlying data.
101 ///
102 /// This call borrows the `CovariantUnsafeCell` mutably (at compile-time) which guarantees that
103 /// we possess the only reference.
104 ///
105 /// # Examples
106 ///
107 /// ```
108 /// #![feature(covariant_unsafe_cell)]
109 /// use std::cell::CovariantUnsafeCell;
110 ///
111 /// let mut c = CovariantUnsafeCell::new(5);
112 /// *c.get_mut() += 1;
113 ///
114 /// assert_eq!(*c.get_mut(), 6);
115 /// ```
116 #[inline(always)]
117 #[unstable(feature = "covariant_unsafe_cell", issue = "159735")]
118 #[rustc_const_unstable(feature = "covariant_unsafe_cell", issue = "159735")]
119 pub const fn get_mut(&mut self) -> &mut T {
120 self.0.get_mut()
121 }
122
123 /// Gets a mutable pointer to the wrapped value.
124 /// The difference from [`get`] is that this function accepts a raw pointer,
125 /// which is useful to avoid the creation of temporary references.
126 ///
127 /// This can be cast to a pointer of any kind. When creating (shared or mutable) references, you
128 /// must uphold the aliasing rules; see [the `UnsafeCell` type-level docs] for more discussion
129 /// and caveats.
130 ///
131 /// [`get`]: CovariantUnsafeCell::get()
132 ///
133 /// # Examples
134 ///
135 /// Gradual initialization of an `CovariantUnsafeCell` requires `raw_get`, as
136 /// calling `get` would require creating a reference to uninitialized data:
137 ///
138 /// ```
139 /// #![feature(covariant_unsafe_cell)]
140 /// use std::cell::CovariantUnsafeCell;
141 /// use std::mem::MaybeUninit;
142 ///
143 /// let m = MaybeUninit::<CovariantUnsafeCell<i32>>::uninit();
144 /// unsafe { CovariantUnsafeCell::raw_get(m.as_ptr()).write(5); }
145 /// // avoid below which references to uninitialized data
146 /// // unsafe { CovariantUnsafeCell::get(&*m.as_ptr()).write(5); }
147 /// let uc = unsafe { m.assume_init() };
148 ///
149 /// assert_eq!(uc.into_inner(), 5);
150 /// ```
151 #[inline(always)]
152 #[unstable(feature = "covariant_unsafe_cell", issue = "159735")]
153 #[rustc_const_unstable(feature = "covariant_unsafe_cell", issue = "159735")]
154 pub const fn raw_get(this: *const Self) -> *mut T {
155 // We can just cast the pointer from `UnsafeCell<T>` to `T` because of
156 // #[repr(transparent)].
157 //
158 // Note that this is also known to be allowed for user code as per
159 // `#[rustc_pub_transparent]`.
160 this as *const T as *mut T
161 }
162}
163
164#[unstable(feature = "coerce_unsized", issue = "18598")]
165impl<T: CoerceUnsized<U>, U> CoerceUnsized<CovariantUnsafeCell<U>> for CovariantUnsafeCell<T> {}
166
167#[unstable(feature = "covariant_unsafe_cell", issue = "159735")]
168impl<T: ?Sized> fmt::Debug for CovariantUnsafeCell<T> {
169 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170 f.debug_struct("CovariantUnsafeCell").finish_non_exhaustive()
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 fn _covarience<'short, 'long: 'short>(
179 x: CovariantUnsafeCell<&'long ()>,
180 ) -> CovariantUnsafeCell<&'short ()> {
181 x
182 }
183}