Skip to content

Stabilization for owned (now boxed) and cell #15591

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

Closed
wants to merge 1 commit into from
Closed
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: 19 additions & 40 deletions src/liballoc/owned.rs → src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
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>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you leave the move method as a #[deprecated] default method for now?


// 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
Original file line number Diff line number Diff line change
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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also have a #[deprecated] pub use of owned to boxed (both here and in std)

pub mod arc;
pub mod rc;

Expand Down
2 changes: 1 addition & 1 deletion src/libcollections/btree.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading