Skip to content

Commit 1e0d3f6

Browse files
committed
refactor(lib): remove pin related unsafe code
1 parent d5d09ed commit 1e0d3f6

File tree

2 files changed

+23
-25
lines changed

2 files changed

+23
-25
lines changed

src/server/accept.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
99
#[cfg(feature = "stream")]
1010
use futures_core::Stream;
11+
#[cfg(feature = "stream")]
12+
use pin_project::pin_project;
1113

1214
use crate::common::{
1315
task::{self, Poll},
@@ -53,6 +55,9 @@ where
5355
{
5456
struct PollFn<F>(F);
5557

58+
// The closure `F` is never pinned
59+
impl<F> Unpin for PollFn<F> {}
60+
5661
impl<F, IO, E> Accept for PollFn<F>
5762
where
5863
F: FnMut(&mut task::Context<'_>) -> Poll<Option<Result<IO, E>>>,
@@ -63,7 +68,7 @@ where
6368
self: Pin<&mut Self>,
6469
cx: &mut task::Context<'_>,
6570
) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
66-
unsafe { (self.get_unchecked_mut().0)(cx) }
71+
(self.get_mut().0)(cx)
6772
}
6873
}
6974

@@ -81,7 +86,8 @@ pub fn from_stream<S, IO, E>(stream: S) -> impl Accept<Conn = IO, Error = E>
8186
where
8287
S: Stream<Item = Result<IO, E>>,
8388
{
84-
struct FromStream<S>(S);
89+
#[pin_project]
90+
struct FromStream<S>(#[pin] S);
8591

8692
impl<S, IO, E> Accept for FromStream<S>
8793
where
@@ -93,7 +99,7 @@ where
9399
self: Pin<&mut Self>,
94100
cx: &mut task::Context<'_>,
95101
) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
96-
unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0).poll_next(cx) }
102+
self.project().0.poll_next(cx)
97103
}
98104
}
99105

src/service/oneshot.rs

+14-22
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// TODO: Eventually to be replaced with tower_util::Oneshot.
22

3-
use std::marker::Unpin;
4-
use std::mem;
5-
3+
use pin_project::pin_project;
64
use tower_service::Service;
75

86
use crate::common::{task, Future, Pin, Poll};
@@ -20,49 +18,43 @@ where
2018
// is ready, and then calling `Service::call` with the request, and
2119
// waiting for that `Future`.
2220
#[allow(missing_debug_implementations)]
21+
#[pin_project]
2322
pub struct Oneshot<S: Service<Req>, Req> {
23+
#[pin]
2424
state: State<S, Req>,
2525
}
2626

27+
#[pin_project(Replace, project = StateProj, project_replace = StateProjOwn)]
2728
enum State<S: Service<Req>, Req> {
2829
NotReady(S, Req),
29-
Called(S::Future),
30+
Called(#[pin] S::Future),
3031
Tmp,
3132
}
3233

33-
// Unpin is projected to S::Future, but never S.
34-
impl<S, Req> Unpin for Oneshot<S, Req>
35-
where
36-
S: Service<Req>,
37-
S::Future: Unpin,
38-
{
39-
}
40-
4134
impl<S, Req> Future for Oneshot<S, Req>
4235
where
4336
S: Service<Req>,
4437
{
4538
type Output = Result<S::Response, S::Error>;
4639

4740
fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
48-
// Safety: The service's future is never moved once we get one.
49-
let mut me = unsafe { Pin::get_unchecked_mut(self) };
41+
let mut me = self.project();
5042

5143
loop {
52-
match me.state {
53-
State::NotReady(ref mut svc, _) => {
44+
match me.state.as_mut().project() {
45+
StateProj::NotReady(ref mut svc, _) => {
5446
ready!(svc.poll_ready(cx))?;
5547
// fallthrough out of the match's borrow
5648
}
57-
State::Called(ref mut fut) => {
58-
return unsafe { Pin::new_unchecked(fut) }.poll(cx);
49+
StateProj::Called(fut) => {
50+
return fut.poll(cx);
5951
}
60-
State::Tmp => unreachable!(),
52+
StateProj::Tmp => unreachable!(),
6153
}
6254

63-
match mem::replace(&mut me.state, State::Tmp) {
64-
State::NotReady(mut svc, req) => {
65-
me.state = State::Called(svc.call(req));
55+
match me.state.as_mut().project_replace(State::Tmp) {
56+
StateProjOwn::NotReady(mut svc, req) => {
57+
me.state.set(State::Called(svc.call(req)));
6658
}
6759
_ => unreachable!(),
6860
}

0 commit comments

Comments
 (0)