(index<- )        ./libstd/any.rs

    git branch:    * master           c7553ea auto merge of #13609 : richo/rust/str-type-vim, r=alexcrichton
    modified:    Sat Apr 19 11:22:39 2014
   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.
   4  //
   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.
  10  
  11  //! Traits for dynamic typing of any type (through runtime reflection)
  12  //!
  13  //! This module implements the `Any` trait, which enables dynamic typing
  14  //! of any type, through runtime reflection.
  15  //!
  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.
  22  
  23  use cast::{transmute, transmute_copy};
  24  use fmt;
  25  use option::{Option, Some, None};
  26  use raw::TraitObject;
  27  use result::{Result, Ok, Err};
  28  use intrinsics::TypeId;
  29  use intrinsics;
  30  
  31  /// A type with no inhabitants
  32  pub enum Void { }
  33  
  34  ///////////////////////////////////////////////////////////////////////////////
  35  // Any trait
  36  ///////////////////////////////////////////////////////////////////////////////
  37  
  38  /// The `Any` trait is implemented by all types, and can be used as a trait object
  39  /// for dynamic typing
  40  pub trait Any {
  41      /// Get the `TypeId` of `self`
  42      fn get_type_id(&self) -> TypeId;
  43  }
  44  
  45  impl<T: 'static> Any for T {
  46      /// Get the `TypeId` of `self`
  47      fn get_type_id(&self) -> TypeId {
  48          TypeId::of::<T>()
  49      }
  50  }
  51  
  52  ///////////////////////////////////////////////////////////////////////////////
  53  // Extension methods for Any trait objects.
  54  // Implemented as three extension traits so that the methods can be generic.
  55  ///////////////////////////////////////////////////////////////////////////////
  56  
  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;
  61  
  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>;
  65  }
  66  
  67  impl<'a> AnyRefExt<'a> for &'a Any {
  68      #[inline]
  69      fn is<T: 'static>(self) -> bool {
  70          // Get TypeId of the type this function is instantiated with
  71          let t = TypeId::of::<T>();
  72  
  73          // Get TypeId of the type in the trait object
  74          let boxed = self.get_type_id();
  75  
  76          // Compare both TypeIds on equality
  77          t == boxed
  78      }
  79  
  80      #[inline]
  81      fn as_ref<T: 'static>(self) -> Option<&'a T> {
  82          if self.is::<T>() {
  83              unsafe {
  84                  // Get the raw representation of the trait object
  85                  let toTraitObject = transmute_copy(&self);
  86  
  87                  // Extract the data pointer
  88                  Some(transmute(to.data))
  89              }
  90          } else {
  91              None
  92          }
  93      }
  94  }
  95  
  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>;
 101  }
 102  
 103  impl<'a> AnyMutRefExt<'a> for &'a mut Any {
 104      #[inline]
 105      fn as_mut<T: 'static>(self) -> Option<&'a mut T> {
 106          if self.is::<T>() {
 107              unsafe {
 108                  // Get the raw representation of the trait object
 109                  let toTraitObject = transmute_copy(&self);
 110  
 111                  // Extract the data pointer
 112                  Some(transmute(to.data))
 113              }
 114          } else {
 115              None
 116          }
 117      }
 118  }
 119  
 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>;
 125  }
 126  
 127  impl AnyOwnExt for ~Any {
 128      #[inline]
 129      fn move<T: 'static>(self) -> Result<~T, ~Any> {
 130          if self.is::<T>() {
 131              unsafe {
 132                  // Get the raw representation of the trait object
 133                  let toTraitObject = transmute_copy(&self);
 134  
 135                  // Prevent destructor on self being run
 136                  intrinsics::forget(self);
 137  
 138                  // Extract the data pointer
 139                  Ok(transmute(to.data))
 140              }
 141          } else {
 142              Err(self)
 143          }
 144      }
 145  }
 146  
 147  ///////////////////////////////////////////////////////////////////////////////
 148  // Trait implementations
 149  ///////////////////////////////////////////////////////////////////////////////
 150  
 151  impl fmt::Show for ~Any {
 152      fn fmt(&self, f&mut fmt::Formatter) -> fmt::Result {
 153          f.pad("~Any")
 154      }
 155  }
 156  
 157  impl<'a> fmt::Show for &'a Any {
 158      fn fmt(&self, f&mut fmt::Formatter) -> fmt::Result {
 159          f.pad("&Any")
 160      }
 161  }
 162  
 163  #[cfg(test)]
 164  mod tests {
 165      use prelude::*;
 166      use super::*;
 167      use str::StrSlice;
 168  
 169      #[deriving(Eq, Show)]
 170      struct Test;
 171  
 172      static TEST: &'static str = "Test";
 173  
 174      #[test]
 175      fn any_referenced() {
 176          let (a, b, c) = (&5u as &Any, &TEST as &Any, &Test as &Any);
 177  
 178          assert!(a.is::<uint>());
 179          assert!(!b.is::<uint>());
 180          assert!(!c.is::<uint>());
 181  
 182          assert!(!a.is::<&'static str>());
 183          assert!(b.is::<&'static str>());
 184          assert!(!c.is::<&'static str>());
 185  
 186          assert!(!a.is::<Test>());
 187          assert!(!b.is::<Test>());
 188          assert!(c.is::<Test>());
 189      }
 190  
 191      #[test]
 192      fn any_owning() {
 193          let (a, b, c) = (~5u as ~Any, ~TEST as ~Any, ~Test as ~Any);
 194  
 195          assert!(a.is::<uint>());
 196          assert!(!b.is::<uint>());
 197          assert!(!c.is::<uint>());
 198  
 199          assert!(!a.is::<&'static str>());
 200          assert!(b.is::<&'static str>());
 201          assert!(!c.is::<&'static str>());
 202  
 203          assert!(!a.is::<Test>());
 204          assert!(!b.is::<Test>());
 205          assert!(c.is::<Test>());
 206      }
 207  
 208      #[test]
 209      fn any_as_ref() {
 210          let a = &5u as &Any;
 211  
 212          match a.as_ref::<uint>() {
 213              Some(&5) => {}
 214              x => fail!("Unexpected value {:?}", x)
 215          }
 216  
 217          match a.as_ref::<Test>() {
 218              None => {}
 219              x => fail!("Unexpected value {:?}", x)
 220          }
 221      }
 222  
 223      #[test]
 224      fn any_as_mut() {
 225          let mut a = 5u;
 226          let mut b = ~7u;
 227  
 228          let a_r = &mut a as &mut Any;
 229          let tmp: &mut uint = b;
 230          let b_r = tmp as &mut Any;
 231  
 232          match a_r.as_mut::<uint>() {
 233              Some(x) => {
 234                  assert_eq!(*x, 5u);
 235                  *x = 612;
 236              }
 237              x => fail!("Unexpected value {:?}", x)
 238          }
 239  
 240          match b_r.as_mut::<uint>() {
 241              Some(x) => {
 242                  assert_eq!(*x, 7u);
 243                  *x = 413;
 244              }
 245              x => fail!("Unexpected value {:?}", x)
 246          }
 247  
 248          match a_r.as_mut::<Test>() {
 249              None => (),
 250              x => fail!("Unexpected value {:?}", x)
 251          }
 252  
 253          match b_r.as_mut::<Test>() {
 254              None => (),
 255              x => fail!("Unexpected value {:?}", x)
 256          }
 257  
 258          match a_r.as_mut::<uint>() {
 259              Some(&612) => {}
 260              x => fail!("Unexpected value {:?}", x)
 261          }
 262  
 263          match b_r.as_mut::<uint>() {
 264              Some(&413) => {}
 265              x => fail!("Unexpected value {:?}", x)
 266          }
 267      }
 268  
 269      #[test]
 270      fn any_move() {
 271          let a = ~8u as ~Any;
 272          let b = ~Test as ~Any;
 273  
 274          match a.move::<uint>() {
 275              Ok(a) => { assert_eq!(a, ~8u); }
 276              Err(..) => fail!()
 277          }
 278          match b.move::<Test>() {
 279              Ok(a) => { assert_eq!(a, ~Test); }
 280              Err(..) => fail!()
 281          }
 282  
 283          let a = ~8u as ~Any;
 284          let b = ~Test as ~Any;
 285  
 286          assert!(a.move::<~Test>().is_err());
 287          assert!(b.move::<~uint>().is_err());
 288      }
 289  
 290      #[test]
 291      fn test_show() {
 292          let a = ~8u as ~Any;
 293          let b = ~Test as ~Any;
 294          assert_eq!(format!("{}", a), "~Any".to_owned());
 295          assert_eq!(format!("{}", b), "~Any".to_owned());
 296  
 297          let a = &8u as &Any;
 298          let b = &Test as &Any;
 299          assert_eq!(format!("{}", a), "&Any".to_owned());
 300          assert_eq!(format!("{}", b), "&Any".to_owned());
 301      }
 302  }
 303  
 304  #[cfg(test)]
 305  mod bench {
 306      extern crate test;
 307  
 308      use any::{Any, AnyRefExt};
 309      use option::Some;
 310      use self::test::Bencher;
 311  
 312      #[bench]
 313      fn bench_as_ref(b: &mut Bencher) {
 314          b.iter(|| {
 315              let mut x = 0; let mut y = &mut x as &mut Any;
 316              test::black_box(&mut y);
 317              test::black_box(y.as_ref::<int>() == Some(&0));
 318          });
 319      }
 320  }


libstd/any.rs:120:55-120:55 -trait- definition:
/// Extension methods for an owning `Any` trait object
pub trait AnyOwnExt {
    /// Returns the boxed value if it is of type `T`, or
references:- 2
123:     /// `Err(Self)` if it isn't.
124:     fn move<T: 'static>(self) -> Result<~T, Self>;
125: }
127: impl AnyOwnExt for ~Any {
128:     #[inline]


libstd/any.rs:39:23-39:23 -trait- definition:
/// for dynamic typing
pub trait Any {
    /// Get the `TypeId` of `self`
references:- 16
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 {
libstd/option.rs:
241:     #[inline]
242:     pub fn expect<M: Any + Send>(self, msg: M) -> T {
243:         match self {
libstd/task.rs:
58: /// children tasks complete, recommend using a result future.
59: pub type TaskResult = Result<(), ~Any:Send>;
--
242: pub fn try<T:Send>(f: proc():Send -> T) -> Result<T, ~Any:Send> {
243:     /*!
libstd/rt/mod.rs:
166:     // FIXME: This is a serious code smell and this should not exist at all.
167:     fn wrap(~self) -> ~Any;
168: }
libstd/rt/unwind.rs:
375: fn begin_unwind_inner(msg: ~Any:Send, file: &'static str, line: uint) -> ! {
376:     let mut task;
libstd/any.rs:
127: impl AnyOwnExt for ~Any {
128:     #[inline]


libstd/any.rs:31:31-31:31 -enum- definition:
/// A type with no inhabitants
pub enum Void { }
///////////////////////////////////////////////////////////////////////////////
references:- 4
libstd/fmt/mod.rs:
537: pub struct Argument<'a> {
538:     formatter: extern "Rust" fn(&any::Void, &mut Formatter) -> Result,
539:     value: &'a any::Void,
540: }
--
849:                 let v = self.curarg.next().unwrap().value;
850:                 unsafe { Some(*(v as *any::Void as *uint)) }
851:             }