Skip to content

Commit 012803d

Browse files
fix: remove Unpin requirement (#12)
Co-authored-by: teor <[email protected]>
1 parent 1eb98c7 commit 012803d

File tree

7 files changed

+65
-32
lines changed

7 files changed

+65
-32
lines changed

CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
## Next release
22

33
- Allow iterating through future and stream collections.
4-
Some types may need to be [pinned](https://docs.rs/rustc-std-workspace-std/latest/std/pin/macro.pin.html)
5-
before being passed to `try_push`. This is a breaking change.
6-
See [PR 11](https://github.com/thomaseizinger/rust-futures-bounded/pull/11).
4+
See [PR 10](https://github.com/thomaseizinger/rust-futures-bounded/pull/10),
5+
[PR 11](https://github.com/thomaseizinger/rust-futures-bounded/pull/11)
6+
and [PR 12](https://github.com/thomaseizinger/rust-futures-bounded/pull/12).
77

88
## 0.3.0
99

src/futures_map.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,22 @@ where
127127
/// This iterator returns futures in an arbitrary order, which may change.
128128
///
129129
/// If downcasting a future to `T` fails it will be skipped in the iterator.
130-
pub fn iter_of_type<T>(&self) -> impl Iterator<Item = (&ID, &T)>
130+
pub fn iter_of_type<T>(&self) -> impl Iterator<Item = (&ID, Pin<&T>)>
131131
where
132132
T: 'static,
133133
{
134134
self.inner.iter().filter_map(|a| {
135-
let pin = a.inner.inner.as_ref();
136-
let any = Pin::into_inner(pin) as &(dyn Any + Send);
135+
let pointer = a.inner.inner.as_ref().get_ref();
136+
137+
let any = pointer as &(dyn Any + Send);
138+
// SAFETY: this returns `None` and drops a `&T`, which is safe because dropping a reference is trivial.
137139
let inner = any.downcast_ref::<T>()?;
138-
Some((&a.tag, inner))
140+
141+
// Safety: The pointer is already pinned, and will remain pinned for its entire lifetime,
142+
// because we return a `Pin<&T>`.
143+
let pinned = unsafe { Pin::new_unchecked(inner) };
144+
145+
Some((&a.tag, pinned))
139146
})
140147
}
141148

@@ -144,15 +151,22 @@ where
144151
/// This iterator returns futures in an arbitrary order, which may change.
145152
///
146153
/// If downcasting a future to `T` fails it will be skipped in the iterator.
147-
pub fn iter_mut_of_type<T>(&mut self) -> impl Iterator<Item = (&ID, &mut T)>
154+
pub fn iter_mut_of_type<T>(&mut self) -> impl Iterator<Item = (&ID, Pin<&mut T>)>
148155
where
149156
T: 'static,
150157
{
151158
self.inner.iter_mut().filter_map(|a| {
152159
let pin = a.inner.inner.as_mut();
153-
let any = Pin::into_inner(pin) as &mut (dyn Any + Send);
160+
161+
// Safety: We are only temporarily manipulating the pointer and pinning it again further down.
162+
let pointer = unsafe { Pin::into_inner_unchecked(pin) };
163+
let any = pointer as &mut (dyn Any + Send);
154164
let inner = any.downcast_mut::<T>()?;
155-
Some((&a.tag, inner))
165+
166+
// Safety: The pointer is already pinned.
167+
let pinned = unsafe { Pin::new_unchecked(inner) };
168+
169+
Some((&a.tag, pinned))
156170
})
157171
}
158172
}
@@ -329,7 +343,7 @@ mod tests {
329343
}
330344
assert!(!sender.iter().any(|tx| tx.is_canceled()));
331345

332-
for (_, rx) in futures.iter_mut_of_type::<oneshot::Receiver<()>>() {
346+
for (_, mut rx) in futures.iter_mut_of_type::<oneshot::Receiver<()>>() {
333347
rx.close();
334348
}
335349
assert!(sender.iter().all(|tx| tx.is_canceled()));

src/futures_set.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use std::task::{ready, Context, Poll};
1+
use std::{
2+
pin::Pin,
3+
task::{ready, Context, Poll},
4+
};
25

36
use crate::{AnyFuture, BoxFuture, Delay, FuturesMap, PushError, Timeout};
47

@@ -63,7 +66,7 @@ where
6366
/// This iterator returns futures in an arbitrary order, which may change.
6467
///
6568
/// If downcasting a future to `T` fails it will be skipped in the iterator.
66-
pub fn iter_of_type<T>(&self) -> impl Iterator<Item = &T>
69+
pub fn iter_of_type<T>(&self) -> impl Iterator<Item = Pin<&T>>
6770
where
6871
T: 'static,
6972
{
@@ -75,7 +78,7 @@ where
7578
/// This iterator returns futures in an arbitrary order, which may change.
7679
///
7780
/// If downcasting a future to `T` fails it will be skipped in the iterator.
78-
pub fn iter_mut_of_type<T>(&mut self) -> impl Iterator<Item = &mut T>
81+
pub fn iter_mut_of_type<T>(&mut self) -> impl Iterator<Item = Pin<&mut T>>
7982
where
8083
T: 'static,
8184
{

src/futures_tuple_set.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::HashMap;
2+
use std::pin::Pin;
23
use std::task::{ready, Context, Poll};
34

45
use crate::{AnyFuture, BoxFuture, Delay, FuturesMap, PushError, Timeout};
@@ -70,7 +71,7 @@ where
7071
/// This iterator returns futures in an arbitrary order, which may change.
7172
///
7273
/// If downcasting a future to `T` fails it will be skipped in the iterator.
73-
pub fn iter_of_type<T>(&self) -> impl Iterator<Item = (&T, &D)>
74+
pub fn iter_of_type<T>(&self) -> impl Iterator<Item = (Pin<&T>, &D)>
7475
where
7576
T: 'static,
7677
{
@@ -84,7 +85,7 @@ where
8485
/// This iterator returns futures in an arbitrary order, which may change.
8586
///
8687
/// If downcasting a future to `T` fails it will be skipped in the iterator.
87-
pub fn iter_mut_of_type<T>(&mut self) -> impl Iterator<Item = (&mut T, &mut D)>
88+
pub fn iter_mut_of_type<T>(&mut self) -> impl Iterator<Item = (Pin<&mut T>, &mut D)>
8889
where
8990
T: 'static,
9091
{
@@ -150,7 +151,7 @@ mod tests {
150151
}
151152
assert!(!sender.iter().any(|tx| tx.is_canceled()));
152153

153-
for (rx, _) in futures.iter_mut_of_type::<oneshot::Receiver<()>>() {
154+
for (mut rx, _) in futures.iter_mut_of_type::<oneshot::Receiver<()>>() {
154155
rx.close();
155156
}
156157
assert!(sender.iter().all(|tx| tx.is_canceled()));

src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,15 @@ impl<T> fmt::Debug for PushError<T> {
5959
impl std::error::Error for Timeout {}
6060

6161
#[doc(hidden)]
62-
pub trait AnyStream: futures_util::Stream + Any + Unpin + Send {}
62+
pub trait AnyStream: futures_util::Stream + Any + Send {}
6363

64-
impl<T> AnyStream for T where T: futures_util::Stream + Any + Unpin + Send {}
64+
impl<T> AnyStream for T where T: futures_util::Stream + Any + Send {}
6565

6666
type BoxStream<T> = Pin<Box<dyn AnyStream<Item = T> + Send>>;
6767

6868
#[doc(hidden)]
69-
pub trait AnyFuture: std::future::Future + Any + Unpin + Send {}
69+
pub trait AnyFuture: std::future::Future + Any + Send {}
7070

71-
impl<T> AnyFuture for T where T: std::future::Future + Any + Unpin + Send {}
71+
impl<T> AnyFuture for T where T: std::future::Future + Any + Send {}
7272

7373
type BoxFuture<T> = Pin<Box<dyn AnyFuture<Output = T> + Send>>;

src/stream_map.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,20 @@ where
119119
/// This iterator returns streams in an arbitrary order, which may change.
120120
///
121121
/// If downcasting a stream to `T` fails it will be skipped in the iterator.
122-
pub fn iter_of_type<T>(&self) -> impl Iterator<Item = (&ID, &T)>
122+
pub fn iter_of_type<T>(&self) -> impl Iterator<Item = (&ID, Pin<&T>)>
123123
where
124124
T: 'static,
125125
{
126126
self.inner.iter().filter_map(|a| {
127-
let pin = a.inner.inner.as_ref();
128-
let any = Pin::into_inner(pin) as &(dyn Any + Send);
127+
let pointer = a.inner.inner.as_ref().get_ref();
128+
129+
let any = pointer as &(dyn Any + Send);
129130
let inner = any.downcast_ref::<T>()?;
130-
Some((&a.key, inner))
131+
132+
// Safety: The pointer is already pinned.
133+
let pinned = unsafe { Pin::new_unchecked(inner) };
134+
135+
Some((&a.key, pinned))
131136
})
132137
}
133138

@@ -136,15 +141,22 @@ where
136141
/// This iterator returns streams in an arbitrary order, which may change.
137142
///
138143
/// If downcasting a stream to `T` fails it will be skipped in the iterator.
139-
pub fn iter_mut_of_type<T>(&mut self) -> impl Iterator<Item = (&ID, &mut T)>
144+
pub fn iter_mut_of_type<T>(&mut self) -> impl Iterator<Item = (&ID, Pin<&mut T>)>
140145
where
141146
T: 'static,
142147
{
143148
self.inner.iter_mut().filter_map(|a| {
144149
let pin = a.inner.inner.as_mut();
145-
let any = Pin::into_inner(pin) as &mut (dyn Any + Send);
150+
151+
// Safety: We are only temporarily manipulating the pointer and pinning it again further down.
152+
let pointer = unsafe { Pin::into_inner_unchecked(pin) };
153+
let any = pointer as &mut (dyn Any + Send);
146154
let inner = any.downcast_mut::<T>()?;
147-
Some((&a.key, inner))
155+
156+
// Safety: The pointer is already pinned.
157+
let pinned = unsafe { Pin::new_unchecked(inner) };
158+
159+
Some((&a.key, pinned))
148160
})
149161
}
150162
}
@@ -355,7 +367,7 @@ mod tests {
355367
}
356368
assert!(!sender.iter().any(|tx| tx.is_closed()));
357369

358-
for (_, rx) in streams.iter_mut_of_type::<mpsc::Receiver<()>>() {
370+
for (_, mut rx) in streams.iter_mut_of_type::<mpsc::Receiver<()>>() {
359371
rx.close();
360372
}
361373
assert!(sender.iter().all(|tx| tx.is_closed()));

src/stream_set.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use std::task::{ready, Context, Poll};
1+
use std::{
2+
pin::Pin,
3+
task::{ready, Context, Poll},
4+
};
25

36
use crate::{AnyStream, BoxStream, Delay, PushError, StreamMap, Timeout};
47

@@ -63,7 +66,7 @@ where
6366
/// This iterator returns streams in an arbitrary order, which may change.
6467
///
6568
/// If downcasting a stream to `T` fails it will be skipped in the iterator.
66-
pub fn iter_of_type<T>(&self) -> impl Iterator<Item = &T>
69+
pub fn iter_of_type<T>(&self) -> impl Iterator<Item = Pin<&T>>
6770
where
6871
T: 'static,
6972
{
@@ -75,7 +78,7 @@ where
7578
/// This iterator returns streams in an arbitrary order, which may change.
7679
///
7780
/// If downcasting a stream to `T` fails it will be skipped in the iterator.
78-
pub fn iter_mut_of_type<T>(&mut self) -> impl Iterator<Item = &mut T>
81+
pub fn iter_mut_of_type<T>(&mut self) -> impl Iterator<Item = Pin<&mut T>>
7982
where
8083
T: 'static,
8184
{

0 commit comments

Comments
 (0)