Skip to content

Commit 17876ec

Browse files
committed
Make UnsafeCell, RefCell, Mutex, and RwLock accept DSTs
This + DST coercions (#24619) would allow code like `Rc<RefCell<Box<Trait>>>` to be simplified to `Rc<RefCell<Trait>>`.
1 parent 2a62242 commit 17876ec

File tree

5 files changed

+122
-64
lines changed

5 files changed

+122
-64
lines changed

src/libcore/cell.rs

+32-27
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144
use clone::Clone;
145145
use cmp::PartialEq;
146146
use default::Default;
147-
use marker::{Copy, Send, Sync};
147+
use marker::{Copy, Send, Sync, Sized};
148148
use ops::{Deref, DerefMut, Drop};
149149
use option::Option;
150150
use option::Option::{None, Some};
@@ -266,9 +266,9 @@ impl<T:PartialEq + Copy> PartialEq for Cell<T> {
266266
///
267267
/// See the [module-level documentation](index.html) for more.
268268
#[stable(feature = "rust1", since = "1.0.0")]
269-
pub struct RefCell<T> {
270-
value: UnsafeCell<T>,
269+
pub struct RefCell<T: ?Sized> {
271270
borrow: Cell<BorrowFlag>,
271+
value: UnsafeCell<T>,
272272
}
273273

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

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

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

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

471473
#[stable(feature = "rust1", since = "1.0.0")]
472-
impl<T: PartialEq> PartialEq for RefCell<T> {
474+
impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> {
473475
#[inline]
474476
fn eq(&self, other: &RefCell<T>) -> bool {
475477
*self.borrow() == *other.borrow()
@@ -520,15 +522,15 @@ impl<'b> Clone for BorrowRef<'b> {
520522
///
521523
/// See the [module-level documentation](index.html) for more.
522524
#[stable(feature = "rust1", since = "1.0.0")]
523-
pub struct Ref<'b, T:'b> {
525+
pub struct Ref<'b, T: ?Sized + 'b> {
524526
// FIXME #12808: strange name to try to avoid interfering with
525527
// field accesses of the contained type via Deref
526528
_value: &'b T,
527529
_borrow: BorrowRef<'b>,
528530
}
529531

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

534536
#[inline]
@@ -584,15 +586,15 @@ impl<'b> BorrowRefMut<'b> {
584586
///
585587
/// See the [module-level documentation](index.html) for more.
586588
#[stable(feature = "rust1", since = "1.0.0")]
587-
pub struct RefMut<'b, T:'b> {
589+
pub struct RefMut<'b, T: ?Sized + 'b> {
588590
// FIXME #12808: strange name to try to avoid interfering with
589591
// field accesses of the contained type via Deref
590592
_value: &'b mut T,
591593
_borrow: BorrowRefMut<'b>,
592594
}
593595

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

598600
#[inline]
@@ -602,7 +604,7 @@ impl<'b, T> Deref for RefMut<'b, T> {
602604
}
603605

604606
#[stable(feature = "rust1", since = "1.0.0")]
605-
impl<'b, T> DerefMut for RefMut<'b, T> {
607+
impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> {
606608
#[inline]
607609
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
608610
self._value
@@ -635,7 +637,7 @@ impl<'b, T> DerefMut for RefMut<'b, T> {
635637
/// recommended to access its fields directly, `get` should be used instead.
636638
#[lang="unsafe_cell"]
637639
#[stable(feature = "rust1", since = "1.0.0")]
638-
pub struct UnsafeCell<T> {
640+
pub struct UnsafeCell<T: ?Sized> {
639641
/// Wrapped value
640642
///
641643
/// This field should not be accessed directly, it is made public for static
@@ -644,7 +646,7 @@ pub struct UnsafeCell<T> {
644646
pub value: T,
645647
}
646648

647-
impl<T> !Sync for UnsafeCell<T> {}
649+
impl<T: ?Sized> !Sync for UnsafeCell<T> {}
648650

649651
impl<T> UnsafeCell<T> {
650652
/// Constructs a new instance of `UnsafeCell` which will wrap the specified
@@ -666,7 +668,12 @@ impl<T> UnsafeCell<T> {
666668
UnsafeCell { value: value }
667669
}
668670

669-
/// Gets a mutable pointer to the wrapped value.
671+
/// Unwraps the value.
672+
///
673+
/// # Unsafety
674+
///
675+
/// This function is unsafe because there is no guarantee that this or other threads are
676+
/// currently inspecting the inner value.
670677
///
671678
/// # Examples
672679
///
@@ -675,22 +682,15 @@ impl<T> UnsafeCell<T> {
675682
///
676683
/// let uc = UnsafeCell::new(5);
677684
///
678-
/// let five = uc.get();
685+
/// let five = unsafe { uc.into_inner() };
679686
/// ```
680687
#[inline]
681688
#[stable(feature = "rust1", since = "1.0.0")]
682-
pub fn get(&self) -> *mut T {
683-
// FIXME(#23542) Replace with type ascription.
684-
#![allow(trivial_casts)]
685-
&self.value as *const T as *mut T
686-
}
689+
pub unsafe fn into_inner(self) -> T { self.value }
690+
}
687691

688-
/// Unwraps the value.
689-
///
690-
/// # Unsafety
691-
///
692-
/// This function is unsafe because there is no guarantee that this or other threads are
693-
/// currently inspecting the inner value.
692+
impl<T: ?Sized> UnsafeCell<T> {
693+
/// Gets a mutable pointer to the wrapped value.
694694
///
695695
/// # Examples
696696
///
@@ -699,9 +699,14 @@ impl<T> UnsafeCell<T> {
699699
///
700700
/// let uc = UnsafeCell::new(5);
701701
///
702-
/// let five = unsafe { uc.into_inner() };
702+
/// let five = uc.get();
703703
/// ```
704704
#[inline]
705705
#[stable(feature = "rust1", since = "1.0.0")]
706-
pub unsafe fn into_inner(self) -> T { self.value }
706+
pub fn get(&self) -> *mut T {
707+
// FIXME(#23542) Replace with type ascription.
708+
#![allow(trivial_casts)]
709+
&self.value as *const T as *mut T
710+
}
711+
707712
}

src/libcore/fmt/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,7 @@ impl<T: Copy + Debug> Debug for Cell<T> {
10681068
}
10691069

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

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

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

src/libcoretest/cell.rs

+24
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,27 @@ fn refcell_default() {
159159
let cell: RefCell<u64> = Default::default();
160160
assert_eq!(0, *cell.borrow());
161161
}
162+
163+
#[test]
164+
fn unsafe_cell_unsized() {
165+
let cell: &UnsafeCell<[i32]> = &UnsafeCell::new([1, 2, 3]);
166+
{
167+
let val: &mut [i32] = unsafe { &mut *cell.get() };
168+
val[0] = 4;
169+
val[2] = 5;
170+
}
171+
let comp: &mut [i32] = &mut [4, 5, 3];
172+
assert_eq!(unsafe { &mut *cell.get() }, comp);
173+
}
174+
175+
#[test]
176+
fn refcell_unsized() {
177+
let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
178+
{
179+
let b = &mut *cell.borrow_mut();
180+
b[0] = 4;
181+
b[2] = 5;
182+
}
183+
let comp: &mut [i32] = &mut [4, 2, 5];
184+
assert_eq!(&*cell.borrow(), comp);
185+
}

src/libstd/sync/mutex.rs

+29-15
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
112112
/// *guard += 1;
113113
/// ```
114114
#[stable(feature = "rust1", since = "1.0.0")]
115-
pub struct Mutex<T> {
115+
pub struct Mutex<T: ?Sized> {
116116
// Note that this static mutex is in a *box*, not inlined into the struct
117117
// itself. Once a native mutex has been used once, its address can never
118118
// change (it can't be moved). This mutex type can be safely moved at any
@@ -124,9 +124,9 @@ pub struct Mutex<T> {
124124

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

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

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

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

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

197+
impl<T: ?Sized> Mutex<T> {
196198
/// Acquires a mutex, blocking the current task until it is able to do so.
197199
///
198200
/// This function will block the local task until it is available to acquire
@@ -246,7 +248,7 @@ impl<T> Mutex<T> {
246248

247249
#[unsafe_destructor]
248250
#[stable(feature = "rust1", since = "1.0.0")]
249-
impl<T> Drop for Mutex<T> {
251+
impl<T: ?Sized> Drop for Mutex<T> {
250252
fn drop(&mut self) {
251253
// This is actually safe b/c we know that there is no further usage of
252254
// this mutex (it's up to the user to arrange for a mutex to get
@@ -256,12 +258,12 @@ impl<T> Drop for Mutex<T> {
256258
}
257259

258260
#[stable(feature = "rust1", since = "1.0.0")]
259-
impl<T: fmt::Debug + 'static> fmt::Debug for Mutex<T> {
261+
impl<T: ?Sized + fmt::Debug + 'static> fmt::Debug for Mutex<T> {
260262
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
261263
match self.try_lock() {
262-
Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", *guard),
264+
Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", &*guard),
263265
Err(TryLockError::Poisoned(err)) => {
264-
write!(f, "Mutex {{ data: Poisoned({:?}) }}", **err.get_ref())
266+
write!(f, "Mutex {{ data: Poisoned({:?}) }}", &**err.get_ref())
265267
},
266268
Err(TryLockError::WouldBlock) => write!(f, "Mutex {{ <locked> }}")
267269
}
@@ -311,7 +313,7 @@ impl StaticMutex {
311313
}
312314
}
313315

314-
impl<'mutex, T> MutexGuard<'mutex, T> {
316+
impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
315317

316318
fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
317319
-> LockResult<MutexGuard<'mutex, T>> {
@@ -326,23 +328,23 @@ impl<'mutex, T> MutexGuard<'mutex, T> {
326328
}
327329

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

332334
fn deref<'a>(&'a self) -> &'a T {
333335
unsafe { &*self.__data.get() }
334336
}
335337
}
336338
#[stable(feature = "rust1", since = "1.0.0")]
337-
impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> {
339+
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
338340
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
339341
unsafe { &mut *self.__data.get() }
340342
}
341343
}
342344

343345
#[unsafe_destructor]
344346
#[stable(feature = "rust1", since = "1.0.0")]
345-
impl<'a, T> Drop for MutexGuard<'a, T> {
347+
impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
346348
#[inline]
347349
fn drop(&mut self) {
348350
unsafe {
@@ -352,11 +354,11 @@ impl<'a, T> Drop for MutexGuard<'a, T> {
352354
}
353355
}
354356

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

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

@@ -530,4 +532,16 @@ mod test {
530532
let lock = arc.lock().unwrap();
531533
assert_eq!(*lock, 2);
532534
}
535+
536+
#[test]
537+
fn test_mutex_unsized() {
538+
let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
539+
{
540+
let b = &mut *mutex.lock().unwrap();
541+
b[0] = 4;
542+
b[2] = 5;
543+
}
544+
let comp: &[i32] = &[4, 2, 5];
545+
assert_eq!(&*mutex.lock().unwrap(), comp);
546+
}
533547
}

0 commit comments

Comments
 (0)