Skip to content
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

Make UnsafeCell, RefCell, Mutex, and RwLock accept DSTs #24737

Merged
merged 1 commit into from
May 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 32 additions & 27 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
use clone::Clone;
use cmp::PartialEq;
use default::Default;
use marker::{Copy, Send, Sync};
use marker::{Copy, Send, Sync, Sized};
use ops::{Deref, DerefMut, Drop};
use option::Option;
use option::Option::{None, Some};
Expand Down Expand Up @@ -266,9 +266,9 @@ impl<T:PartialEq + Copy> PartialEq for Cell<T> {
///
/// See the [module-level documentation](index.html) for more.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RefCell<T> {
value: UnsafeCell<T>,
pub struct RefCell<T: ?Sized> {
borrow: Cell<BorrowFlag>,
value: UnsafeCell<T>,
}

/// An enumeration of values returned from the `state` method on a `RefCell<T>`.
Expand Down Expand Up @@ -328,7 +328,9 @@ impl<T> RefCell<T> {
debug_assert!(self.borrow.get() == UNUSED);
unsafe { self.value.into_inner() }
}
}

impl<T: ?Sized> RefCell<T> {
/// Query the current state of this `RefCell`
///
/// The returned value can be dispatched on to determine if a call to
Expand Down Expand Up @@ -449,7 +451,7 @@ impl<T> RefCell<T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T> Send for RefCell<T> where T: Send {}
unsafe impl<T: ?Sized> Send for RefCell<T> where T: Send {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> Clone for RefCell<T> {
Expand All @@ -469,7 +471,7 @@ impl<T:Default> Default for RefCell<T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialEq> PartialEq for RefCell<T> {
impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> {
#[inline]
fn eq(&self, other: &RefCell<T>) -> bool {
*self.borrow() == *other.borrow()
Expand Down Expand Up @@ -519,15 +521,15 @@ impl<'b> Clone for BorrowRef<'b> {
///
/// See the [module-level documentation](index.html) for more.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Ref<'b, T:'b> {
pub struct Ref<'b, T: ?Sized + 'b> {
// FIXME #12808: strange name to try to avoid interfering with
// field accesses of the contained type via Deref
_value: &'b T,
_borrow: BorrowRef<'b>,
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'b, T> Deref for Ref<'b, T> {
impl<'b, T: ?Sized> Deref for Ref<'b, T> {
type Target = T;

#[inline]
Expand Down Expand Up @@ -582,15 +584,15 @@ impl<'b> BorrowRefMut<'b> {
///
/// See the [module-level documentation](index.html) for more.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RefMut<'b, T:'b> {
pub struct RefMut<'b, T: ?Sized + 'b> {
// FIXME #12808: strange name to try to avoid interfering with
// field accesses of the contained type via Deref
_value: &'b mut T,
_borrow: BorrowRefMut<'b>,
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'b, T> Deref for RefMut<'b, T> {
impl<'b, T: ?Sized> Deref for RefMut<'b, T> {
type Target = T;

#[inline]
Expand All @@ -600,7 +602,7 @@ impl<'b, T> Deref for RefMut<'b, T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'b, T> DerefMut for RefMut<'b, T> {
impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> {
#[inline]
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
self._value
Expand Down Expand Up @@ -633,7 +635,7 @@ impl<'b, T> DerefMut for RefMut<'b, T> {
/// recommended to access its fields directly, `get` should be used instead.
#[lang="unsafe_cell"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct UnsafeCell<T> {
pub struct UnsafeCell<T: ?Sized> {
/// Wrapped value
///
/// This field should not be accessed directly, it is made public for static
Expand All @@ -642,7 +644,7 @@ pub struct UnsafeCell<T> {
pub value: T,
}

impl<T> !Sync for UnsafeCell<T> {}
impl<T: ?Sized> !Sync for UnsafeCell<T> {}

impl<T> UnsafeCell<T> {
/// Constructs a new instance of `UnsafeCell` which will wrap the specified
Expand All @@ -664,7 +666,12 @@ impl<T> UnsafeCell<T> {
UnsafeCell { value: value }
}

/// Gets a mutable pointer to the wrapped value.
/// Unwraps the value.
///
/// # Unsafety
///
/// This function is unsafe because there is no guarantee that this or other threads are
/// currently inspecting the inner value.
///
/// # Examples
///
Expand All @@ -673,22 +680,15 @@ impl<T> UnsafeCell<T> {
///
/// let uc = UnsafeCell::new(5);
///
/// let five = uc.get();
/// let five = unsafe { uc.into_inner() };
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get(&self) -> *mut T {
// FIXME(#23542) Replace with type ascription.
#![allow(trivial_casts)]
&self.value as *const T as *mut T
}
pub unsafe fn into_inner(self) -> T { self.value }
}

/// Unwraps the value.
///
/// # Unsafety
///
/// This function is unsafe because there is no guarantee that this or other threads are
/// currently inspecting the inner value.
impl<T: ?Sized> UnsafeCell<T> {
/// Gets a mutable pointer to the wrapped value.
///
/// # Examples
///
Expand All @@ -697,9 +697,14 @@ impl<T> UnsafeCell<T> {
///
/// let uc = UnsafeCell::new(5);
///
/// let five = unsafe { uc.into_inner() };
/// let five = uc.get();
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn into_inner(self) -> T { self.value }
pub fn get(&self) -> *mut T {
// FIXME(#23542) Replace with type ascription.
#![allow(trivial_casts)]
&self.value as *const T as *mut T
}

}
6 changes: 3 additions & 3 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1062,7 +1062,7 @@ impl<T: Copy + Debug> Debug for Cell<T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Debug> Debug for RefCell<T> {
impl<T: ?Sized + Debug> Debug for RefCell<T> {
fn fmt(&self, f: &mut Formatter) -> Result {
match self.borrow_state() {
BorrowState::Unused | BorrowState::Reading => {
Expand All @@ -1074,14 +1074,14 @@ impl<T: Debug> Debug for RefCell<T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'b, T: Debug> Debug for Ref<'b, T> {
impl<'b, T: ?Sized + Debug> Debug for Ref<'b, T> {
fn fmt(&self, f: &mut Formatter) -> Result {
Debug::fmt(&**self, f)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'b, T: Debug> Debug for RefMut<'b, T> {
impl<'b, T: ?Sized + Debug> Debug for RefMut<'b, T> {
fn fmt(&self, f: &mut Formatter) -> Result {
Debug::fmt(&*(self.deref()), f)
}
Expand Down
24 changes: 24 additions & 0 deletions src/libcoretest/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,27 @@ fn refcell_default() {
let cell: RefCell<u64> = Default::default();
assert_eq!(0, *cell.borrow());
}

#[test]
fn unsafe_cell_unsized() {
let cell: &UnsafeCell<[i32]> = &UnsafeCell::new([1, 2, 3]);
{
let val: &mut [i32] = unsafe { &mut *cell.get() };
val[0] = 4;
val[2] = 5;
}
let comp: &mut [i32] = &mut [4, 2, 5];
assert_eq!(unsafe { &mut *cell.get() }, comp);
}

#[test]
fn refcell_unsized() {
let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
{
let b = &mut *cell.borrow_mut();
b[0] = 4;
b[2] = 5;
}
let comp: &mut [i32] = &mut [4, 2, 5];
assert_eq!(&*cell.borrow(), comp);
}
44 changes: 29 additions & 15 deletions src/libstd/sync/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
/// *guard += 1;
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Mutex<T> {
pub struct Mutex<T: ?Sized> {
// Note that this static mutex is in a *box*, not inlined into the struct
// itself. Once a native mutex has been used once, its address can never
// change (it can't be moved). This mutex type can be safely moved at any
Expand All @@ -124,9 +124,9 @@ pub struct Mutex<T> {

// these are the only places where `T: Send` matters; all other
// functionality works fine on a single thread.
unsafe impl<T: Send> Send for Mutex<T> { }
unsafe impl<T: ?Sized + Send> Send for Mutex<T> { }

unsafe impl<T: Send> Sync for Mutex<T> { }
unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { }

/// The static mutex type is provided to allow for static allocation of mutexes.
///
Expand Down Expand Up @@ -164,15 +164,15 @@ pub struct StaticMutex {
/// `Deref` and `DerefMut` implementations
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct MutexGuard<'a, T: 'a> {
pub struct MutexGuard<'a, T: ?Sized + 'a> {
// funny underscores due to how Deref/DerefMut currently work (they
// disregard field privacy).
__lock: &'a StaticMutex,
__data: &'a UnsafeCell<T>,
__poison: poison::Guard,
}

impl<'a, T> !marker::Send for MutexGuard<'a, T> {}
impl<'a, T: ?Sized> !marker::Send for MutexGuard<'a, T> {}

/// Static initialization of a mutex. This constant can be used to initialize
/// other mutex constants.
Expand All @@ -192,7 +192,9 @@ impl<T> Mutex<T> {
data: UnsafeCell::new(t),
}
}
}

impl<T: ?Sized> Mutex<T> {
/// Acquires a mutex, blocking the current task until it is able to do so.
///
/// This function will block the local task until it is available to acquire
Expand Down Expand Up @@ -245,7 +247,7 @@ impl<T> Mutex<T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Mutex<T> {
impl<T: ?Sized> Drop for Mutex<T> {
fn drop(&mut self) {
// This is actually safe b/c we know that there is no further usage of
// this mutex (it's up to the user to arrange for a mutex to get
Expand All @@ -255,12 +257,12 @@ impl<T> Drop for Mutex<T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug + 'static> fmt::Debug for Mutex<T> {
impl<T: ?Sized + fmt::Debug + 'static> fmt::Debug for Mutex<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.try_lock() {
Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", *guard),
Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", &*guard),
Err(TryLockError::Poisoned(err)) => {
write!(f, "Mutex {{ data: Poisoned({:?}) }}", **err.get_ref())
write!(f, "Mutex {{ data: Poisoned({:?}) }}", &**err.get_ref())
},
Err(TryLockError::WouldBlock) => write!(f, "Mutex {{ <locked> }}")
}
Expand Down Expand Up @@ -310,7 +312,7 @@ impl StaticMutex {
}
}

impl<'mutex, T> MutexGuard<'mutex, T> {
impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {

fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
-> LockResult<MutexGuard<'mutex, T>> {
Expand All @@ -325,22 +327,22 @@ impl<'mutex, T> MutexGuard<'mutex, T> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'mutex, T> Deref for MutexGuard<'mutex, T> {
impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> {
type Target = T;

fn deref<'a>(&'a self) -> &'a T {
unsafe { &*self.__data.get() }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> {
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
unsafe { &mut *self.__data.get() }
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Drop for MutexGuard<'a, T> {
impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
#[inline]
fn drop(&mut self) {
unsafe {
Expand All @@ -350,11 +352,11 @@ impl<'a, T> Drop for MutexGuard<'a, T> {
}
}

pub fn guard_lock<'a, T>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
&guard.__lock.lock
}

pub fn guard_poison<'a, T>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
&guard.__lock.poison
}

Expand Down Expand Up @@ -528,4 +530,16 @@ mod tests {
let lock = arc.lock().unwrap();
assert_eq!(*lock, 2);
}

#[test]
fn test_mutex_unsized() {
let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
{
let b = &mut *mutex.lock().unwrap();
b[0] = 4;
b[2] = 5;
}
let comp: &[i32] = &[4, 2, 5];
assert_eq!(&*mutex.lock().unwrap(), comp);
}
}
Loading