1 // Copyright 2013-2014 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.
23 use cast::{transmute, transmute_copy};
25 use option::{Option, Some, None};
27 use result::{Result, Ok, Err};
28 use intrinsics::TypeId;
31 /// A type with no inhabitants
34 ///////////////////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////////////////
38 /// The `Any` trait is implemented by all types, and can be used as a trait object
39 /// for dynamic typing
41 /// Get the `TypeId` of `self`
42 fn get_type_id(&self) -> TypeId;
45 impl<T: 'static> Any for T {
46 /// Get the `TypeId` of `self`
47 fn get_type_id(&self) -> TypeId {
52 ///////////////////////////////////////////////////////////////////////////////
53 // Extension methods for Any trait objects.
54 // Implemented as three extension traits so that the methods can be generic.
55 ///////////////////////////////////////////////////////////////////////////////
57 /// Extension methods for a referenced `Any` trait object
58 pub trait AnyRefExt<'a> {
59 /// Returns true if the boxed type is the same as `T`
60 fn is<T: 'static>(self) -> bool;
62 /// Returns some reference to the boxed value if it is of type `T`, or
63 /// `None` if it isn't.
64 fn as_ref<T: 'static>(self) -> Option<&'a T>;
67 impl<'a> AnyRefExt<'a> for &'a Any {
69 fn is<T: 'static>(self) -> bool {
70 // Get TypeId of the type this function is instantiated with
71 let t = TypeId::of::<T>();
73 // Get TypeId of the type in the trait object
74 let boxed = self.get_type_id();
76 // Compare both TypeIds on equality
81 fn as_ref<T: 'static>(self) -> Option<&'a T> {
84 // Get the raw representation of the trait object
85 let to: TraitObject = transmute_copy(&self);
87 // Extract the data pointer
88 Some(transmute(to.data))
96 /// Extension methods for a mutable referenced `Any` trait object
97 pub trait AnyMutRefExt<'a> {
98 /// Returns some mutable reference to the boxed value if it is of type `T`, or
99 /// `None` if it isn't.
100 fn as_mut<T: 'static>(self) -> Option<&'a mut T>;
103 impl<'a> AnyMutRefExt<'a> for &'a mut Any {
105 fn as_mut<T: 'static>(self) -> Option<&'a mut T> {
108 // Get the raw representation of the trait object
109 let to: TraitObject = transmute_copy(&self);
111 // Extract the data pointer
112 Some(transmute(to.data))
120 /// Extension methods for an owning `Any` trait object
121 pub trait AnyOwnExt {
122 /// Returns the boxed value if it is of type `T`, or
123 /// `Err(Self)` if it isn't.
124 fn move<T: 'static>(self) -> Result<~T, Self>;
127 impl AnyOwnExt for ~Any {
129 fn move<T: 'static>(self) -> Result<~T, ~Any> {
132 // Get the raw representation of the trait object
133 let to: TraitObject = transmute_copy(&self);
135 // Prevent destructor on self being run
136 intrinsics::forget(self);
138 // Extract the data pointer
139 Ok(transmute(to.data))
147 ///////////////////////////////////////////////////////////////////////////////
148 // Trait implementations
149 ///////////////////////////////////////////////////////////////////////////////
151 impl fmt::Show for ~Any {
152 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157 impl<'a> fmt::Show for &'a Any {
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
168 #[deriving(Eq, Show)]
171 static TEST: &'static str = "Test";
174 fn any_referenced() {
175 let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
177 assert!(a.is::<uint>());
178 assert!(!b.is::<uint>());
179 assert!(!c.is::<uint>());
181 assert!(!a.is::<&'static str>());
182 assert!(b.is::<&'static str>());
183 assert!(!c.is::<&'static str>());
185 assert!(!a.is::<Test>());
186 assert!(!b.is::<Test>());
187 assert!(c.is::<Test>());
192 let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
194 assert!(a.is::<uint>());
195 assert!(!b.is::<uint>());
196 assert!(!c.is::<uint>());
198 assert!(!a.is::<&'static str>());
199 assert!(b.is::<&'static str>());
200 assert!(!c.is::<&'static str>());
202 assert!(!a.is::<Test>());
203 assert!(!b.is::<Test>());
204 assert!(c.is::<Test>());
211 match a.as_ref::<uint>() {
213 x => fail!("Unexpected value {:?}", x)
216 match a.as_ref::<Test>() {
218 x => fail!("Unexpected value {:?}", x)
227 let a_r = &mut a as &mut Any;
228 let tmp: &mut uint = b;
229 let b_r = tmp as &mut Any;
231 match a_r.as_mut::<uint>() {
236 x => fail!("Unexpected value {:?}", x)
239 match b_r.as_mut::<uint>() {
244 x => fail!("Unexpected value {:?}", x)
247 match a_r.as_mut::<Test>() {
249 x => fail!("Unexpected value {:?}", x)
252 match b_r.as_mut::<Test>() {
254 x => fail!("Unexpected value {:?}", x)
257 match a_r.as_mut::<uint>() {
259 x => fail!("Unexpected value {:?}", x)
262 match b_r.as_mut::<uint>() {
264 x => fail!("Unexpected value {:?}", x)
271 let b = ~Test as ~Any;
273 match a.move::<uint>() {
274 Ok(a) => { assert_eq!(a, ~8u); }
277 match b.move::<Test>() {
278 Ok(a) => { assert_eq!(a, ~Test); }
283 let b = ~Test as ~Any;
285 assert!(a.move::<~Test>().is_err());
286 assert!(b.move::<~uint>().is_err());
292 let b = ~Test as ~Any;
293 assert_eq!(format!("{}", a), ~"~Any");
294 assert_eq!(format!("{}", b), ~"~Any");
297 let b = &Test as &Any;
298 assert_eq!(format!("{}", a), ~"&Any");
299 assert_eq!(format!("{}", b), ~"&Any");
307 use any::{Any, AnyRefExt};
309 use self::test::Bencher;
312 fn bench_as_ref(b: &mut Bencher) {
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));