From 8dae0a1a4c0a288dd4762f959c842351f7b2f3da Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 13 May 2014 14:58:29 -0700 Subject: [PATCH] std: Move the owned module from core to std The compiler was updated to recognize that implementations for ty_uniq(..) are allowed if the Box lang item is located in the current crate. This enforces the idea that libcore cannot allocated, and moves all related trait implementations from libcore to libstd. This is a breaking change in that the AnyOwnExt trait has moved from the any module to the owned module. Any previous users of std::any::AnyOwnExt should now use std::owned::AnyOwnExt instead. This was done because the trait is intended for Box traits and only Box traits. [breaking-change] --- src/libcore/any.rs | 34 +----- src/libcore/clone.rs | 30 +++--- src/libcore/cmp.rs | 24 ----- src/libcore/default.rs | 6 -- src/libcore/iter.rs | 2 +- src/libcore/lib.rs | 5 +- src/libcore/mem.rs | 2 +- src/libcore/owned.rs | 85 +++++++++++++-- src/librustc/middle/typeck/coherence.rs | 17 ++- src/libstd/lib.rs | 8 +- src/libstd/owned.rs | 101 ++++++++++++++++++ src/libstd/rt/task.rs | 3 +- src/libstd/task.rs | 5 +- .../run-pass/unit-like-struct-drop-run.rs | 2 +- 14 files changed, 219 insertions(+), 105 deletions(-) create mode 100644 src/libstd/owned.rs diff --git a/src/libcore/any.rs b/src/libcore/any.rs index b0227fd60bfeb..70cd46dcfa2b4 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -22,11 +22,8 @@ use mem::{transmute, transmute_copy}; use option::{Option, Some, None}; -use owned::Box; use raw::TraitObject; -use result::{Result, Ok, Err}; use intrinsics::TypeId; -use intrinsics; /// A type with no inhabitants pub enum Void { } @@ -117,38 +114,11 @@ impl<'a> AnyMutRefExt<'a> for &'a mut Any { } } -/// Extension methods for an owning `Any` trait object -pub trait AnyOwnExt { - /// Returns the boxed value if it is of type `T`, or - /// `Err(Self)` if it isn't. - fn move(self) -> Result, Self>; -} - -impl AnyOwnExt for Box { - #[inline] - fn move(self) -> Result, Box> { - if self.is::() { - unsafe { - // Get the raw representation of the trait object - let to: TraitObject = transmute_copy(&self); - - // Prevent destructor on self being run - intrinsics::forget(self); - - // Extract the data pointer - Ok(transmute(to.data)) - } - } else { - Err(self) - } - } -} - #[cfg(test)] mod tests { use prelude::*; use super::*; - use owned::Box; + use realstd::owned::{Box, AnyOwnExt}; use realstd::str::StrAllocating; #[deriving(Eq, Show)] @@ -253,6 +223,8 @@ mod tests { #[test] fn any_move() { + use realstd::any::Any; + use realstd::result::{Ok, Err}; let a = box 8u as Box; let b = box Test as Box; diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 06cbaf1981280..cd66beabc12de 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -21,8 +21,6 @@ the `clone` method. */ -use owned::Box; - /// A common trait for cloning an object. pub trait Clone { /// Returns a copy of the value. The contents of owned pointers @@ -41,18 +39,6 @@ pub trait Clone { } } -impl Clone for Box { - /// Return a copy of the owned box. - #[inline] - fn clone(&self) -> Box { box {(**self).clone()} } - - /// Perform copy-assignment from `source` by reusing the existing allocation. - #[inline] - fn clone_from(&mut self, source: &Box) { - (**self).clone_from(&(**source)); - } -} - impl Clone for @T { /// Return a shallow copy of the managed box. #[inline] @@ -129,12 +115,22 @@ extern_fn_clone!(A, B, C, D, E, F, G, H) #[cfg(test)] mod test { use prelude::*; - use owned::Box; + use realstd::owned::Box; + + fn realclone(t: &T) -> T { + use realstd::clone::Clone; + t.clone() + } + + fn realclone_from(t1: &mut T, t2: &T) { + use realstd::clone::Clone; + t1.clone_from(t2) + } #[test] fn test_owned_clone() { let a = box 5i; - let b: Box = a.clone(); + let b: Box = realclone(&a); assert_eq!(a, b); } @@ -157,7 +153,7 @@ mod test { fn test_clone_from() { let a = box 5; let mut b = box 10; - b.clone_from(&a); + realclone_from(&mut b, &a); assert_eq!(*b, 5); } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index af611cd94e506..f2b1c1cd4cde6 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -193,7 +193,6 @@ pub fn max(v1: T, v2: T) -> T { #[cfg(not(test))] mod impls { use cmp::{Ord, TotalOrd, Eq, TotalEq, Ordering}; - use owned::Box; // & pointers impl<'a, T: Eq> Eq for &'a T { @@ -240,29 +239,6 @@ mod impls { fn cmp(&self, other: &@T) -> Ordering { (**self).cmp(*other) } } impl TotalEq for @T {} - - // box pointers - impl Eq for Box { - #[inline] - fn eq(&self, other: &Box) -> bool { *(*self) == *(*other) } - #[inline] - fn ne(&self, other: &Box) -> bool { *(*self) != *(*other) } - } - impl Ord for Box { - #[inline] - fn lt(&self, other: &Box) -> bool { *(*self) < *(*other) } - #[inline] - fn le(&self, other: &Box) -> bool { *(*self) <= *(*other) } - #[inline] - fn ge(&self, other: &Box) -> bool { *(*self) >= *(*other) } - #[inline] - fn gt(&self, other: &Box) -> bool { *(*self) > *(*other) } - } - impl TotalOrd for Box { - #[inline] - fn cmp(&self, other: &Box) -> Ordering { (**self).cmp(*other) } - } - impl TotalEq for Box {} } #[cfg(test)] diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 9cf3a76364887..af65fcc5a779d 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -10,8 +10,6 @@ //! The `Default` trait for types which may have meaningful default values -use owned::Box; - /// A trait that types which have a useful default value should implement. pub trait Default { /// Return the "default value" for a type. @@ -21,7 +19,3 @@ pub trait Default { impl Default for @T { fn default() -> @T { @Default::default() } } - -impl Default for Box { - fn default() -> Box { box Default::default() } -} diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 10ae30cf39d0c..f6a77d6decae0 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -2334,7 +2334,7 @@ mod tests { use realstd::num; use cmp; - use owned::Box; + use realstd::owned::Box; use uint; #[test] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 06bd46fe9ad97..97b086a093d2a 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -30,7 +30,6 @@ #[cfg(test)] pub use cmp = realcore::cmp; #[cfg(test)] pub use kinds = realcore::kinds; #[cfg(test)] pub use ops = realcore::ops; -#[cfg(test)] pub use owned = realcore::owned; #[cfg(test)] pub use ty = realcore::ty; #[cfg(not(test))] @@ -73,7 +72,6 @@ pub mod ptr; #[cfg(not(test))] pub mod ops; #[cfg(not(test))] pub mod ty; #[cfg(not(test))] pub mod cmp; -#[cfg(not(test))] pub mod owned; pub mod clone; pub mod default; pub mod container; @@ -95,6 +93,9 @@ pub mod slice; pub mod str; pub mod tuple; +#[cfg(stage0, not(test))] +pub mod owned; + mod failure; // FIXME: this module should not exist. Once owned allocations are no longer a diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index feb66f569645b..c5c6d75177728 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -380,7 +380,7 @@ mod tests { use mem::*; use option::{Some,None}; use realstd::str::StrAllocating; - use owned::Box; + use realstd::owned::Box; use raw; #[test] diff --git a/src/libcore/owned.rs b/src/libcore/owned.rs index d5cdd9c39b67c..3af12c5154c29 100644 --- a/src/libcore/owned.rs +++ b/src/libcore/owned.rs @@ -10,10 +10,14 @@ //! Operations on unique pointer types -// FIXME: this module should not exist in libcore. It must currently because the -// Box implementation is quite ad-hoc in the compiler. Once there is -// proper support in the compiler this type will be able to be defined in -// its own module. +use any::{Any, AnyRefExt}; +use clone::Clone; +use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering}; +use default::Default; +use intrinsics; +use mem; +use raw::TraitObject; +use result::{Ok, Err, Result}; /// A value that represents the global exchange heap. This is the default /// place that the `box` keyword allocates into when no place is supplied. @@ -23,16 +27,75 @@ /// let foo = box(HEAP) Bar::new(...); /// let foo = box Bar::new(...); #[lang="exchange_heap"] -#[cfg(not(test))] -pub static HEAP: () = (); - -#[cfg(test)] pub static HEAP: () = (); /// A type that represents a uniquely-owned value. #[lang="owned_box"] -#[cfg(not(test))] pub struct Box(*T); -#[cfg(test)] -pub struct Box(*T); +impl Default for Box { + fn default() -> Box { box Default::default() } +} + +impl Clone for Box { + /// Return a copy of the owned box. + #[inline] + fn clone(&self) -> Box { box {(**self).clone()} } + + /// Perform copy-assignment from `source` by reusing the existing allocation. + #[inline] + fn clone_from(&mut self, source: &Box) { + (**self).clone_from(&(**source)); + } +} + +// box pointers +impl Eq for Box { + #[inline] + fn eq(&self, other: &Box) -> bool { *(*self) == *(*other) } + #[inline] + fn ne(&self, other: &Box) -> bool { *(*self) != *(*other) } +} +impl Ord for Box { + #[inline] + fn lt(&self, other: &Box) -> bool { *(*self) < *(*other) } + #[inline] + fn le(&self, other: &Box) -> bool { *(*self) <= *(*other) } + #[inline] + fn ge(&self, other: &Box) -> bool { *(*self) >= *(*other) } + #[inline] + fn gt(&self, other: &Box) -> bool { *(*self) > *(*other) } +} +impl TotalOrd for Box { + #[inline] + fn cmp(&self, other: &Box) -> Ordering { (**self).cmp(*other) } +} +impl TotalEq for Box {} + +/// Extension methods for an owning `Any` trait object +pub trait AnyOwnExt { + /// Returns the boxed value if it is of type `T`, or + /// `Err(Self)` if it isn't. + fn move(self) -> Result, Self>; +} + +impl AnyOwnExt for Box { + #[inline] + fn move(self) -> Result, Box> { + if self.is::() { + unsafe { + // Get the raw representation of the trait object + let to: TraitObject = + *mem::transmute::<&Box, &TraitObject>(&self); + + // Prevent destructor on self being run + intrinsics::forget(self); + + // Extract the data pointer + Ok(mem::transmute(to.data)) + } + } else { + Err(self) + } + } +} diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index f93eb4550a94a..f853b0dbad40f 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -90,7 +90,7 @@ fn get_base_type(inference_context: &InferCtxt, } } -fn type_is_defined_in_local_crate(original_type: t) -> bool { +fn type_is_defined_in_local_crate(tcx: &ty::ctxt, original_type: t) -> bool { /*! * * For coherence, when we have `impl Trait for Type`, we need to @@ -109,6 +109,14 @@ fn type_is_defined_in_local_crate(original_type: t) -> bool { found_nominal = true; } } + ty_uniq(..) => { + match tcx.lang_items.owned_box() { + Some(did) if did.krate == ast::LOCAL_CRATE => { + found_nominal = true; + } + _ => {} + } + } _ => { } } @@ -194,11 +202,10 @@ impl<'a> visit::Visitor<()> for PrivilegedScopeVisitor<'a> { } } ItemImpl(_, Some(ref trait_ref), _, _) => { + let tcx = self.cc.crate_context.tcx; // `for_ty` is `Type` in `impl Trait for Type` - let for_ty = - ty::node_id_to_type(self.cc.crate_context.tcx, - item.id); - if !type_is_defined_in_local_crate(for_ty) { + let for_ty = ty::node_id_to_type(tcx, item.id); + if !type_is_defined_in_local_crate(tcx, for_ty) { // This implementation is not in scope of its base // type. This still might be OK if the trait is // defined in the same crate. diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 34ed7933c397f..a37f9a516fdb9 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -133,14 +133,16 @@ extern crate core; #[cfg(test)] pub use ops = realstd::ops; #[cfg(test)] pub use cmp = realstd::cmp; #[cfg(test)] pub use ty = realstd::ty; -#[cfg(test)] pub use owned = realstd::owned; +#[cfg(not(stage0), test)] pub use owned = realstd::owned; #[cfg(not(test))] pub use cmp = core::cmp; #[cfg(not(test))] pub use kinds = core::kinds; #[cfg(not(test))] pub use ops = core::ops; -#[cfg(not(test))] pub use owned = core::owned; #[cfg(not(test))] pub use ty = core::ty; +#[cfg(stage0, test)] pub use owned = realstd::owned; +#[cfg(stage0, not(test))] pub use owned = core::owned; + pub use core::any; pub use core::bool; pub use core::cell; @@ -207,6 +209,8 @@ pub mod ascii; pub mod rc; pub mod gc; +#[cfg(not(stage0), not(test))] +pub mod owned; /* Common traits */ diff --git a/src/libstd/owned.rs b/src/libstd/owned.rs new file mode 100644 index 0000000000000..3af12c5154c29 --- /dev/null +++ b/src/libstd/owned.rs @@ -0,0 +1,101 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations on unique pointer types + +use any::{Any, AnyRefExt}; +use clone::Clone; +use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering}; +use default::Default; +use intrinsics; +use mem; +use raw::TraitObject; +use result::{Ok, Err, Result}; + +/// A value that represents the global exchange heap. This is the default +/// place that the `box` keyword allocates into when no place is supplied. +/// +/// The following two examples are equivalent: +/// +/// let foo = box(HEAP) Bar::new(...); +/// let foo = box Bar::new(...); +#[lang="exchange_heap"] +pub static HEAP: () = (); + +/// A type that represents a uniquely-owned value. +#[lang="owned_box"] +pub struct Box(*T); + +impl Default for Box { + fn default() -> Box { box Default::default() } +} + +impl Clone for Box { + /// Return a copy of the owned box. + #[inline] + fn clone(&self) -> Box { box {(**self).clone()} } + + /// Perform copy-assignment from `source` by reusing the existing allocation. + #[inline] + fn clone_from(&mut self, source: &Box) { + (**self).clone_from(&(**source)); + } +} + +// box pointers +impl Eq for Box { + #[inline] + fn eq(&self, other: &Box) -> bool { *(*self) == *(*other) } + #[inline] + fn ne(&self, other: &Box) -> bool { *(*self) != *(*other) } +} +impl Ord for Box { + #[inline] + fn lt(&self, other: &Box) -> bool { *(*self) < *(*other) } + #[inline] + fn le(&self, other: &Box) -> bool { *(*self) <= *(*other) } + #[inline] + fn ge(&self, other: &Box) -> bool { *(*self) >= *(*other) } + #[inline] + fn gt(&self, other: &Box) -> bool { *(*self) > *(*other) } +} +impl TotalOrd for Box { + #[inline] + fn cmp(&self, other: &Box) -> Ordering { (**self).cmp(*other) } +} +impl TotalEq for Box {} + +/// Extension methods for an owning `Any` trait object +pub trait AnyOwnExt { + /// Returns the boxed value if it is of type `T`, or + /// `Err(Self)` if it isn't. + fn move(self) -> Result, Self>; +} + +impl AnyOwnExt for Box { + #[inline] + fn move(self) -> Result, Box> { + if self.is::() { + unsafe { + // Get the raw representation of the trait object + let to: TraitObject = + *mem::transmute::<&Box, &TraitObject>(&self); + + // Prevent destructor on self being run + intrinsics::forget(self); + + // Extract the data pointer + Ok(mem::transmute(to.data)) + } + } else { + Err(self) + } + } +} diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index cd0445056b290..31a2014530607 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -13,7 +13,6 @@ //! local storage, and logging. Even a 'freestanding' Rust would likely want //! to implement this. -use any::AnyOwnExt; use cleanup; use clone::Clone; use comm::Sender; @@ -24,7 +23,7 @@ use local_data; use mem; use ops::Drop; use option::{Option, Some, None}; -use owned::Box; +use owned::{AnyOwnExt, Box}; use prelude::drop; use result::{Result, Ok, Err}; use rt::Runtime; diff --git a/src/libstd/task.rs b/src/libstd/task.rs index 2f7b31ae31d98..7fb61c29112de 100644 --- a/src/libstd/task.rs +++ b/src/libstd/task.rs @@ -47,10 +47,11 @@ use rt::local::Local; use rt::task::Task; use str::{Str, SendStr, IntoMaybeOwned}; -#[cfg(test)] use any::{AnyOwnExt, AnyRefExt}; +#[cfg(test)] use any::AnyRefExt; +#[cfg(test)] use owned::AnyOwnExt; +#[cfg(test)] use realstd::result::ResultUnwrap; #[cfg(test)] use result; #[cfg(test)] use str::StrAllocating; -#[cfg(test)] use realstd::result::ResultUnwrap; /// Indicates the manner in which a task exited. /// diff --git a/src/test/run-pass/unit-like-struct-drop-run.rs b/src/test/run-pass/unit-like-struct-drop-run.rs index 29dbe35752aa1..ae4623c6e66eb 100644 --- a/src/test/run-pass/unit-like-struct-drop-run.rs +++ b/src/test/run-pass/unit-like-struct-drop-run.rs @@ -10,7 +10,7 @@ // Make sure the destructor is run for unit-like structs. -use std::any::AnyOwnExt; +use std::owned::AnyOwnExt; use std::task; struct Foo;