mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Cleaned up std::any
- Added `TraitObject` representation to `std::raw`. - Added doc to `std::raw`. - Removed `Any::as_void_ptr()` and `Any::as_mut_void_ptr()` methods as they are uneccessary now after the removal of headers on owned boxes. This reduces the number of virtual calls needed. - Made the `..Ext` implementations work directly with the repr of a trait object. - Removed `Any`-related traits from the prelude. - Added bench for `Any`
This commit is contained in:
parent
19fadf6567
commit
3158047a45
@ -11,6 +11,7 @@
|
||||
//! A small module implementing a simple "runtime" used for bootstrapping a rust
|
||||
//! scheduler pool and then interacting with it.
|
||||
|
||||
use std::any::Any;
|
||||
use std::cast;
|
||||
use std::rt::Runtime;
|
||||
use std::rt::local::Local;
|
||||
|
@ -18,6 +18,7 @@
|
||||
//! contains the rust task itself in order to juggle around ownership of the
|
||||
//! values.
|
||||
|
||||
use std::any::Any;
|
||||
use std::cast;
|
||||
use std::rt::env;
|
||||
use std::rt::Runtime;
|
||||
|
@ -14,6 +14,7 @@
|
||||
//! by rust tasks. This implements the necessary API traits laid out by std::rt
|
||||
//! in order to spawn new tasks and deschedule the current task.
|
||||
|
||||
use std::any::Any;
|
||||
use std::cast;
|
||||
use std::rt::env;
|
||||
use std::rt::local::Local;
|
||||
|
@ -46,6 +46,7 @@ use middle::lint;
|
||||
|
||||
use d = driver::driver;
|
||||
|
||||
use std::any::AnyRefExt;
|
||||
use std::cmp;
|
||||
use std::io;
|
||||
use std::os;
|
||||
|
@ -2229,6 +2229,7 @@ mod tests {
|
||||
B(~str)
|
||||
}
|
||||
fn check_err<T: Decodable<Decoder>>(to_parse: &'static str, expected_error: &str) {
|
||||
use std::any::AnyRefExt;
|
||||
use std::task;
|
||||
let res = task::try(proc() {
|
||||
// either fails in `decode` (which is what we want), or
|
||||
|
@ -20,9 +20,10 @@
|
||||
//! value. `~Any` adds the `move` method, which will unwrap a `~T` from the object. See the
|
||||
//! extension traits (`*Ext`) for the full details.
|
||||
|
||||
use cast::transmute;
|
||||
use cast::{transmute, transmute_copy};
|
||||
use fmt;
|
||||
use option::{Option, Some, None};
|
||||
use raw::TraitObject;
|
||||
use result::{Result, Ok, Err};
|
||||
use intrinsics::TypeId;
|
||||
use intrinsics;
|
||||
@ -39,12 +40,6 @@ pub enum Void { }
|
||||
pub trait Any {
|
||||
/// Get the `TypeId` of `self`
|
||||
fn get_type_id(&self) -> TypeId;
|
||||
|
||||
/// Get a void pointer to `self`
|
||||
fn as_void_ptr(&self) -> *Void;
|
||||
|
||||
/// Get a mutable void pointer to `self`
|
||||
fn as_mut_void_ptr(&mut self) -> *mut Void;
|
||||
}
|
||||
|
||||
impl<T: 'static> Any for T {
|
||||
@ -52,21 +47,11 @@ impl<T: 'static> Any for T {
|
||||
fn get_type_id(&self) -> TypeId {
|
||||
TypeId::of::<T>()
|
||||
}
|
||||
|
||||
/// Get a void pointer to `self`
|
||||
fn as_void_ptr(&self) -> *Void {
|
||||
self as *T as *Void
|
||||
}
|
||||
|
||||
/// Get a mutable void pointer to `self`
|
||||
fn as_mut_void_ptr(&mut self) -> *mut Void {
|
||||
self as *mut T as *mut Void
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Extension methods for Any trait objects.
|
||||
// Implemented as three extension traits so that generics work.
|
||||
// Implemented as three extension traits so that the methods can be generic.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Extension methods for a referenced `Any` trait object
|
||||
@ -95,7 +80,13 @@ impl<'a> AnyRefExt<'a> for &'a Any {
|
||||
#[inline]
|
||||
fn as_ref<T: 'static>(self) -> Option<&'a T> {
|
||||
if self.is::<T>() {
|
||||
Some(unsafe { transmute(self.as_void_ptr()) })
|
||||
unsafe {
|
||||
// Get the raw representation of the trait object
|
||||
let to: TraitObject = transmute_copy(&self);
|
||||
|
||||
// Extract the data pointer
|
||||
Some(transmute(to.data))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -113,7 +104,13 @@ impl<'a> AnyMutRefExt<'a> for &'a mut Any {
|
||||
#[inline]
|
||||
fn as_mut<T: 'static>(self) -> Option<&'a mut T> {
|
||||
if self.is::<T>() {
|
||||
Some(unsafe { transmute(self.as_mut_void_ptr()) })
|
||||
unsafe {
|
||||
// Get the raw representation of the trait object
|
||||
let to: TraitObject = transmute_copy(&self);
|
||||
|
||||
// Extract the data pointer
|
||||
Some(transmute(to.data))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -132,13 +129,14 @@ impl AnyOwnExt for ~Any {
|
||||
fn move<T: 'static>(self) -> Result<~T, ~Any> {
|
||||
if self.is::<T>() {
|
||||
unsafe {
|
||||
// Extract the pointer to the boxed value, temporary alias with self
|
||||
let ptr: ~T = transmute(self.as_void_ptr());
|
||||
// Get the raw representation of the trait object
|
||||
let to: TraitObject = transmute_copy(&self);
|
||||
|
||||
// Prevent destructor on self being run
|
||||
intrinsics::forget(self);
|
||||
|
||||
Ok(ptr)
|
||||
// Extract the data pointer
|
||||
Ok(transmute(to.data))
|
||||
}
|
||||
} else {
|
||||
Err(self)
|
||||
@ -172,100 +170,6 @@ mod tests {
|
||||
|
||||
static TEST: &'static str = "Test";
|
||||
|
||||
#[test]
|
||||
fn any_as_void_ptr() {
|
||||
let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
|
||||
let a_r: &Any = a;
|
||||
let b_r: &Any = b;
|
||||
let c_r: &Any = c;
|
||||
|
||||
assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
|
||||
assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
|
||||
assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
|
||||
|
||||
let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
|
||||
let a_r: &Any = a;
|
||||
let b_r: &Any = b;
|
||||
let c_r: &Any = c;
|
||||
|
||||
assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
|
||||
assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
|
||||
assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
|
||||
|
||||
let mut x = Test;
|
||||
let mut y: &'static str = "Test";
|
||||
let (a, b, c) = (&mut 5u as &mut Any,
|
||||
&mut y as &mut Any,
|
||||
&mut x as &mut Any);
|
||||
let a_r: &Any = a;
|
||||
let b_r: &Any = b;
|
||||
let c_r: &Any = c;
|
||||
|
||||
assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
|
||||
assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
|
||||
assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
|
||||
|
||||
let (a, b, c) = (5u, "hello", Test);
|
||||
let (a_r, b_r, c_r) = (&a as &Any, &b as &Any, &c as &Any);
|
||||
|
||||
assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
|
||||
assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
|
||||
assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn any_as_mut_void_ptr() {
|
||||
let y: &'static str = "Test";
|
||||
let mut a = ~5u as ~Any;
|
||||
let mut b = ~y as ~Any;
|
||||
let mut c = ~Test as ~Any;
|
||||
|
||||
let a_ptr = a.as_mut_void_ptr();
|
||||
let b_ptr = b.as_mut_void_ptr();
|
||||
let c_ptr = c.as_mut_void_ptr();
|
||||
|
||||
let a_r: &mut Any = a;
|
||||
let b_r: &mut Any = b;
|
||||
let c_r: &mut Any = c;
|
||||
|
||||
assert_eq!(a_ptr, a_r.as_mut_void_ptr());
|
||||
assert_eq!(b_ptr, b_r.as_mut_void_ptr());
|
||||
assert_eq!(c_ptr, c_r.as_mut_void_ptr());
|
||||
|
||||
let mut x = Test;
|
||||
let mut y: &'static str = "Test";
|
||||
let a = &mut 5u as &mut Any;
|
||||
let b = &mut y as &mut Any;
|
||||
let c = &mut x as &mut Any;
|
||||
|
||||
let a_ptr = a.as_mut_void_ptr();
|
||||
let b_ptr = b.as_mut_void_ptr();
|
||||
let c_ptr = c.as_mut_void_ptr();
|
||||
|
||||
let a_r: &mut Any = a;
|
||||
let b_r: &mut Any = b;
|
||||
let c_r: &mut Any = c;
|
||||
|
||||
assert_eq!(a_ptr, a_r.as_mut_void_ptr());
|
||||
assert_eq!(b_ptr, b_r.as_mut_void_ptr());
|
||||
assert_eq!(c_ptr, c_r.as_mut_void_ptr());
|
||||
|
||||
let y: &'static str = "Test";
|
||||
let mut a = 5u;
|
||||
let mut b = y;
|
||||
let mut c = Test;
|
||||
|
||||
let a_ptr = a.as_mut_void_ptr();
|
||||
let b_ptr = b.as_mut_void_ptr();
|
||||
let c_ptr = c.as_mut_void_ptr();
|
||||
|
||||
let (a_r, b_r, c_r) = (&mut a as &mut Any, &mut b as &mut Any, &mut c as &mut Any);
|
||||
|
||||
assert_eq!(a_ptr, a_r.as_mut_void_ptr());
|
||||
assert_eq!(b_ptr, b_r.as_mut_void_ptr());
|
||||
assert_eq!(c_ptr, c_r.as_mut_void_ptr());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn any_referenced() {
|
||||
let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
|
||||
@ -395,3 +299,21 @@ mod tests {
|
||||
assert_eq!(format!("{}", b), ~"&Any");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod bench {
|
||||
extern crate test;
|
||||
|
||||
use any::{Any, AnyRefExt};
|
||||
use option::Some;
|
||||
use self::test::BenchHarness;
|
||||
|
||||
#[bench]
|
||||
fn bench_as_ref(bh: &mut BenchHarness) {
|
||||
bh.iter(|| {
|
||||
let mut x = 0; let mut y = &mut x as &mut Any;
|
||||
test::black_box(&mut y);
|
||||
test::black_box(y.as_ref::<int>() == Some(&0));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ pub use mem::drop;
|
||||
|
||||
// Reexported types and traits
|
||||
|
||||
pub use any::{Any, AnyOwnExt, AnyRefExt, AnyMutRefExt};
|
||||
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, IntoBytes};
|
||||
pub use c_str::ToCStr;
|
||||
pub use char::Char;
|
||||
|
@ -10,6 +10,13 @@
|
||||
|
||||
#[allow(missing_doc)];
|
||||
|
||||
//! Contains struct definitions for the layout of compiler built-in types.
|
||||
//!
|
||||
//! They can be used as targets of transmutes in unsafe code for manipulating
|
||||
//! the raw representations directly.
|
||||
//!
|
||||
//! Their definitition should always match the ABI defined in `rustc::back::abi`.
|
||||
|
||||
use cast;
|
||||
|
||||
/// The representation of a Rust managed box
|
||||
@ -49,13 +56,22 @@ pub struct Procedure {
|
||||
env: *(),
|
||||
}
|
||||
|
||||
/// The representation of a Rust trait object.
|
||||
///
|
||||
/// This struct does not have a `Repr` implementation
|
||||
/// because there is no way to refer to all trait objects generically.
|
||||
pub struct TraitObject {
|
||||
vtable: *(),
|
||||
data: *(),
|
||||
}
|
||||
|
||||
/// This trait is meant to map equivalences between raw structs and their
|
||||
/// corresponding rust values.
|
||||
pub trait Repr<T> {
|
||||
/// This function "unwraps" a rust value (without consuming it) into its raw
|
||||
/// struct representation. This can be used to read/write different values
|
||||
/// for the struct. This is a safe method because by default it does not
|
||||
/// give write-access to the struct returned.
|
||||
/// enable write-access to the fields of the return value in safe code.
|
||||
#[inline]
|
||||
fn repr(&self) -> T { unsafe { cast::transmute_copy(self) } }
|
||||
}
|
||||
|
@ -976,6 +976,8 @@ mod tests {
|
||||
}
|
||||
#[test]
|
||||
fn test_mutex_killed_simple() {
|
||||
use std::any::Any;
|
||||
|
||||
// Mutex must get automatically unlocked if failed/killed within.
|
||||
let m = Mutex::new();
|
||||
let m2 = m.clone();
|
||||
@ -992,6 +994,8 @@ mod tests {
|
||||
#[ignore(reason = "linked failure")]
|
||||
#[test]
|
||||
fn test_mutex_killed_cond() {
|
||||
use std::any::Any;
|
||||
|
||||
// Getting killed during cond wait must not corrupt the mutex while
|
||||
// unwinding (e.g. double unlock).
|
||||
let m = Mutex::new();
|
||||
@ -1019,6 +1023,7 @@ mod tests {
|
||||
#[ignore(reason = "linked failure")]
|
||||
#[test]
|
||||
fn test_mutex_killed_broadcast() {
|
||||
use std::any::Any;
|
||||
use std::unstable::finally::Finally;
|
||||
|
||||
let m = Mutex::new();
|
||||
@ -1329,6 +1334,8 @@ mod tests {
|
||||
}
|
||||
#[cfg(test)]
|
||||
fn rwlock_kill_helper(mode1: RWLockMode, mode2: RWLockMode) {
|
||||
use std::any::Any;
|
||||
|
||||
// Mutex must get automatically unlocked if failed/killed within.
|
||||
let x = RWLock::new();
|
||||
let x2 = x.clone();
|
||||
|
@ -11,5 +11,5 @@
|
||||
// error-pattern:failed at '~Any'
|
||||
|
||||
fn main() {
|
||||
fail!(~413 as ~Any);
|
||||
fail!(~413 as ~::std::any::Any);
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
// Make sure the destructor is run for unit-like structs.
|
||||
|
||||
use std::any::AnyOwnExt;
|
||||
use std::task;
|
||||
|
||||
struct Foo;
|
||||
|
Loading…
Reference in New Issue
Block a user