diff --git a/src/lib.rs b/src/lib.rs index 21ed086..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. @@ -290,6 +291,26 @@ 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> { + /// 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. +pub unsafe trait IntoErasedSendSync<'a> { + /// 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 +484,30 @@ 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. + 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 +1185,32 @@ 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 + 'a> IntoErasedSendSync<'a> for Box { + type Erased = Box; + fn into_erased_send_sync(self) -> Self::Erased { + 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) + } + } +} + +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.