diff options
| author | Huon Wilson <dbau.pp+github@gmail.com> | 2014-05-04 23:35:48 +1000 |
|---|---|---|
| committer | Huon Wilson <dbau.pp+github@gmail.com> | 2014-05-05 18:20:41 +1000 |
| commit | edd9bad4eeb1367464e190d63113600fca0ef25a (patch) | |
| tree | 0fc6da62c79eeb46c4e322206a547a6a49c5dd6b /src/libstd | |
| parent | 781ac3e777a5f47bdfaba05ee17f8b79845670b1 (diff) | |
| download | rust-edd9bad4eeb1367464e190d63113600fca0ef25a.tar.gz rust-edd9bad4eeb1367464e190d63113600fca0ef25a.zip | |
std::comm: use Unsafe to avoid U.B. & -> &mut transmutes.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/comm/mod.rs | 83 |
1 files changed, 49 insertions, 34 deletions
diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs index bbe34d20f6a..c7849892465 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/comm/mod.rs @@ -271,7 +271,6 @@ // 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; @@ -284,6 +283,7 @@ use result::{Ok, Err, Result}; 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 @@ mod stream; 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 @@ static RESCHED_FREQ: int = 256; /// 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 @@ impl<T: Send> Sender<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 @@ impl<T: Send> Sender<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 @@ impl<T: Send> Sender<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 @@ impl<T: Send> Clone for 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 @@ impl<T: Send> Clone for 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 @@ impl<T: Send> Drop for SyncSender<T> { 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 @@ impl<T: Send> Receiver<T> { } 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 @@ impl<T: Send> Receiver<T> { } }; 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 @@ impl<T: Send> Receiver<T> { /// 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 @@ impl<T: Send> Receiver<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 @@ impl<T: Send> Receiver<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 @@ impl<T: Send> select::Packet for Receiver<T> { } }; 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 @@ impl<T: Send> select::Packet for Receiver<T> { }; 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 @@ impl<T: Send> select::Packet for Receiver<T> { 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 @@ impl<T: Send> select::Packet for Receiver<T> { (*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 @@ impl<'a, T: Send> Iterator<T> for Messages<'a, T> { #[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(); }, |
