-
-
Notifications
You must be signed in to change notification settings - Fork 15.2k
implement CovariantUnsafeCell
#159738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
implement CovariantUnsafeCell
#159738
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -737,6 +737,7 @@ symbols! { | |
| cosf64, | ||
| cosf128, | ||
| count, | ||
| covariant_unsafe_cell, | ||
| coverage, | ||
| coverage_attribute, | ||
| cr, | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| use crate::cell::UnsafeCell; | ||
| use crate::fmt; | ||
| use crate::ops::CoerceUnsized; | ||
| use crate::ptr::{self, NonNull}; | ||
|
|
||
| /// **Co**variant version of [`UnsafeCell`]. | ||
| #[unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| #[repr(transparent)] | ||
| #[rustc_pub_transparent] | ||
| // Implementation note: | ||
| // | ||
| // We could make `CovariantUnsafeCell` be the canonical lang item and make `UnsafeCell` a wrapper | ||
| // over it, with `PhantomData<*mut T>`. That would however be a huge compiler change, without clear | ||
| // benefit. | ||
| // | ||
| // As such, `CovariantUnsafeCell` is wrapping `UnsafeCell` instead. It is a lang-item only to | ||
| // hardcode its variance to be **co**variant in `T`, even though it is wrapping `UnsafeCell` which | ||
| // is **in**variant in `T`. | ||
| #[lang = "covariant_unsafe_cell"] | ||
| pub struct CovariantUnsafeCell<T: ?Sized>(UnsafeCell<T>); | ||
|
|
||
| #[unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| impl<T: ?Sized> !Sync for CovariantUnsafeCell<T> {} | ||
|
|
||
| impl<T> CovariantUnsafeCell<T> { | ||
| /// Constructs a new instance of `CovariantUnsafeCell` which will wrap the specified value. | ||
| /// | ||
| /// All access to the inner value through `&CovariantUnsafeCell<T>` requires `unsafe` code. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// #![feature(covariant_unsafe_cell)] | ||
| /// use std::cell::CovariantUnsafeCell; | ||
| /// | ||
| /// let uc = CovariantUnsafeCell::new(5); | ||
| /// ``` | ||
| #[unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| #[rustc_const_unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| #[inline(always)] | ||
| pub const fn new(value: T) -> CovariantUnsafeCell<T> { | ||
| CovariantUnsafeCell(UnsafeCell::new(value)) | ||
| } | ||
|
|
||
| /// Unwraps the value, consuming the cell. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// #![feature(covariant_unsafe_cell)] | ||
| /// use std::cell::CovariantUnsafeCell; | ||
| /// | ||
| /// let uc = CovariantUnsafeCell::new(5); | ||
| /// | ||
| /// let five = uc.into_inner(); | ||
| /// ``` | ||
| #[inline(always)] | ||
| #[unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| #[rustc_const_unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| pub const fn into_inner(self) -> T { | ||
| self.0.into_inner() | ||
| } | ||
| } | ||
|
|
||
| impl<T: ?Sized> CovariantUnsafeCell<T> { | ||
| /// Gets a mutable non-null pointer to the wrapped value. | ||
| /// | ||
| /// This can be cast to a pointer of any kind. When creating (shared or mutable) references, you | ||
| /// must uphold the aliasing rules; see [the `UnsafeCell` type-level docs] for more discussion | ||
| /// and caveats. | ||
| /// | ||
| /// [the `UnsafeCell` type-level docs]: super::UnsafeCell#aliasing-rules | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// #![feature(covariant_unsafe_cell)] | ||
| /// use std::cell::CovariantUnsafeCell; | ||
| /// use std::ptr::NonNull; | ||
| /// | ||
| /// let uc = CovariantUnsafeCell::new(5); | ||
| /// | ||
| /// let ptr: NonNull<i32> = uc.get(); | ||
| /// ``` | ||
| #[inline(always)] | ||
| #[rustc_as_ptr] | ||
| #[rustc_should_not_be_called_on_const_items] | ||
| #[unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| #[rustc_const_unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| pub const fn get(&self) -> NonNull<T> { | ||
| // We can just cast the pointer from `CovariantUnsafeCell<T>` to `T` because of | ||
| // #[repr(transparent)]. | ||
| // | ||
| // Note that this is also known to be allowed for user code as per | ||
| // `#[rustc_pub_transparent]`. | ||
| // SAFETY: the pointer is not null, as it comes from a reference | ||
| unsafe { NonNull::new_unchecked(ptr::from_ref(self).cast_mut() as *mut T) } | ||
| } | ||
|
|
||
| /// Returns a mutable reference to the underlying data. | ||
| /// | ||
| /// This call borrows the `CovariantUnsafeCell` mutably (at compile-time) which guarantees that | ||
| /// we possess the only reference. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ``` | ||
| /// #![feature(covariant_unsafe_cell)] | ||
| /// use std::cell::CovariantUnsafeCell; | ||
| /// | ||
| /// let mut c = CovariantUnsafeCell::new(5); | ||
| /// *c.get_mut() += 1; | ||
| /// | ||
| /// assert_eq!(*c.get_mut(), 6); | ||
| /// ``` | ||
| #[inline(always)] | ||
| #[unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| #[rustc_const_unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| pub const fn get_mut(&mut self) -> &mut T { | ||
| self.0.get_mut() | ||
| } | ||
|
|
||
| /// Gets a mutable pointer to the wrapped value. | ||
| /// The difference from [`get`] is that this function accepts a raw pointer, | ||
| /// which is useful to avoid the creation of temporary references. | ||
| /// | ||
| /// This can be cast to a pointer of any kind. When creating (shared or mutable) references, you | ||
| /// must uphold the aliasing rules; see [the `UnsafeCell` type-level docs] for more discussion | ||
| /// and caveats. | ||
| /// | ||
| /// [`get`]: CovariantUnsafeCell::get() | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// Gradual initialization of an `CovariantUnsafeCell` requires `raw_get`, as | ||
| /// calling `get` would require creating a reference to uninitialized data: | ||
| /// | ||
| /// ``` | ||
| /// #![feature(covariant_unsafe_cell)] | ||
| /// use std::cell::CovariantUnsafeCell; | ||
| /// use std::mem::MaybeUninit; | ||
| /// | ||
| /// let m = MaybeUninit::<CovariantUnsafeCell<i32>>::uninit(); | ||
| /// unsafe { CovariantUnsafeCell::raw_get(m.as_ptr()).write(5); } | ||
| /// // avoid below which references to uninitialized data | ||
| /// // unsafe { CovariantUnsafeCell::get(&*m.as_ptr()).write(5); } | ||
| /// let uc = unsafe { m.assume_init() }; | ||
| /// | ||
| /// assert_eq!(uc.into_inner(), 5); | ||
| /// ``` | ||
| #[inline(always)] | ||
| #[unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| #[rustc_const_unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| pub const fn raw_get(this: *const Self) -> *mut T { | ||
| // We can just cast the pointer from `UnsafeCell<T>` to `T` because of | ||
| // #[repr(transparent)]. | ||
| // | ||
| // Note that this is also known to be allowed for user code as per | ||
| // `#[rustc_pub_transparent]`. | ||
| this as *const T as *mut T | ||
| } | ||
| } | ||
|
|
||
| #[unstable(feature = "coerce_unsized", issue = "18598")] | ||
| impl<T: CoerceUnsized<U>, U> CoerceUnsized<CovariantUnsafeCell<U>> for CovariantUnsafeCell<T> {} | ||
|
|
||
| #[unstable(feature = "covariant_unsafe_cell", issue = "159735")] | ||
| impl<T: ?Sized> fmt::Debug for CovariantUnsafeCell<T> { | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| f.debug_struct("CovariantUnsafeCell").finish_non_exhaustive() | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| fn _covarience<'short, 'long: 'short>( | ||
| x: CovariantUnsafeCell<&'long ()>, | ||
| ) -> CovariantUnsafeCell<&'short ()> { | ||
| x | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.