@@ -244,6 +244,7 @@ use boxed::Box;
244244#[ cfg( test) ]
245245use std:: boxed:: Box ;
246246
247+ use core:: any:: Any ;
247248use core:: borrow;
248249use core:: cell:: Cell ;
249250use core:: cmp:: Ordering ;
@@ -608,6 +609,46 @@ impl<T: Clone> Rc<T> {
608609 }
609610}
610611
612+ impl Rc < Any > {
613+ #[ inline]
614+ #[ unstable( feature = "rc_downcast" , issue = "0" ) ]
615+ /// Attempt to downcast the `Rc<Any>` to a concrete type.
616+ ///
617+ /// # Examples
618+ ///
619+ /// ```
620+ /// #![feature(rc_downcast)]
621+ /// use std::any::Any;
622+ /// use std::rc::Rc;
623+ ///
624+ /// fn print_if_string(value: Rc<Any>) {
625+ /// if let Ok(string) = value.downcast::<String>() {
626+ /// println!("String ({}): {}", string.len(), string);
627+ /// }
628+ /// }
629+ ///
630+ /// fn main() {
631+ /// let my_string = "Hello World".to_string();
632+ /// print_if_string(Rc::new(my_string));
633+ /// print_if_string(Rc::new(0i8));
634+ /// }
635+ /// ```
636+ pub fn downcast < T : Any > ( self ) -> Result < Rc < T > , Rc < Any > > {
637+ if ( * self ) . is :: < T > ( ) {
638+ // avoid the pointer arithmetic in from_raw
639+ unsafe {
640+ let raw: * const RcBox < Any > = self . ptr . as_ptr ( ) ;
641+ forget ( self ) ;
642+ Ok ( Rc {
643+ ptr : Shared :: new_unchecked ( raw as * const RcBox < T > as * mut _ ) ,
644+ } )
645+ }
646+ } else {
647+ Err ( self )
648+ }
649+ }
650+ }
651+
611652impl < T : ?Sized > Rc < T > {
612653 // Allocates an `RcBox<T>` with sufficient space for an unsized value
613654 unsafe fn allocate_for_ptr ( ptr : * const T ) -> * mut RcBox < T > {
@@ -1696,6 +1737,26 @@ mod tests {
16961737
16971738 assert_eq ! ( & r[ ..] , [ 1 , 2 , 3 ] ) ;
16981739 }
1740+
1741+ #[ test]
1742+ fn test_downcast ( ) {
1743+ use std:: any:: Any ;
1744+
1745+ let r1: Rc < Any > = Rc :: new ( i32:: max_value ( ) ) ;
1746+ let r2: Rc < Any > = Rc :: new ( "abc" ) ;
1747+
1748+ assert ! ( r1. clone( ) . downcast:: <u32 >( ) . is_err( ) ) ;
1749+
1750+ let r1i32 = r1. downcast :: < i32 > ( ) ;
1751+ assert ! ( r1i32. is_ok( ) ) ;
1752+ assert_eq ! ( r1i32. unwrap( ) , Rc :: new( i32 :: max_value( ) ) ) ;
1753+
1754+ assert ! ( r2. clone( ) . downcast:: <i32 >( ) . is_err( ) ) ;
1755+
1756+ let r2str = r2. downcast :: < & ' static str > ( ) ;
1757+ assert ! ( r2str. is_ok( ) ) ;
1758+ assert_eq ! ( r2str. unwrap( ) , Rc :: new( "abc" ) ) ;
1759+ }
16991760}
17001761
17011762#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments