Skip to content

Commit 0a5138c

Browse files
committed
auto merge of #12667 : Kimundi/rust/any_improv, r=cmr
- 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 from 2 to 1. - Made the `..Ext` implementations work directly with the repr of a trait object. - Removed `Any`-related traits from the prelude. - Added bench. Bench before/after: ~~~ 7 ns/iter (+/- 0) 4 ns/iter (+/- 0) ~~~
2 parents a15448c + 3158047 commit 0a5138c

File tree

11 files changed

+70
-120
lines changed

11 files changed

+70
-120
lines changed

src/libgreen/simple.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! A small module implementing a simple "runtime" used for bootstrapping a rust
1212
//! scheduler pool and then interacting with it.
1313
14+
use std::any::Any;
1415
use std::cast;
1516
use std::rt::Runtime;
1617
use std::rt::local::Local;

src/libgreen/task.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
//! contains the rust task itself in order to juggle around ownership of the
1919
//! values.
2020
21+
use std::any::Any;
2122
use std::cast;
2223
use std::rt::env;
2324
use std::rt::Runtime;

src/libnative/task.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
//! by rust tasks. This implements the necessary API traits laid out by std::rt
1515
//! in order to spawn new tasks and deschedule the current task.
1616
17+
use std::any::Any;
1718
use std::cast;
1819
use std::rt::env;
1920
use std::rt::local::Local;

src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use middle::lint;
4646

4747
use d = driver::driver;
4848

49+
use std::any::AnyRefExt;
4950
use std::cmp;
5051
use std::io;
5152
use std::os;

