Skip to content

Cleaned up std::any. #12667

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

Merged
merged 1 commit into from
Mar 4, 2014
Merged
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
1 change: 1 addition & 0 deletions src/libgreen/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/libgreen/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/libnative/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use middle::lint;

use d = driver::driver;

use std::any::AnyRefExt;
use std::cmp;
use std::io;
use std::os;
Expand Down
1 change: 1 addition & 0 deletions src/libserialize/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
156 changes: 39 additions & 117 deletions src/libstd/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -39,34 +40,18 @@ 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;
}

Copy link
Member

Choose a reason for hiding this comment

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

Why are these removed?

Copy link
Member Author

Choose a reason for hiding this comment

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

As explained in the PR description, they existed only to reliably get a pointer to self in a time with managed headers in some owned boxes.

Furthermore, they polluted the global namespace if you use Any, as every type suddenly gets a as_[mut_]void_ptr() method for something that should only be an implementatin detail.

Finally, their usage meant un-erasing a type from an Any trait object needing two virtual calls, instead of just one.

impl<T: 'static> Any for T {
/// Get the `TypeId` of `self`
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
Expand Down Expand Up @@ -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
}
Expand All @@ -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
}
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
});
}
}
1 change: 0 additions & 1 deletion src/libstd/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
18 changes: 17 additions & 1 deletion src/libstd/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) } }
}
Expand Down
7 changes: 7 additions & 0 deletions src/libsync/sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/test/run-fail/fail-macro-any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
// error-pattern:failed at '~Any'

fn main() {
fail!(~413 as ~Any);
fail!(~413 as ~::std::any::Any);
}
1 change: 1 addition & 0 deletions src/test/run-pass/unit-like-struct-drop-run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

// Make sure the destructor is run for unit-like structs.

use std::any::AnyOwnExt;
use std::task;

struct Foo;
Expand Down