@@ -237,7 +237,7 @@ impl<Fut: Future, const N: usize> Future for SelectArray<Fut, N> {
237
237
#[ derive( Debug ) ]
238
238
#[ must_use = "futures do nothing unless you `.await` or poll them" ]
239
239
pub struct SelectSlice < ' a , Fut > {
240
- inner : & ' a mut [ Fut ] ,
240
+ inner : Pin < & ' a mut [ Fut ] > ,
241
241
}
242
242
243
243
/// Creates a new future which will select over a slice of futures.
@@ -247,31 +247,26 @@ pub struct SelectSlice<'a, Fut> {
247
247
/// future that was ready.
248
248
///
249
249
/// If the slice is empty, the resulting future will be Pending forever.
250
- pub fn select_slice < ' a , Fut : Future > ( slice : & ' a mut [ Fut ] ) -> SelectSlice < ' a , Fut > {
250
+ pub fn select_slice < ' a , Fut : Future > ( slice : Pin < & ' a mut [ Fut ] > ) -> SelectSlice < ' a , Fut > {
251
251
SelectSlice { inner : slice }
252
252
}
253
253
254
254
impl < ' a , Fut : Future > Future for SelectSlice < ' a , Fut > {
255
255
type Output = ( Fut :: Output , usize ) ;
256
256
257
- fn poll ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
258
- // Safety: Since `self` is pinned, `inner` cannot move. Since `inner` cannot move,
259
- // its elements also cannot move. Therefore it is safe to access `inner` and pin
260
- // references to the contained futures.
261
- let item = unsafe {
262
- self . get_unchecked_mut ( )
263
- . inner
264
- . iter_mut ( )
265
- . enumerate ( )
266
- . find_map ( |( i, f) | match Pin :: new_unchecked ( f) . poll ( cx) {
267
- Poll :: Pending => None ,
268
- Poll :: Ready ( e) => Some ( ( i, e) ) ,
269
- } )
270
- } ;
271
-
272
- match item {
273
- Some ( ( idx, res) ) => Poll :: Ready ( ( res, idx) ) ,
274
- None => Poll :: Pending ,
257
+ fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
258
+ // Safety: refer to
259
+ // https://users.rust-lang.org/t/working-with-pinned-slices-are-there-any-structurally-pinning-vec-like-collection-types/50634/2
260
+ #[ inline( always) ]
261
+ fn pin_iter < T > ( slice : Pin < & mut [ T ] > ) -> impl Iterator < Item = Pin < & mut T > > {
262
+ unsafe { slice. get_unchecked_mut ( ) . iter_mut ( ) . map ( |v| Pin :: new_unchecked ( v) ) }
263
+ }
264
+ for ( i, fut) in pin_iter ( self . inner . as_mut ( ) ) . enumerate ( ) {
265
+ if let Poll :: Ready ( res) = fut. poll ( cx) {
266
+ return Poll :: Ready ( ( res, i) ) ;
267
+ }
275
268
}
269
+
270
+ Poll :: Pending
276
271
}
277
272
}
0 commit comments