]> git.lizzy.rs Git - rust.git/commitdiff
std::comm: use Unsafe to avoid U.B. & -> &mut transmutes.
authorHuon Wilson <dbau.pp+github@gmail.com>
Sun, 4 May 2014 13:35:48 +0000 (23:35 +1000)
committerHuon Wilson <dbau.pp+github@gmail.com>
Mon, 5 May 2014 08:20:41 +0000 (18:20 +1000)
src/libstd/comm/mod.rs

index bbe34d20f6a2e2f0ea615a630a1e12215ec94315..c78498924656c5fa5b0b1910464cdc347ccd37ee 100644 (file)
 // And now that you've seen all the races that I found and attempted to fix,
 // here's the code for you to find some more!
 
-use cast;
 use cell::Cell;
 use clone::Clone;
 use iter::Iterator;
 use rt::local::Local;
 use rt::task::{Task, BlockedTask};
 use sync::arc::UnsafeArc;
+use ty::Unsafe;
 
 pub use comm::select::{Select, Handle};
 
@@ -318,11 +318,6 @@ fn f() $b
 mod shared;
 mod sync;
 
-// FIXME #13933: Remove/justify all `&T` to `&mut T` transmutes
-unsafe fn transmute_mut<'a,T>(x: &'a T) -> &'a mut T {
-    cast::transmute::<&_, &mut _>(x)
-}
-
 // Use a power of 2 to allow LLVM to optimize to something that's not a
 // division, this is hit pretty regularly.
 static RESCHED_FREQ: int = 256;
@@ -330,7 +325,7 @@ unsafe fn transmute_mut<'a,T>(x: &'a T) -> &'a mut T {
 /// The receiving-half of Rust's channel type. This half can only be owned by
 /// one task
 pub struct Receiver<T> {
-    inner: Flavor<T>,
+    inner: Unsafe<Flavor<T>>,
     receives: Cell<uint>,
     // can't share in an arc
     marker: marker::NoShare,
@@ -346,7 +341,7 @@ pub struct Messages<'a, T> {
 /// The sending-half of Rust's asynchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
 pub struct Sender<T> {
-    inner: Flavor<T>,
+    inner: Unsafe<Flavor<T>>,
     sends: Cell<uint>,
     // can't share in an arc
     marker: marker::NoShare,
@@ -395,6 +390,27 @@ enum Flavor<T> {
     Sync(UnsafeArc<sync::Packet<T>>),
 }
 
+#[doc(hidden)]
+trait UnsafeFlavor<T> {
+    fn inner_unsafe<'a>(&'a self) -> &'a Unsafe<Flavor<T>>;
+    unsafe fn mut_inner<'a>(&'a self) -> &'a mut Flavor<T> {
+        &mut *self.inner_unsafe().get()
+    }
+    unsafe fn inner<'a>(&'a self) -> &'a Flavor<T> {
+        &*self.inner_unsafe().get()
+    }
+}
+impl<T> UnsafeFlavor<T> for Sender<T> {
+    fn inner_unsafe<'a>(&'a self) -> &'a Unsafe<Flavor<T>> {
+        &self.inner
+    }
+}
+impl<T> UnsafeFlavor<T> for Receiver<T> {
+    fn inner_unsafe<'a>(&'a self) -> &'a Unsafe<Flavor<T>> {
+        &self.inner
+    }
+}
+
 /// Creates a new asynchronous channel, returning the sender/receiver halves.
 ///
 /// All data sent on the sender will become available on the receiver, and no
