From 88a3b66552608ccb0348657f7a56218c72e15a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 18 Nov 2017 14:14:57 +0100 Subject: [PATCH 1/3] Add erase_send_sync_owner to create Erased + Send + Sync references --- src/lib.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 21ed086..5384c5f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -290,6 +290,16 @@ pub unsafe trait IntoErased<'a> { fn into_erased(self) -> Self::Erased; } +/// Helper trait for erasing the concrete type of what an owner derferences to, +/// for example `Box -> Box`. This would be unneeded with +/// higher kinded types support in the language. +pub unsafe trait IntoErasedSendSync<'a>: Send + Sync { + /// Owner with the dereference type substituted to `Erased + Send + Sync`. + type Erased: Send + Sync; + /// Perform the type erasure. + fn into_erased_send_sync(self) -> Self::Erased; +} + ///////////////////////////////////////////////////////////////////////////// // OwningRef ///////////////////////////////////////////////////////////////////////////// @@ -463,6 +473,18 @@ impl OwningRef { } } + /// Erases the concrete base type of the owner with a trait object which implements `Send` and `Sync`. + /// + /// This allows mixing of owned references with different owner base types. + pub fn erase_send_sync_owner<'a>(self) -> OwningRef + where O: IntoErasedSendSync<'a>, + { + OwningRef { + reference: self.reference, + owner: self.owner.into_erased_send_sync(), + } + } + // TODO: wrap_owner // FIXME: Naming convention? @@ -1140,6 +1162,20 @@ unsafe impl<'a, T: 'a> IntoErased<'a> for Arc { } } +unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Box { + type Erased = Box; + fn into_erased_send_sync(self) -> Self::Erased { + self + } +} + +unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Arc { + type Erased = Arc; + fn into_erased_send_sync(self) -> Self::Erased { + self + } +} + /// Typedef of a owning reference that uses an erased `Box` as the owner. pub type ErasedBoxRef = OwningRef, U>; /// Typedef of a owning reference that uses an erased `Rc` as the owner. From 726738bee3329e385c15d810b710ffc6f41e8dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 22 Dec 2017 14:33:24 +0100 Subject: [PATCH 2/3] Add erase_send_owner to create Erased + Send references --- src/lib.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 5384c5f..48063e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -290,6 +290,16 @@ pub unsafe trait IntoErased<'a> { fn into_erased(self) -> Self::Erased; } +/// Helper trait for erasing the concrete type of what an owner derferences to, +/// for example `Box -> Box`. This would be unneeded with +/// higher kinded types support in the language. +pub unsafe trait IntoErasedSend<'a>: Send { + /// Owner with the dereference type substituted to `Erased + Send`. + type Erased: Send; + /// Perform the type erasure. + fn into_erased_send(self) -> Self::Erased; +} + /// Helper trait for erasing the concrete type of what an owner derferences to, /// for example `Box -> Box`. This would be unneeded with /// higher kinded types support in the language. @@ -473,6 +483,18 @@ impl OwningRef { } } + /// Erases the concrete base type of the owner with a trait object which implements `Send`. + /// + /// This allows mixing of owned references with different owner base types. + pub fn erase_send_owner<'a>(self) -> OwningRef + where O: IntoErasedSend<'a>, + { + OwningRef { + reference: self.reference, + owner: self.owner.into_erased_send(), + } + } + /// Erases the concrete base type of the owner with a trait object which implements `Send` and `Sync`. /// /// This allows mixing of owned references with different owner base types. @@ -1162,6 +1184,13 @@ unsafe impl<'a, T: 'a> IntoErased<'a> for Arc { } } +unsafe impl<'a, T: Send + 'a> IntoErasedSend<'a> for Box { + type Erased = Box; + fn into_erased_send(self) -> Self::Erased { + self + } +} + unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Box { type Erased = Box; fn into_erased_send_sync(self) -> Self::Erased { From 143e5b7c356e23b13da33f0477d59feea8d99b2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 22 Dec 2017 23:48:08 +0100 Subject: [PATCH 3/3] Let Erased be implicitly Sync --- src/lib.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 48063e8..1f3e787 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -244,6 +244,7 @@ fn main() { */ extern crate stable_deref_trait; +use std::mem; pub use stable_deref_trait::{StableDeref as StableAddress, CloneStableDeref as CloneStableAddress}; /// An owning reference. @@ -293,7 +294,7 @@ pub unsafe trait IntoErased<'a> { /// Helper trait for erasing the concrete type of what an owner derferences to, /// for example `Box -> Box`. This would be unneeded with /// higher kinded types support in the language. -pub unsafe trait IntoErasedSend<'a>: Send { +pub unsafe trait IntoErasedSend<'a> { /// Owner with the dereference type substituted to `Erased + Send`. type Erased: Send; /// Perform the type erasure. @@ -303,7 +304,7 @@ pub unsafe trait IntoErasedSend<'a>: Send { /// Helper trait for erasing the concrete type of what an owner derferences to, /// for example `Box -> Box`. This would be unneeded with /// higher kinded types support in the language. -pub unsafe trait IntoErasedSendSync<'a>: Send + Sync { +pub unsafe trait IntoErasedSendSync<'a> { /// Owner with the dereference type substituted to `Erased + Send + Sync`. type Erased: Send + Sync; /// Perform the type erasure. @@ -1191,10 +1192,15 @@ unsafe impl<'a, T: Send + 'a> IntoErasedSend<'a> for Box { } } -unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Box { - type Erased = Box; +unsafe impl<'a, T: Send + 'a> IntoErasedSendSync<'a> for Box { + type Erased = Box; fn into_erased_send_sync(self) -> Self::Erased { - self + let result: Box = self; + // This is safe since Erased can always implement Sync + // Only the destructor is available and it takes &mut self + unsafe { + mem::transmute(result) + } } }