1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Traits for dynamic typing of any type (through runtime reflection)
13 //! This module implements the `Any` trait, which enables dynamic typing
14 //! of any type, through runtime reflection.
16 //! `Any` itself can be used to get a `TypeId`, and has more features when used as a trait object.
17 //! As `&Any` (a borrowed trait object), it has the `is` and `as_ref` methods, to test if the
18 //! contained value is of a given type, and to get a reference to the inner value as a type. As
19 //! `&mut Any`, there is also the `as_mut` method, for getting a mutable reference to the inner
20 //! value. `~Any` adds the `move` method, which will unwrap a `~T` from the object. See the
21 //! extension traits (`*Ext`) for the full details.
24 use option::{Option, Some, None};
25 use result::{Result, Ok, Err};
27 use unstable::intrinsics::TypeId;
28 use unstable::intrinsics;
31 ///////////////////////////////////////////////////////////////////////////////
33 ///////////////////////////////////////////////////////////////////////////////
35 /// The `Any` trait is implemented by all types, and can be used as a trait object
36 /// for dynamic typing
38 /// Get the `TypeId` of `self`
39 fn get_type_id(&self) -> TypeId;
41 /// Get a void pointer to `self`
42 fn as_void_ptr(&self) -> *Void;
44 /// Get a mutable void pointer to `self`
45 fn as_mut_void_ptr(&mut self) -> *mut Void;
48 impl<T: 'static> Any for T {
49 /// Get the `TypeId` of `self`
50 fn get_type_id(&self) -> TypeId {
54 /// Get a void pointer to `self`
55 fn as_void_ptr(&self) -> *Void {
59 /// Get a mutable void pointer to `self`
60 fn as_mut_void_ptr(&mut self) -> *mut Void {
61 self as *mut T as *mut Void
65 ///////////////////////////////////////////////////////////////////////////////
66 // Extension methods for Any trait objects.
67 // Implemented as three extension traits so that generics work.
68 ///////////////////////////////////////////////////////////////////////////////
70 /// Extension methods for a referenced `Any` trait object
71 pub trait AnyRefExt<'a> {
72 /// Returns true if the boxed type is the same as `T`
73 fn is<T: 'static>(self) -> bool;
75 /// Returns some reference to the boxed value if it is of type `T`, or
76 /// `None` if it isn't.
77 fn as_ref<T: 'static>(self) -> Option<&'a T>;
80 impl<'a> AnyRefExt<'a> for &'a Any {
82 fn is<T: 'static>(self) -> bool {
83 // Get TypeId of the type this function is instantiated with
84 let t = TypeId::of::<T>();
86 // Get TypeId of the type in the trait object
87 let boxed = self.get_type_id();
89 // Compare both TypeIds on equality
94 fn as_ref<T: 'static>(self) -> Option<&'a T> {
96 Some(unsafe { transmute(self.as_void_ptr()) })
103 /// Extension methods for a mutable referenced `Any` trait object
104 pub trait AnyMutRefExt<'a> {
105 /// Returns some mutable reference to the boxed value if it is of type `T`, or
106 /// `None` if it isn't.
107 fn as_mut<T: 'static>(self) -> Option<&'a mut T>;
110 impl<'a> AnyMutRefExt<'a> for &'a mut Any {
112 fn as_mut<T: 'static>(self) -> Option<&'a mut T> {
114 Some(unsafe { transmute(self.as_mut_void_ptr()) })
121 /// Extension methods for a owning `Any` trait object
122 pub trait AnyOwnExt {
123 /// Returns the boxed value if it is of type `T`, or
124 /// `Err(Self)` if it isn't.
125 fn move<T: 'static>(self) -> Result<~T, Self>;
128 impl AnyOwnExt for ~Any {
130 fn move<T: 'static>(self) -> Result<~T, ~Any> {
133 // Extract the pointer to the boxed value, temporary alias with self
134 let ptr: ~T = transmute(self.as_void_ptr());
136 // Prevent destructor on self being run
137 intrinsics::forget(self);
147 ///////////////////////////////////////////////////////////////////////////////
148 // Trait implementations
149 ///////////////////////////////////////////////////////////////////////////////
151 impl ToStr for ~Any {
152 fn to_str(&self) -> ~str { ~"~Any" }
155 impl<'a> ToStr for &'a Any {
156 fn to_str(&self) -> ~str { ~"&Any" }
167 static TEST: &'static str = "Test";
170 fn any_as_void_ptr() {
171 let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
176 assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
177 assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
178 assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
180 let (a, b, c) = (@5u as @Any, @TEST as @Any, @Test as @Any);
185 assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
186 assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
187 assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
189 let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
194 assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
195 assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
196 assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
199 let mut y: &'static str = "Test";
200 let (a, b, c) = (&mut 5u as &mut Any,
207 assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
208 assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
209 assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
211 let (a, b, c) = (5u, "hello", Test);
212 let (a_r, b_r, c_r) = (&a as &Any, &b as &Any, &c as &Any);
214 assert_eq!(a.as_void_ptr(), a_r.as_void_ptr());
215 assert_eq!(b.as_void_ptr(), b_r.as_void_ptr());
216 assert_eq!(c.as_void_ptr(), c_r.as_void_ptr());
220 fn any_as_mut_void_ptr() {
221 let y: &'static str = "Test";
222 let mut a = ~5u as ~Any;
223 let mut b = ~y as ~Any;
224 let mut c = ~Test as ~Any;
226 let a_ptr = a.as_mut_void_ptr();
227 let b_ptr = b.as_mut_void_ptr();
228 let c_ptr = c.as_mut_void_ptr();
230 let a_r: &mut Any = a;
231 let b_r: &mut Any = b;
232 let c_r: &mut Any = c;
234 assert_eq!(a_ptr, a_r.as_mut_void_ptr());
235 assert_eq!(b_ptr, b_r.as_mut_void_ptr());
236 assert_eq!(c_ptr, c_r.as_mut_void_ptr());
239 let mut y: &'static str = "Test";
240 let a = &mut 5u as &mut Any;
241 let b = &mut y as &mut Any;
242 let c = &mut x as &mut Any;
244 let a_ptr = a.as_mut_void_ptr();
245 let b_ptr = b.as_mut_void_ptr();
246 let c_ptr = c.as_mut_void_ptr();
248 let a_r: &mut Any = a;
249 let b_r: &mut Any = b;
250 let c_r: &mut Any = c;
252 assert_eq!(a_ptr, a_r.as_mut_void_ptr());
253 assert_eq!(b_ptr, b_r.as_mut_void_ptr());
254 assert_eq!(c_ptr, c_r.as_mut_void_ptr());
256 let y: &'static str = "Test";
261 let a_ptr = a.as_mut_void_ptr();
262 let b_ptr = b.as_mut_void_ptr();
263 let c_ptr = c.as_mut_void_ptr();
265 let (a_r, b_r, c_r) = (&mut a as &mut Any, &mut b as &mut Any, &mut c as &mut Any);
267 assert_eq!(a_ptr, a_r.as_mut_void_ptr());
268 assert_eq!(b_ptr, b_r.as_mut_void_ptr());
269 assert_eq!(c_ptr, c_r.as_mut_void_ptr());
273 fn any_referenced() {
274 let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
276 assert!(a.is::<uint>());
277 assert!(!b.is::<uint>());
278 assert!(!c.is::<uint>());
280 assert!(!a.is::<&'static str>());
281 assert!(b.is::<&'static str>());
282 assert!(!c.is::<&'static str>());
284 assert!(!a.is::<Test>());
285 assert!(!b.is::<Test>());
286 assert!(c.is::<Test>());
291 let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
293 assert!(a.is::<uint>());
294 assert!(!b.is::<uint>());
295 assert!(!c.is::<uint>());
297 assert!(!a.is::<&'static str>());
298 assert!(b.is::<&'static str>());
299 assert!(!c.is::<&'static str>());
301 assert!(!a.is::<Test>());
302 assert!(!b.is::<Test>());
303 assert!(c.is::<Test>());
308 let (a, b, c) = (@5u as @Any, @TEST as @Any, @Test as @Any);
310 assert!(a.is::<uint>());
311 assert!(!b.is::<uint>());
312 assert!(!c.is::<uint>());
314 assert!(!a.is::<&'static str>());
315 assert!(b.is::<&'static str>());
316 assert!(!c.is::<&'static str>());
318 assert!(!a.is::<Test>());
319 assert!(!b.is::<Test>());
320 assert!(c.is::<Test>());
327 match a.as_ref::<uint>() {
329 x => fail!("Unexpected value {:?}", x)
332 match a.as_ref::<Test>() {
334 x => fail!("Unexpected value {:?}", x)
343 let a_r = &mut a as &mut Any;
344 let tmp: &mut uint = b;
345 let b_r = tmp as &mut Any;
347 match a_r.as_mut::<uint>() {
352 x => fail!("Unexpected value {:?}", x)
355 match b_r.as_mut::<uint>() {
360 x => fail!("Unexpected value {:?}", x)
363 match a_r.as_mut::<Test>() {
365 x => fail!("Unexpected value {:?}", x)
368 match b_r.as_mut::<Test>() {
370 x => fail!("Unexpected value {:?}", x)
373 match a_r.as_mut::<uint>() {
375 x => fail!("Unexpected value {:?}", x)
378 match b_r.as_mut::<uint>() {
380 x => fail!("Unexpected value {:?}", x)
387 let b = ~Test as ~Any;
389 match a.move::<uint>() {
390 Ok(a) => { assert_eq!(a, ~8u); }
393 match b.move::<Test>() {
394 Ok(a) => { assert_eq!(a, ~Test); }
399 let b = ~Test as ~Any;
401 assert!(a.move::<~Test>().is_err());
402 assert!(b.move::<~uint>().is_err());