@@ -463,7 +479,7 @@ pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
 
 impl<T: Send> Sender<T> {
     fn new(inner: Flavor<T>) -> Sender<T> {
-        Sender { inner: inner, sends: Cell::new(0), marker: marker::NoShare }
+        Sender { inner: Unsafe::new(inner), sends: Cell::new(0), marker: marker::NoShare }
     }
 
     /// Sends a value along this channel to be received by the corresponding
@@ -537,7 +553,7 @@ pub fn send_opt(&self, t: T) -> Result<(), T> {
             task.map(|t| t.maybe_yield());
         }
 
-        let (new_inner, ret) = match self.inner {
+        let (new_inner, ret) = match *unsafe { self.inner() } {
             Oneshot(ref p) => {
                 let p = p.get();
                 unsafe {
@@ -569,8 +585,8 @@ pub fn send_opt(&self, t: T) -> Result<(), T> {
         };
 
         unsafe {
-            let mut tmp = Sender::new(Stream(new_inner));
-            mem::swap(&mut transmute_mut(self).inner, &mut tmp.inner);
+            let tmp = Sender::new(Stream(new_inner));
+            mem::swap(self.mut_inner(), tmp.mut_inner());
         }
         return ret;
     }
@@ -578,7 +594,7 @@ pub fn send_opt(&self, t: T) -> Result<(), T> {
 
 impl<T: Send> Clone for Sender<T> {
     fn clone(&self) -> Sender<T> {
-        let (packet, sleeper) = match self.inner {
+        let (packet, sleeper) = match *unsafe { self.inner() } {
             Oneshot(ref p) => {
                 let (a, b) = UnsafeArc::new2(shared::Packet::new());
                 match unsafe { (*p.get()).upgrade(Receiver::new(Shared(a))) } {
@@ -603,8 +619,8 @@ fn clone(&self) -> Sender<T> {
         unsafe {
             (*packet.get()).inherit_blocker(sleeper);
 
-            let mut tmp = Sender::new(Shared(packet.clone()));
-            mem::swap(&mut transmute_mut(self).inner, &mut tmp.inner);
+            let tmp = Sender::new(Shared(packet.clone()));
+            mem::swap(self.mut_inner(), tmp.mut_inner());
         }
         Sender::new(Shared(packet))
     }
@@ -613,7 +629,7 @@ fn clone(&self) -> Sender<T> {
 #[unsafe_destructor]
 impl<T: Send> Drop for Sender<T> {
     fn drop(&mut self) {
-        match self.inner {
+        match *unsafe { self.mut_inner() } {
             Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
             Stream(ref mut p) => unsafe { (*p.get()).drop_chan(); },
             Shared(ref mut p) => unsafe { (*p.get()).drop_chan(); },
@@ -710,7 +726,7 @@ fn drop(&mut self) {
 
 impl<T: Send> Receiver<T> {
     fn new(inner: Flavor<T>) -> Receiver<T> {
-        Receiver { inner: inner, receives: Cell::new(0), marker: marker::NoShare }
+        Receiver { inner: Unsafe::new(inner), receives: Cell::new(0), marker: marker::NoShare }
     }
 
     /// Blocks waiting for a value on this receiver
@@ -762,7 +778,7 @@ pub fn try_recv(&self) -> Result<T, TryRecvError> {
         }
 
         loop {
-            let mut new_port = match self.inner {
+            let new_port = match *unsafe { self.inner() } {
                 Oneshot(ref p) => {
                     match unsafe { (*p.get()).try_recv() } {
                         Ok(t) => return Ok(t),
@@ -795,8 +811,8 @@ pub fn try_recv(&self) -> Result<T, TryRecvError> {
                 }
             };
             unsafe {
-                mem::swap(&mut transmute_mut(self).inner,
-                          &mut new_port.inner);
+                mem::swap(self.mut_inner(),
+                          new_port.mut_inner());
             }
         }
     }
@@ -815,7 +831,7 @@ pub fn try_recv(&self) -> Result<T, TryRecvError> {
     /// the value found on the receiver is returned.
     pub fn recv_opt(&self) -> Result<T, ()> {
         loop {
-            let mut new_port = match self.inner {
+            let new_port = match *unsafe { self.inner() } {
                 Oneshot(ref p) => {
                     match unsafe { (*p.get()).recv() } {
                         Ok(t) => return Ok(t),
@@ -842,8 +858,7 @@ pub fn recv_opt(&self) -> Result<T, ()> {
                 Sync(ref p) => return unsafe { (*p.get()).recv() }
             };
             unsafe {
-                mem::swap(&mut transmute_mut(self).inner,
-                          &mut new_port.inner);
+                mem::swap(self.mut_inner(), new_port.mut_inner());
             }
         }
     }
@@ -858,7 +873,7 @@ pub fn iter<'a>(&'a self) -> Messages<'a, T> {
 impl<T: Send> select::Packet for Receiver<T> {
     fn can_recv(&self) -> bool {
         loop {
-            let mut new_port = match self.inner {
+            let new_port = match *unsafe { self.inner() } {
                 Oneshot(ref p) => {
                     match unsafe { (*p.get()).can_recv() } {
                         Ok(ret) => return ret,
@@ -879,15 +894,15 @@ fn can_recv(&self) -> bool {
                 }
             };
             unsafe {
-                mem::swap(&mut transmute_mut(self).inner,
-                          &mut new_port.inner);
+                mem::swap(self.mut_inner(),
+                          new_port.mut_inner());
             }
         }
     }
 
     fn start_selection(&self, mut task: BlockedTask) -> Result<(), BlockedTask>{
         loop {
-            let (t, mut new_port) = match self.inner {
+            let (t, new_port) = match *unsafe { self.inner() } {
                 Oneshot(ref p) => {
                     match unsafe { (*p.get()).start_selection(task) } {
                         oneshot::SelSuccess => return Ok(()),
@@ -911,8 +926,8 @@ fn start_selection(&self, mut task: BlockedTask) -> Result<(), BlockedTask>{
             };
             task = t;
             unsafe {
-                mem::swap(&mut transmute_mut(self).inner,
-                          &mut new_port.inner);
+                mem::swap(self.mut_inner(),
+                          new_port.mut_inner());
             }
         }
     }
@@ -920,7 +935,7 @@ fn start_selection(&self, mut task: BlockedTask) -> Result<(), BlockedTask>{
     fn abort_selection(&self) -> bool {
         let mut was_upgrade = false;
         loop {
-            let result = match self.inner {
+            let result = match *unsafe { self.inner() } {
                 Oneshot(ref p) => unsafe { (*p.get()).abort_selection() },
                 Stream(ref p) => unsafe {
                     (*p.get()).abort_selection(was_upgrade)
@@ -932,11 +947,11 @@ fn abort_selection(&self) -> bool {
                     (*p.get()).abort_selection()
                 },
             };
-            let mut new_port = match result { Ok(b) => return b, Err(p) => p };
+            let new_port = match result { Ok(b) => return b, Err(p) => p };
             was_upgrade = true;
             unsafe {
-                mem::swap(&mut transmute_mut(self).inner,
-                          &mut new_port.inner);
+                mem::swap(self.mut_inner(),
+                          new_port.mut_inner());
             }
         }
     }
@@ -949,7 +964,7 @@ fn next(&mut self) -> Option<T> { self.rx.recv_opt().ok() }
 #[unsafe_destructor]
 impl<T: Send> Drop for Receiver<T> {
     fn drop(&mut self) {
-        match self.inner {
+        match *unsafe { self.mut_inner() } {
             Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
             Stream(ref mut p) => unsafe { (*p.get()).drop_port(); },
             Shared(ref mut p) => unsafe { (*p.get()).drop_port(); },