Skip to main content

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}