Skip to content

Commit

Permalink
auto merge of #15591 : aturon/rust/box-cell-stability, r=alexcrichton
Browse files Browse the repository at this point in the history
This PR is the outcome of the library stabilization meeting for the
`liballoc::owned` and `libcore::cell` modules.

Aside from the stability attributes, there are a few breaking changes:

* The `owned` modules is now named `boxed`, to better represent its
  contents. (`box` was unavailable, since it's a keyword.) This will
  help avoid the misconception that `Box` plays a special role wrt
  ownership.

* The `AnyOwnExt` extension trait is renamed to `BoxAny`, and its `move`
  method is renamed to `downcast`, in both cases to improve clarity.

* The recently-added `AnySendOwnExt` extension trait is removed; it was
  not being used and is unnecessary.

[breaking-change]
  • Loading branch information
bors committed Jul 13, 2014
2 parents 7a6208f + e0ede9c commit ffd9966
Show file tree
Hide file tree
Showing 49 changed files with 112 additions and 107 deletions.
59 changes: 19 additions & 40 deletions src/liballoc/owned.rs → src/liballoc/boxed.rs
Expand Up @@ -16,7 +16,6 @@ use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
use core::default::Default;
use core::fmt;
use core::intrinsics;
use core::kinds::Send;
use core::mem;
use core::option::Option;
use core::raw::TraitObject;
Expand All @@ -27,17 +26,19 @@ use core::result::{Ok, Err, Result};
///
/// The following two examples are equivalent:
///
/// use std::owned::HEAP;
/// use std::boxed::HEAP;
///
/// # struct Bar;
/// # impl Bar { fn new(_a: int) { } }
/// let foo = box(HEAP) Bar::new(2);
/// let foo = box Bar::new(2);
#[lang="exchange_heap"]
#[lang = "exchange_heap"]
#[experimental = "may be renamed; uncertain about custom allocator design"]
pub static HEAP: () = ();

/// A type that represents a uniquely-owned value.
#[lang="owned_box"]
#[lang = "owned_box"]
#[unstable = "custom allocators will add an additional type parameter (with default)"]
pub struct Box<T>(*mut T);

impl<T: Default> Default for Box<T> {
Expand All @@ -57,7 +58,6 @@ impl<T: Clone> Clone for Box<T> {
}
}

// box pointers
impl<T:PartialEq> PartialEq for Box<T> {
#[inline]
fn eq(&self, other: &Box<T>) -> bool { *(*self) == *(*other) }
Expand Down Expand Up @@ -85,48 +85,27 @@ impl<T: Ord> Ord for Box<T> {
impl<T: Eq> Eq for Box<T> {}

/// Extension methods for an owning `Any` trait object
pub trait AnyOwnExt {
#[unstable = "post-DST, the signature of `downcast` will change to take `Box<Self>`"]
pub trait BoxAny {
/// Returns the boxed value if it is of type `T`, or
/// `Err(Self)` if it isn't.
fn move<T: 'static>(self) -> Result<Box<T>, Self>;
}

impl AnyOwnExt for Box<Any> {
#[inline]
fn move<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
if self.is::<T>() {
unsafe {
// Get the raw representation of the trait object
let to: TraitObject =
*mem::transmute::<&Box<Any>, &TraitObject>(&self);

// Prevent destructor on self being run
intrinsics::forget(self);
fn downcast<T: 'static>(self) -> Result<Box<T>, Self>;

// Extract the data pointer
Ok(mem::transmute(to.data))
}
} else {
Err(self)
}
/// Deprecated; this method has been renamed to `downcast`.
#[deprecated = "use downcast instead"]
fn move<T: 'static>(self) -> Result<Box<T>, Self> {
self.downcast::<T>()
}
}

/// Extension methods for an owning `Any+Send` trait object
pub trait AnySendOwnExt {
/// Returns the boxed value if it is of type `T`, or
/// `Err(Self)` if it isn't.
fn move_send<T: 'static>(self) -> Result<Box<T>, Self>;
}

impl AnySendOwnExt for Box<Any+Send> {
impl BoxAny for Box<Any> {
#[inline]
fn move_send<T: 'static>(self) -> Result<Box<T>, Box<Any+Send>> {
fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
if self.is::<T>() {
unsafe {
// Get the raw representation of the trait object
let to: TraitObject =
*mem::transmute::<&Box<Any+Send>, &TraitObject>(&self);
*mem::transmute::<&Box<Any>, &TraitObject>(&self);

// Prevent destructor on self being run
intrinsics::forget(self);
Expand Down Expand Up @@ -166,20 +145,20 @@ mod test {
let a = box 8u as Box<Any>;
let b = box Test as Box<Any>;

match a.move::<uint>() {
match a.downcast::<uint>() {
Ok(a) => { assert!(a == box 8u); }
Err(..) => fail!()
}
match b.move::<Test>() {
match b.downcast::<Test>() {
Ok(a) => { assert!(a == box Test); }
Err(..) => fail!()
}

let a = box 8u as Box<Any>;
let b = box Test as Box<Any>;

assert!(a.move::<Box<Test>>().is_err());
assert!(b.move::<Box<uint>>().is_err());
assert!(a.downcast::<Box<Test>>().is_err());
assert!(b.downcast::<Box<uint>>().is_err());
}

#[test]
Expand Down
14 changes: 10 additions & 4 deletions src/liballoc/lib.rs
Expand Up @@ -21,11 +21,11 @@
//!
//! Currently, there are four major definitions in this library.
//!
//! ## Owned pointers
//! ## Boxed values
//!
//! The [`Box`](owned/index.html) type is the core owned pointer type in rust.
//! The [`Box`](boxed/index.html) type is the core owned pointer type in rust.
//! There can only be one owner of a `Box`, and the owner can decide to mutate
//! the contents.
//! the contents, which live on the heap.
//!
//! This type can be sent among tasks efficiently as the size of a `Box` value
//! is just a pointer. Tree-like data structures are often built on owned
Expand Down Expand Up @@ -82,6 +82,12 @@ extern crate libc;
#[cfg(test)] #[phase(plugin, link)] extern crate std;
#[cfg(test)] #[phase(plugin, link)] extern crate log;

// The deprecated name of the boxed module

#[deprecated = "use boxed instead"]
#[cfg(not(test))]
pub use owned = boxed;

// Heaps provided for low-level allocation strategies

pub mod heap;
Expand All @@ -91,7 +97,7 @@ pub mod util;
// Primitive types using the heaps above

#[cfg(not(test))]
pub mod owned;
pub mod boxed;
pub mod arc;
pub mod rc;

Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/btree.rs
Expand Up @@ -20,7 +20,7 @@

use core::prelude::*;

use alloc::owned::Box;
use alloc::boxed::Box;
use core::fmt;
use core::fmt::Show;

Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/dlist.rs
Expand Up @@ -23,7 +23,7 @@

use core::prelude::*;

use alloc::owned::Box;
use alloc::boxed::Box;
use core::default::Default;
use core::fmt;
use core::iter;
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/hash/mod.rs
Expand Up @@ -65,7 +65,7 @@

use core::prelude::*;

use alloc::owned::Box;
use alloc::boxed::Box;
use alloc::rc::Rc;
use core::intrinsics::TypeId;
use core::mem;
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/treemap.rs
Expand Up @@ -14,7 +14,7 @@

use core::prelude::*;

use alloc::owned::Box;
use alloc::boxed::Box;
use core::default::Default;
use core::fmt;
use core::fmt::Show;
Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/trie.rs
Expand Up @@ -12,7 +12,7 @@

use core::prelude::*;

use alloc::owned::Box;
use alloc::boxed::Box;
use core::default::Default;
use core::mem::zeroed;
use core::mem;
Expand Down
24 changes: 21 additions & 3 deletions src/libcore/cell.rs
Expand Up @@ -163,11 +163,13 @@ use option::{None, Option, Some};
use ty::Unsafe;

/// A mutable memory location that admits only `Copy` data.
#[unstable = "likely to be renamed; otherwise stable"]
pub struct Cell<T> {
value: Unsafe<T>,
noshare: marker::NoShare,
}

#[stable]
impl<T:Copy> Cell<T> {
/// Creates a new `Cell` containing the given value.
pub fn new(value: T) -> Cell<T> {
Expand All @@ -192,20 +194,22 @@ impl<T:Copy> Cell<T> {
}
}

#[unstable]
#[unstable = "waiting for `Clone` trait to become stable"]
impl<T:Copy> Clone for Cell<T> {
fn clone(&self) -> Cell<T> {
Cell::new(self.get())
}
}

#[unstable = "waiting for `PartialEq` trait to become stable"]
impl<T:PartialEq + Copy> PartialEq for Cell<T> {
fn eq(&self, other: &Cell<T>) -> bool {
self.get() == other.get()
}
}

/// A mutable memory location with dynamically checked borrow rules
#[unstable = "likely to be renamed; otherwise stable"]
pub struct RefCell<T> {
value: Unsafe<T>,
borrow: Cell<BorrowFlag>,
Expand All @@ -221,6 +225,7 @@ static WRITING: BorrowFlag = -1;

impl<T> RefCell<T> {
/// Create a new `RefCell` containing `value`
#[stable]
pub fn new(value: T) -> RefCell<T> {
RefCell {
value: Unsafe::new(value),
Expand All @@ -231,6 +236,7 @@ impl<T> RefCell<T> {
}

/// Consumes the `RefCell`, returning the wrapped value.
#[unstable = "may be renamed, depending on global conventions"]
pub fn unwrap(self) -> T {
debug_assert!(self.borrow.get() == UNUSED);
unsafe{self.value.unwrap()}
Expand All @@ -242,6 +248,7 @@ impl<T> RefCell<T> {
/// immutable borrows can be taken out at the same time.
///
/// Returns `None` if the value is currently mutably borrowed.
#[unstable = "may be renamed, depending on global conventions"]
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
match self.borrow.get() {
WRITING => None,
Expand All @@ -260,6 +267,7 @@ impl<T> RefCell<T> {
/// # Failure
///
/// Fails if the value is currently mutably borrowed.
#[unstable]
pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
match self.try_borrow() {
Some(ptr) => ptr,
Expand All @@ -273,6 +281,7 @@ impl<T> RefCell<T> {
/// cannot be borrowed while this borrow is active.
///
/// Returns `None` if the value is currently borrowed.
#[unstable = "may be renamed, depending on global conventions"]
pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
match self.borrow.get() {
UNUSED => {
Expand All @@ -291,6 +300,7 @@ impl<T> RefCell<T> {
/// # Failure
///
/// Fails if the value is currently borrowed.
#[unstable]
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
match self.try_borrow_mut() {
Some(ptr) => ptr,
Expand All @@ -299,27 +309,30 @@ impl<T> RefCell<T> {
}
}

#[unstable]
#[unstable = "waiting for `Clone` to become stable"]
impl<T: Clone> Clone for RefCell<T> {
fn clone(&self) -> RefCell<T> {
RefCell::new(self.borrow().clone())
}
}

#[unstable = "waiting for `PartialEq` to become stable"]
impl<T: PartialEq> PartialEq for RefCell<T> {
fn eq(&self, other: &RefCell<T>) -> bool {
*self.borrow() == *other.borrow()
}
}

/// Wraps a borrowed reference to a value in a `RefCell` box.
#[unstable]
pub struct Ref<'b, T> {
// FIXME #12808: strange name to try to avoid interfering with
// field accesses of the contained type via Deref
_parent: &'b RefCell<T>
}

#[unsafe_destructor]
#[unstable]
impl<'b, T> Drop for Ref<'b, T> {
fn drop(&mut self) {
let borrow = self._parent.borrow.get();
Expand All @@ -328,6 +341,7 @@ impl<'b, T> Drop for Ref<'b, T> {
}
}

#[unstable = "waiting for `Deref` to become stable"]
impl<'b, T> Deref<T> for Ref<'b, T> {
#[inline]
fn deref<'a>(&'a self) -> &'a T {
Expand All @@ -341,7 +355,7 @@ impl<'b, T> Deref<T> for Ref<'b, T> {
///
/// A `Clone` implementation would interfere with the widespread
/// use of `r.borrow().clone()` to clone the contents of a `RefCell`.
#[experimental]
#[experimental = "likely to be moved to a method, pending language changes"]
pub fn clone_ref<'b, T>(orig: &Ref<'b, T>) -> Ref<'b, T> {
// Since this Ref exists, we know the borrow flag
// is not set to WRITING.
Expand All @@ -355,13 +369,15 @@ pub fn clone_ref<'b, T>(orig: &Ref<'b, T>) -> Ref<'b, T> {
}

/// Wraps a mutable borrowed reference to a value in a `RefCell` box.
#[unstable]
pub struct RefMut<'b, T> {
// FIXME #12808: strange name to try to avoid interfering with
// field accesses of the contained type via Deref
_parent: &'b RefCell<T>
}

#[unsafe_destructor]
#[unstable]
impl<'b, T> Drop for RefMut<'b, T> {
fn drop(&mut self) {
let borrow = self._parent.borrow.get();
Expand All @@ -370,13 +386,15 @@ impl<'b, T> Drop for RefMut<'b, T> {
}
}

#[unstable = "waiting for `Deref` to become stable"]
impl<'b, T> Deref<T> for RefMut<'b, T> {
#[inline]
fn deref<'a>(&'a self) -> &'a T {
unsafe { &*self._parent.value.get() }
}
}

#[unstable = "waiting for `DerefMut` to become stable"]
impl<'b, T> DerefMut<T> for RefMut<'b, T> {
#[inline]
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
Expand Down
2 changes: 1 addition & 1 deletion src/librustrt/args.rs
Expand Up @@ -45,7 +45,7 @@ pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
mod imp {
use core::prelude::*;

use alloc::owned::Box;
use alloc::boxed::Box;
use collections::vec::Vec;
use core::mem;
use core::slice;
Expand Down
2 changes: 1 addition & 1 deletion src/librustrt/at_exit_imp.rs
Expand Up @@ -14,7 +14,7 @@

use core::prelude::*;

use alloc::owned::Box;
use alloc::boxed::Box;
use collections::vec::Vec;
use core::atomics;
use core::mem;
Expand Down
2 changes: 1 addition & 1 deletion src/librustrt/lib.rs
Expand Up @@ -37,7 +37,7 @@ pub use self::unwind::{begin_unwind, begin_unwind_fmt};

use core::prelude::*;

use alloc::owned::Box;
use alloc::boxed::Box;
use core::any::Any;

use task::{Task, BlockedTask, TaskOpts};
Expand Down

0 comments on commit ffd9966

Please sign in to comment.