From 91d57b893fa335650ff7000eb0999efd00ee941c Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Thu, 15 Apr 2021 23:25:10 +0200 Subject: [PATCH 1/3] Add unsizing for {Arc,Rc}Box To avoid the unstable traits this uses a helper crate that provides the necessary checks and mechanisms for the raw pointer conversion while opting into them via a trait implemented for the smart pointers here. --- Cargo.lock | 10 +++++++++ crates/rc-box/Cargo.toml | 4 ++++ crates/rc-box/src/lib.rs | 44 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 1c3e182..79000f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,7 @@ version = "1.1.1" dependencies = [ "erasable 1.2.1", "slice-dst 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unsize", ] [[package]] @@ -104,3 +105,12 @@ dependencies = [ "autocfg", "erasable 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] + +[[package]] +name = "unsize" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fa7a7a734c1a5664a662ddcea0b6c9472a21da8888c957c7f1eaa09dba7a939" +dependencies = [ + "autocfg", +] diff --git a/crates/rc-box/Cargo.toml b/crates/rc-box/Cargo.toml index 7649e11..14c5174 100644 --- a/crates/rc-box/Cargo.toml +++ b/crates/rc-box/Cargo.toml @@ -27,3 +27,7 @@ slice-dst = { version = "1.4.0", optional = true } version = "1.0.0" path = "../erasable" optional = true + +[dependencies.unsize] +version = "1.1" +optional = true diff --git a/crates/rc-box/src/lib.rs b/crates/rc-box/src/lib.rs index b2878c6..b2c9edb 100644 --- a/crates/rc-box/src/lib.rs +++ b/crates/rc-box/src/lib.rs @@ -634,6 +634,50 @@ then the data will be pinned in memory and unable to be moved."), #[cfg(feature = "std")] impl UnwindSafe for $RcBox where Box: UnwindSafe {} + + #[cfg(feature = "unsize")] + doc_comment! { + concat!("Unsizes a pointer using the `unsize` crate. +# Usage + +``` +# use rc_box::*; +use unsize::{Coercion, CoerceUnsize}; + +let unique = ", stringify!($RcBox), "::new(|| 42u32); +let unique:", stringify!($RcBox), r" u32> = + unique.unsize(Coercion::<_, dyn Fn() -> u32>::to_fn()); + +let value = (*unique)(); +assert_eq!(value, 42); +``` + +Another common usage would be to create an `dyn Any`. + +fn print_if_string(value: ", stringify!($RcBox), r#") { + if let Ok(string) = value.downcast::() { + println!("String ({}): {}", string.len(), string); + } +} + +let my_string = "Hello World".to_string(); +let my_string: "#, stringify!($RcBox), " = ", stringify!($RcBox), "::new(my_string).unsize(Coercion::to_any()); +print_if_string(my_string); +let my_number: ", stringify!($RcBox), " = ", stringify!($RcBox), "::new(0i8).unsize(Coercion::to_any()); +print_if_string(my_number); +```"), + unsafe impl unsize::CoerciblePtr for $RcBox { + type Pointee = T; + type Output = $RcBox; + fn as_sized_ptr(&mut self) -> *mut T { + $RcBox::as_raw(self).as_ptr() + } + unsafe fn replace_ptr(self, new: *mut U) -> $RcBox { + let new = $RcBox::into_raw(self).replace_ptr(new); + $RcBox::from_raw(new.as_ptr() as *const U) + } + } + } )*}; } From bc02b1e4457faaccc8fbc925009175183ec2ae25 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Thu, 15 Apr 2021 23:30:22 +0200 Subject: [PATCH 2/3] Adjust documentation on unsizing --- crates/rc-box/Cargo.toml | 3 +++ crates/rc-box/src/lib.rs | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/rc-box/Cargo.toml b/crates/rc-box/Cargo.toml index 14c5174..2c68d37 100644 --- a/crates/rc-box/Cargo.toml +++ b/crates/rc-box/Cargo.toml @@ -31,3 +31,6 @@ optional = true [dependencies.unsize] version = "1.1" optional = true + +[package.metadata.docs.rs] +all-features = true diff --git a/crates/rc-box/src/lib.rs b/crates/rc-box/src/lib.rs index b2c9edb..89b56bb 100644 --- a/crates/rc-box/src/lib.rs +++ b/crates/rc-box/src/lib.rs @@ -95,8 +95,6 @@ macro_rules! rc_box { // ~~~ $Rc and Box like inherent impls ~~~ // - // downcast is pretty useless without CoerceUnsized - impl $RcBox { doc_comment! { concat!("Attempt to downcast the box to a concrete type. @@ -122,7 +120,8 @@ print_if_string(my_number.try_into().unwrap()); ``` The unsizing as `", stringify!($Rc), "` is required until -[DST coercions](https://github.com/rust-lang/rust/issues/27732) are stabilized."), +[DST coercions](https://github.com/rust-lang/rust/issues/27732) are stabilized. Alternatively, +activate the `unsize` feature to convert the pointer via an explicit method call."), #[inline] pub fn downcast(self) -> Result<$RcBox, Self> where T: Any, @@ -164,7 +163,8 @@ print_if_string(my_number.try_into().unwrap()); ``` The unsizing as `", stringify!($Rc), "` is required until -[DST coercions](https://github.com/rust-lang/rust/issues/27732) are stabilized."), +[DST coercions](https://github.com/rust-lang/rust/issues/27732) are stabilized. Alternatively, +activate the `unsize` feature to convert the pointer via an explicit method call."), #[inline] pub fn downcast(self) -> Result<$RcBox, Self> where T: Any + Send @@ -206,7 +206,8 @@ print_if_string(my_number.try_into().unwrap()); ``` The unsizing as `", stringify!($Rc), "` is required until -[DST coercions](https://github.com/rust-lang/rust/issues/27732) are stabilized."), +[DST coercions](https://github.com/rust-lang/rust/issues/27732) are stabilized. Alternatively, +activate the `unsize` feature to convert the pointer via an explicit method call."), #[inline] pub fn downcast(self) -> Result<$RcBox, Self> where T: Any + Send + Sync From e8b7cc371fd29a853c934afa9ec4ce5b87b6efb7 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Fri, 16 Apr 2021 17:32:27 +0200 Subject: [PATCH 3/3] Resolve review nits in documentation --- crates/rc-box/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/rc-box/src/lib.rs b/crates/rc-box/src/lib.rs index 89b56bb..0909f91 100644 --- a/crates/rc-box/src/lib.rs +++ b/crates/rc-box/src/lib.rs @@ -639,6 +639,7 @@ then the data will be pinned in memory and unable to be moved."), #[cfg(feature = "unsize")] doc_comment! { concat!("Unsizes a pointer using the `unsize` crate. + # Usage ``` @@ -653,7 +654,7 @@ let value = (*unique)(); assert_eq!(value, 42); ``` -Another common usage would be to create an `dyn Any`. +Another common usage would be to create a `dyn Any`. fn print_if_string(value: ", stringify!($RcBox), r#") { if let Ok(string) = value.downcast::() {