about summary refs log tree commit diff
path: root/library/alloc/src
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2021-01-31 01:47:27 +0100
committerGitHub <noreply@github.com>2021-01-31 01:47:27 +0100
commitcaf2c0652a2aa2db136abcc0a37c85bfb254e2cb (patch)
tree6027f0bedd2ae2df2c4967e4e6442a30a4e38856 /library/alloc/src
parent1e99f26894a766f5861ae2805c13e915e74493f0 (diff)
parent12014d29b89557836a22fa46d74101371d81daf1 (diff)
downloadrust-caf2c0652a2aa2db136abcc0a37c85bfb254e2cb.tar.gz
rust-caf2c0652a2aa2db136abcc0a37c85bfb254e2cb.zip
Rollup merge of #80945 - sdroege:downcast-send-sync, r=m-ou-se
Add Box::downcast() for dyn Any + Send + Sync

Looks like a plain omission, but unfortunately I just needed that in my code :)
Diffstat (limited to 'library/alloc/src')
-rw-r--r--library/alloc/src/boxed.rs33
1 files changed, 33 insertions, 0 deletions
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index a3c0be69813..949079e5b69 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -1372,6 +1372,39 @@ impl<A: Allocator> Box<dyn Any + Send, A> {
     }
 }
 
+impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
+    #[inline]
+    #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")]
+    /// Attempt to downcast the box to a concrete type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::any::Any;
+    ///
+    /// fn print_if_string(value: Box<dyn Any + Send + Sync>) {
+    ///     if let Ok(string) = value.downcast::<String>() {
+    ///         println!("String ({}): {}", string.len(), string);
+    ///     }
+    /// }
+    ///
+    /// let my_string = "Hello World".to_string();
+    /// print_if_string(Box::new(my_string));
+    /// print_if_string(Box::new(0i8));
+    /// ```
+    pub fn downcast<T: Any>(self) -> Result<Box<T, A>, Self> {
+        if self.is::<T>() {
+            unsafe {
+                let (raw, alloc): (*mut (dyn Any + Send + Sync), _) =
+                    Box::into_raw_with_allocator(self);
+                Ok(Box::from_raw_in(raw as *mut T, alloc))
+            }
+        } else {
+            Err(self)
+        }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Display + ?Sized, A: Allocator> fmt::Display for Box<T, A> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {