summary refs log tree commit diff
path: root/src/librustc_data_structures
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-03-03 06:17:06 +0100
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-03-07 01:56:59 +0100
commit62089c335fbdbe2a04c432239dce9e6e8f9a5e8e (patch)
treef87a18a8cd044b24e782e6a5eebb21885d1569fa /src/librustc_data_structures
parente8af0f4c1f121263e55da29854208db0ae1fea54 (diff)
downloadrust-62089c335fbdbe2a04c432239dce9e6e8f9a5e8e.tar.gz
rust-62089c335fbdbe2a04c432239dce9e6e8f9a5e8e.zip
Make metadata references Send + Sync
Diffstat (limited to 'src/librustc_data_structures')
-rw-r--r--src/librustc_data_structures/owning_ref/mod.rs47
-rw-r--r--src/librustc_data_structures/sync.rs3
2 files changed, 43 insertions, 7 deletions
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<O, T: ?Sized> {
 pub trait Erased {}
 impl<T> 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<T> -> Box<Erased>`. 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<T> -> Box<Erased + Send>`. 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<T> -> Box<Erased + Send + Sync>`. 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<O, T: ?Sized> OwningRef<O, T> {
         }
     }
 
+    /// 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<O::Erased, T>
+        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<T> {
     }
 }
 
-unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Box<T> {
-    type Erased = Box<Erased + Send + Sync + 'a>;
-    fn into_erased_send_sync(self) -> Self::Erased {
+unsafe impl<'a, T: Send + 'a> IntoErasedSend<'a> for Box<T> {
+    type Erased = Box<Erased + Send + 'a>;
+    fn into_erased_send(self) -> Self::Erased {
         self
     }
 }
 
+unsafe impl<'a, T: Send + 'a> IntoErasedSendSync<'a> for Box<T> {
+    type Erased = Box<Erased + Sync + Send + 'a>;
+    fn into_erased_send_sync(self) -> Self::Erased {
+        let result: Box<Erased + Send + 'a> = 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<T> {
     type Erased = Arc<Erased + Send + Sync + 'a>;
     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<T: ?Sized + Sync>() {}
+pub fn assert_send_val<T: ?Sized + Send>(_t: &T) {}
 pub fn assert_send_sync_val<T: ?Sized + Sync + Send>(_t: &T) {}
 
 #[macro_export]