Skip to content
This repository was archived by the owner on Oct 30, 2019. It is now read-only.

Commit 6613e31

Browse files
taiki-eyoshuawuyts
authored andcommitted
Remove unsafe pin-projections (#102)
1 parent dabf429 commit 6613e31

File tree

7 files changed

+33
-46
lines changed

7 files changed

+33
-46
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ futures-preview = "0.3.0-alpha.18"
2121
runtime-attributes = { path = "runtime-attributes", version = "0.3.0-alpha.6", default-features = false }
2222
runtime-raw = { path = "runtime-raw", version = "0.3.0-alpha.5" }
2323
runtime-native = { path = "runtime-native", version = "0.3.0-alpha.6", optional = true }
24+
pin-project = "0.4.0-alpha.11"
2425

2526
[dev-dependencies]
2627
failure = "0.1.5"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ Getting things right takes time. But if you'd like to move the state of async fo
213213
you to get involved!
214214

215215
## Safety
216-
This crate uses `unsafe` in a few places to construct pin projections.
216+
This crate uses ``#![deny(unsafe_code)]`` to ensure everything is implemented in 100% Safe Rust.
217217

218218
## Contributing
219219
Want to join us? Check out our [The "Contributing" section of the

runtime-tokio/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//! [Runtime](https://github.com/rustasync/runtime). See the [Runtime
33
//! documentation](https://docs.rs/runtime) for more details.
44
5+
#![deny(unsafe_code)]
56
#![warn(
67
missing_debug_implementations,
78
missing_docs,

runtime-tokio/src/tcp.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ impl runtime_raw::TcpListener for TcpListener {
9898
self: Pin<&mut Self>,
9999
_cx: &mut Context<'_>,
100100
) -> Poll<io::Result<Pin<Box<dyn runtime_raw::TcpStream>>>> {
101-
let listener = unsafe { &mut self.get_unchecked_mut().tokio_listener };
101+
let listener = &mut self.get_mut().tokio_listener;
102102
match listener.poll_accept()? {
103103
futures01::Async::Ready((tokio_stream, _)) => {
104104
let stream = Box::pin(TcpStream { tokio_stream });

runtime-tokio/src/udp.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl runtime_raw::UdpSocket for UdpSocket {
2121
buf: &[u8],
2222
receiver: &SocketAddr,
2323
) -> Poll<io::Result<usize>> {
24-
let socket = unsafe { &mut self.get_unchecked_mut().tokio_socket };
24+
let socket = &mut self.get_mut().tokio_socket;
2525
match socket.poll_send_to(&buf, &receiver)? {
2626
futures01::Async::Ready(size) => Poll::Ready(Ok(size)),
2727
futures01::Async::NotReady => Poll::Pending,
@@ -33,7 +33,7 @@ impl runtime_raw::UdpSocket for UdpSocket {
3333
_cx: &mut Context<'_>,
3434
buf: &mut [u8],
3535
) -> Poll<io::Result<(usize, SocketAddr)>> {
36-
let socket = unsafe { &mut self.get_unchecked_mut().tokio_socket };
36+
let socket = &mut self.get_mut().tokio_socket;
3737
match socket.poll_recv_from(buf)? {
3838
futures01::Async::Ready((size, addr)) => Poll::Ready(Ok((size, addr))),
3939
futures01::Async::NotReady => Poll::Pending,

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
//! - [Runtime Tokio](https://docs.rs/runtime-tokio) provides a thread pool, bindings to the OS, and
8484
//! a work-stealing scheduler.
8585
86+
#![deny(unsafe_code)]
8687
#![warn(
8788
missing_debug_implementations,
8889
missing_docs,

src/time/ext.rs

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Extensions for Futures types.
22
3+
use pin_project::pin_project;
34
use std::future::Future;
45
use std::io;
56
use std::pin::Pin;
@@ -13,31 +14,26 @@ use super::Delay;
1314
/// A future returned by methods in the [`FutureExt`] trait.
1415
///
1516
/// [`FutureExt.timeout`]: trait.FutureExt.html
17+
#[pin_project]
1618
#[derive(Debug)]
1719
pub struct Timeout<F: Future> {
20+
#[pin]
1821
future: F,
22+
#[pin]
1923
delay: Delay,
2024
}
2125

2226
impl<F: Future> Future for Timeout<F> {
2327
type Output = Result<F::Output, io::Error>;
2428

25-
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
26-
// This pinning projection is safe because:
27-
// 1. `Timeout` is only Unpin when `F` is Unpin. (Ok for default auto impl)
28-
// 2. `drop` never moves out of `F`. (No manual `Drop` impl and no `#[repr(packed)]`)
29-
// 3. `drop` on `F` must be called before overwritten or deallocated. (No manual `Drop` impl)
30-
// 4. No other operation provided for moving out `F`. (Ok)
31-
let (future, delay) = unsafe {
32-
let Timeout { future, delay } = self.get_unchecked_mut();
33-
(Pin::new_unchecked(future), Pin::new(delay))
34-
};
29+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
30+
let this = self.project();
3531

36-
if let Poll::Ready(t) = future.poll(cx) {
32+
if let Poll::Ready(t) = this.future.poll(cx) {
3733
return Poll::Ready(Ok(t));
3834
}
3935

40-
delay
36+
this.delay
4137
.poll(cx)
4238
.map(|_| Err(io::Error::new(io::ErrorKind::TimedOut, "future timed out")))
4339
}
@@ -139,35 +135,29 @@ impl<T: Future> FutureExt for T {}
139135
/// A stream returned by methods in the [`StreamExt`] trait.
140136
///
141137
/// [`StreamExt`]: trait.StreamExt.html
138+
#[pin_project]
142139
#[derive(Debug)]
143140
pub struct TimeoutStream<S: Stream> {
141+
#[pin]
144142
timeout: Delay,
145143
dur: Duration,
144+
#[pin]
146145
stream: S,
147146
}
148147

149148
impl<S: Stream> Stream for TimeoutStream<S> {
150149
type Item = Result<S::Item, io::Error>;
151150

152-
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
153-
// This pinning projection is safe.
154-
// See detail in `Timeout::poll`.
155-
let (mut timeout, dur, stream) = unsafe {
156-
let TimeoutStream {
157-
timeout,
158-
dur,
159-
stream,
160-
} = self.get_unchecked_mut();
161-
(Pin::new(timeout), Pin::new(dur), Pin::new_unchecked(stream))
162-
};
151+
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
152+
let mut this = self.project();
163153

164-
if let Poll::Ready(s) = stream.poll_next(cx) {
165-
timeout.set(Delay::new(*dur));
154+
if let Poll::Ready(s) = this.stream.as_mut().poll_next(cx) {
155+
this.timeout.set(Delay::new(*this.dur));
166156
return Poll::Ready(Ok(s).transpose());
167157
}
168158

169-
Pin::new(&mut *timeout).poll(cx).map(|_| {
170-
timeout.set(Delay::new(*dur));
159+
this.timeout.as_mut().poll(cx).map(|_| {
160+
this.timeout.set(Delay::new(*this.dur));
171161
Some(Err(io::Error::new(
172162
io::ErrorKind::TimedOut,
173163
"future timed out",
@@ -223,37 +213,31 @@ impl<S: Stream> StreamExt for S {}
223213
/// A stream returned by methods in the [`StreamExt`] trait.
224214
///
225215
/// [`StreamExt`]: trait.StreamExt.html
216+
#[pin_project]
226217
#[derive(Debug)]
227218
pub struct TimeoutAsyncRead<S: AsyncRead> {
219+
#[pin]
228220
timeout: Delay,
229221
dur: Duration,
222+
#[pin]
230223
stream: S,
231224
}
232225

233226
impl<S: AsyncRead> AsyncRead for TimeoutAsyncRead<S> {
234227
fn poll_read(
235-
self: Pin<&mut Self>,
228+
mut self: Pin<&mut Self>,
236229
cx: &mut Context<'_>,
237230
buf: &mut [u8],
238231
) -> Poll<Result<usize, io::Error>> {
239-
// This pinning projection is safe.
240-
// See detail in `Timeout::poll`.
241-
let (mut timeout, dur, stream) = unsafe {
242-
let TimeoutAsyncRead {
243-
timeout,
244-
dur,
245-
stream,
246-
} = self.get_unchecked_mut();
247-
(Pin::new(timeout), Pin::new(dur), Pin::new_unchecked(stream))
248-
};
232+
let mut this = self.project();
249233

250-
if let Poll::Ready(s) = stream.poll_read(cx, buf) {
251-
timeout.set(Delay::new(*dur));
234+
if let Poll::Ready(s) = this.stream.as_mut().poll_read(cx, buf) {
235+
this.timeout.set(Delay::new(*this.dur));
252236
return Poll::Ready(s);
253237
}
254238

255-
Pin::new(&mut *timeout).poll(cx).map(|_| {
256-
timeout.set(Delay::new(*dur));
239+
this.timeout.as_mut().poll(cx).map(|_| {
240+
this.timeout.set(Delay::new(*this.dur));
257241
Err(io::Error::new(io::ErrorKind::TimedOut, "future timed out"))
258242
})
259243
}

0 commit comments

Comments
 (0)