src/libserialize/json.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2229,6 +2229,7 @@ mod tests {
22292229
B(~str)
22302230
}
22312231
fn check_err<T: Decodable<Decoder>>(to_parse: &'static str, expected_error: &str) {
2232+
use std::any::AnyRefExt;
22322233
use std::task;
22332234
let res = task::try(proc() {
22342235
// either fails in `decode` (which is what we want), or

src/libstd/any.rs

+39-117
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@
2020
//! value. `~Any` adds the `move` method, which will unwrap a `~T` from the object. See the
2121
//! extension traits (`*Ext`) for the full details.
2222
23-
use cast::transmute;
23+
use cast::{transmute, transmute_copy};
2424
use fmt;
2525
use option::{Option, Some, None};
26+
use raw::TraitObject;
2627
use result::{Result, Ok, Err};
2728
use intrinsics::TypeId;
2829
use intrinsics;
@@ -39,34 +40,18 @@ pub enum Void { }
3940
pub trait Any {
4041
/// Get the `TypeId` of `self`
4142
fn get_type_id(&self) -> TypeId;
42-
43-
/// Get a void pointer to `self`
44-
fn as_void_ptr(&self) -> *Void;
45-
46-
/// Get a mutable void pointer to `self`
47-
fn as_mut_void_ptr(&mut self) -> *mut Void;
4843
}
4944

5045
impl<T: 'static> Any for T {
5146
/// Get the `TypeId` of `self`
5247
fn get_type_id(&self) -> TypeId {
5348
TypeId::of::<T>()
5449
}
55-
56-
/// Get a void pointer to `self`
57-
fn as_void_ptr(&self) -> *Void {
58-
self as *T as *Void
59-
}
60-
61-
/// Get a mutable void pointer to `self`
62-
fn as_mut_void_ptr(&mut self) -> *mut Void {
63-
self as *mut T as *mut Void
64-
}
6550
}
6651

6752
///////////////////////////////////////////////////////////////////////////////
6853
// Extension methods for Any trait objects.
69-
// Implemented as three extension traits so that generics work.
54+
// Implemented as three extension traits so that the methods can be generic.
7055
///////////////////////////////////////////////////////////////////////////////
7156

7257
/// Extension methods for a referenced `Any` trait object
@@ -95,7 +80,13 @@ impl<'a> AnyRefExt<'a> for &'a Any {
9580
#[inline]
9681
fn as_ref<T: 'static>(self) -> Option<&'a T> {
9782
if self.is::<T>() {
98-
Some(unsafe { transmute(self.as_void_ptr()) })
83+
unsafe {
84+
// Get the raw representation of the trait object
85+
let to: TraitObject = transmute_copy(&self);
86+
87+
// Extract the data pointer
88+
Some(transmute(to.data))
89+
}
9990
} else {
10091
None
10192
}
@@ -113,7 +104,13 @@ impl<'a> AnyMutRefExt<'a> for &'a mut Any {
113104
#[inline]
114105
fn as_mut<T: 'static>(self) -> Option<&'a mut T> {
115106
if self.is::<T>() {
116-
Some(unsafe { transmute(self.as_mut_void_ptr()) })
107+
unsafe {
108+
// Get the raw representation of the trait object
109+
let to: TraitObject = transmute_copy(&self);
110+
111+
// Extract the data pointer
112+
Some(transmute(to.data))
113+
}
117114
} else {
118115
None
119116
}
@@ -132,13 +129,14 @@ impl AnyOwnExt for ~Any {
132129
fn move<T: 'static>(self) -> Result<~T, ~Any> {
133130
if self.is::<T>() {
134131
unsafe {
135-
// Extract the pointer to the boxed value, temporary alias with self
136-
let ptr: ~T = transmute(self.as_void_ptr());
132+
// Get the raw representation of the trait object
133+
let to: TraitObject = transmute_copy(&self);
137134

138135
// Prevent destructor on self being run
139136
intrinsics::forget(self);
140137

141-
Ok(ptr)
138+
// Extract the data pointer
139+
Ok(transmute(to.data))
142140
}
143141
} else {
144142
Err(self)
@@ -172,100 +170,6 @@ mod tests {
172170

173171
static TEST: &'static str = "Test";
174172

175-
#[test]
176-
fn any_as_void_ptr() {
177-
let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
178-
let a_r: &Any = a;
179-
let b_r: &Any = b;
180-
let c_r: &Any = c;
181-
182-
assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
183-
assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
184-
assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
185-
186-
let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
187-
let a_r: &Any = a;
188-
let b_r: &Any = b;
189-
let c_r: &Any = c;
190-
191-
assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
192-
assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
193-
assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
194-
195-
let mut x = Test;
196-
let mut y: &'static str = "Test";
197-
let (a, b, c) = (&mut 5u as &mut Any,
198-
&mut y as &mut Any,
199-
&mut x as &mut Any);
200-
let a_r: &Any = a;
201-
let b_r: &Any = b;
202-
let c_r: &Any = c;
203-
204-
assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
205-
assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
206-
assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
207-
208-
let (a, b, c) = (5u, "hello", Test);
209-
let (a_r, b_r, c_r) = (&a as &Any, &b as &Any, &c as &Any);
210-
211-
assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
212-
assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
213-
assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
214-
}
215-
216-
#[test]
217-
fn any_as_mut_void_ptr() {
218-
let y: &'static str = "Test";
219-
let mut a = ~5u as ~Any;
220-
let mut b = ~y as ~Any;
221-
let mut c = ~Test as ~Any;
222-
223-
let a_ptr = a.as_mut_void_ptr();
224-
let b_ptr = b.as_mut_void_ptr();
225-
let c_ptr = c.as_mut_void_ptr();
226-
227-
let a_r: &mut Any = a;
228-
let b_r: &mut Any = b;
229-
let c_r: &mut Any = c;
230-
231-
assert_eq!(a_ptr, a_r.as_mut_void_ptr());
232-
assert_eq!(b_ptr, b_r.as_mut_void_ptr());
233-
assert_eq!(c_ptr, c_r.as_mut_void_ptr());
234-
235-
let mut x = Test;
236-
let mut y: &'static str = "Test";
237-
let a = &mut 5u as &mut Any;
238-
let b = &mut y as &mut Any;
239-
let c = &mut x as &mut Any;
240-
241-
let a_ptr = a.as_mut_void_ptr();
242-
let b_ptr = b.as_mut_void_ptr();
243-
let c_ptr = c.as_mut_void_ptr();
244-
245-
let a_r: &mut Any = a;
246-
let b_r: &mut Any = b;
247-
let c_r: &mut Any = c;
248-
249-
assert_eq!(a_ptr, a_r.as_mut_void_ptr());
250-
assert_eq!(b_ptr, b_r.as_mut_void_ptr());
251-
assert_eq!(c_ptr, c_r.as_mut_void_ptr());
252-
253-
let y: &'static str = "Test";
254-
let mut a = 5u;
255-
let mut b = y;
256-
let mut c = Test;
257-
258-
let a_ptr = a.as_mut_void_ptr();
259-
let b_ptr = b.as_mut_void_ptr();
260-
let c_ptr = c.as_mut_void_ptr();
261-
262-
let (a_r, b_r, c_r) = (&mut a as &mut Any, &mut b as &mut Any, &mut c as &mut Any);
263-
264-
assert_eq!(a_ptr, a_r.as_mut_void_ptr());
265-
assert_eq!(b_ptr, b_r.as_mut_void_ptr());
266-
assert_eq!(c_ptr, c_r.as_mut_void_ptr());
267-
}
268-
269173
#[test]
270174
fn any_referenced() {
271175
let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
@@ -395,3 +299,21 @@ mod tests {
395299
assert_eq!(format!("{}", b), ~"&Any");
396300
}
397301
}
302+
303+
#[cfg(test)]
304+
mod bench {
305+
extern crate test;
306+
307+
use any::{Any, AnyRefExt};
308+
use option::Some;
309+
use self::test::BenchHarness;
310+
311+
#[bench]
312+
fn bench_as_ref(bh: &mut BenchHarness) {
313+
bh.iter(|| {
314+
let mut x = 0; let mut y = &mut x as &mut Any;
315+
test::black_box(&mut y);
316+
test::black_box(y.as_ref::<int>() == Some(&0));
317+
});
318+
}
319+
}

src/libstd/prelude.rs

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ pub use mem::drop;
3535

3636
// Reexported types and traits
3737

38-
pub use any::{Any, AnyOwnExt, AnyRefExt, AnyMutRefExt};
3938
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, IntoBytes};
4039
pub use c_str::ToCStr;
4140
pub use char::Char;

src/libstd/raw.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010

1111
#[allow(missing_doc)];
1212

13+
//! Contains struct definitions for the layout of compiler built-in types.
14+
//!
15+
//! They can be used as targets of transmutes in unsafe code for manipulating
16+
//! the raw representations directly.
17+
//!
18+
//! Their definitition should always match the ABI defined in `rustc::back::abi`.
19+
1320
use cast;
1421

1522
/// The representation of a Rust managed box
@@ -49,13 +56,22 @@ pub struct Procedure {
4956
env: *(),
5057
}
5158

59+
/// The representation of a Rust trait object.
60+
///
61+
/// This struct does not have a `Repr` implementation
62+
/// because there is no way to refer to all trait objects generically.
63+
pub struct TraitObject {
64+
vtable: *(),
65+
data: *(),
66+
}
67+
5268
/// This trait is meant to map equivalences between raw structs and their
5369
/// corresponding rust values.
5470
pub trait Repr<T> {
5571
/// This function "unwraps" a rust value (without consuming it) into its raw
5672
/// struct representation. This can be used to read/write different values
5773
/// for the struct. This is a safe method because by default it does not
58-
/// give write-access to the struct returned.
74+
/// enable write-access to the fields of the return value in safe code.
5975
#[inline]
6076
fn repr(&self) -> T { unsafe { cast::transmute_copy(self) } }
6177
}

src/libsync/sync/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,8 @@ mod tests {
976976
}
977977
#[test]
978978
fn test_mutex_killed_simple() {
979+
use std::any::Any;
980+
979981
// Mutex must get automatically unlocked if failed/killed within.
980982
let m = Mutex::new();
981983
let m2 = m.clone();
@@ -992,6 +994,8 @@ mod tests {
992994
#[ignore(reason = "linked failure")]
993995
#[test]
994996
fn test_mutex_killed_cond() {
997+
use std::any::Any;
998+
995999
// Getting killed during cond wait must not corrupt the mutex while
9961000
// unwinding (e.g. double unlock).
9971001
let m = Mutex::new();
@@ -1019,6 +1023,7 @@ mod tests {
10191023
#[ignore(reason = "linked failure")]
10201024
#[test]
10211025
fn test_mutex_killed_broadcast() {
1026+
use std::any::Any;
10221027
use std::unstable::finally::Finally;
10231028

10241029
let m = Mutex::new();
@@ -1329,6 +1334,8 @@ mod tests {
13291334
}
13301335
#[cfg(test)]
13311336
fn rwlock_kill_helper(mode1: RWLockMode, mode2: RWLockMode) {
1337+
use std::any::Any;
1338+
13321339
// Mutex must get automatically unlocked if failed/killed within.
13331340
let x = RWLock::new();
13341341
let x2 = x.clone();

src/test/run-fail/fail-macro-any.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
// error-pattern:failed at '~Any'
1212

1313
fn main() {
14-
fail!(~413 as ~Any);
14+
fail!(~413 as ~::std::any::Any);
1515
}

src/test/run-pass/unit-like-struct-drop-run.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

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

13+
use std::any::AnyOwnExt;
1314
use std::task;
1415

1516
struct Foo;

0 commit comments

Comments
 (0)