From 62089c335fbdbe2a04c432239dce9e6e8f9a5e8e Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Sat, 3 Mar 2018 06:17:06 +0100 Subject: Make metadata references Send + Sync --- src/librustc_data_structures/owning_ref/mod.rs | 47 ++++++++++++++++++++++---- src/librustc_data_structures/sync.rs | 3 +- 2 files changed, 43 insertions(+), 7 deletions(-) (limited to 'src/librustc_data_structures') diff --git a/src/librustc_data_structures/owning_ref/mod.rs b/src/librustc_data_structures/owning_ref/mod.rs index 23e0733748b..c466b8f8ad1 100644 --- a/src/librustc_data_structures/owning_ref/mod.rs +++ b/src/librustc_data_structures/owning_ref/mod.rs @@ -243,6 +243,7 @@ fn main() { ``` */ +use std::mem; pub use stable_deref_trait::{StableDeref as StableAddress, CloneStableDeref as CloneStableAddress}; /// An owning reference. @@ -279,7 +280,7 @@ pub struct OwningRefMut { pub trait Erased {} impl Erased for T {} -/// Helper trait for erasing the concrete type of what an owner derferences to, +/// Helper trait for erasing the concrete type of what an owner dereferences to, /// for example `Box -> Box`. This would be unneeded with /// higher kinded types support in the language. pub unsafe trait IntoErased<'a> { @@ -289,10 +290,20 @@ pub unsafe trait IntoErased<'a> { fn into_erased(self) -> Self::Erased; } -/// Helper trait for erasing the concrete type of what an owner derferences to, +/// Helper trait for erasing the concrete type of what an owner dereferences 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 dereferences 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. @@ -472,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. @@ -1161,13 +1184,25 @@ 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 { +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 { diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index b1ab4eaa069..69fc9ef785e 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -177,7 +177,7 @@ cfg_if! { macro_rules! rustc_erase_owner { ($v:expr) => {{ let v = $v; - ::rustc_data_structures::sync::assert_send_sync_val(&v); + ::rustc_data_structures::sync::assert_send_val(&v); v.erase_send_sync_owner() }} } @@ -262,6 +262,7 @@ cfg_if! { } pub fn assert_sync() {} +pub fn assert_send_val(_t: &T) {} pub fn assert_send_sync_val(_t: &T) {} #[macro_export] -- cgit 1.4.1-3-g733a5