File tree Expand file tree Collapse file tree 2 files changed +82
-5
lines changed
Expand file tree Collapse file tree 2 files changed +82
-5
lines changed Original file line number Diff line number Diff line change @@ -51,14 +51,21 @@ where
5151 let mut this = self . project ( ) ;
5252 loop {
5353 if let Some ( inner) = this. inner_stream . as_mut ( ) . as_pin_mut ( ) {
54- if let item @ Some ( _) = futures_core:: ready!( inner. poll_next( cx) ) {
55- return Poll :: Ready ( item) ;
54+ let next_item = futures_core:: ready!( inner. poll_next( cx) ) ;
55+
56+ if next_item. is_some ( ) {
57+ return Poll :: Ready ( next_item) ;
58+ } else {
59+ this. inner_stream . set ( None ) ;
5660 }
5761 }
5862
59- match futures_core:: ready!( this. stream. as_mut( ) . poll_next( cx) ) {
60- None => return Poll :: Ready ( None ) ,
61- Some ( inner) => this. inner_stream . set ( Some ( inner. into_stream ( ) ) ) ,
63+ let inner = futures_core:: ready!( this. stream. as_mut( ) . poll_next( cx) ) ;
64+
65+ if inner. is_some ( ) {
66+ this. inner_stream . set ( inner. map ( IntoStream :: into_stream) ) ;
67+ } else {
68+ return Poll :: Ready ( None ) ;
6269 }
6370 }
6471 }
Original file line number Diff line number Diff line change @@ -98,3 +98,73 @@ fn merge_works_with_unfused_streams() {
9898 } ) ;
9999 assert_eq ! ( xs, vec![ 92 , 92 ] ) ;
100100}
101+
102+ #[ test]
103+ fn flat_map_doesnt_poll_completed_inner_stream ( ) {
104+ async_std:: task:: block_on ( async {
105+ use async_std:: prelude:: * ;
106+ use async_std:: task:: * ;
107+ use std:: convert:: identity;
108+ use std:: marker:: Unpin ;
109+ use std:: pin:: Pin ;
110+
111+ struct S < T > ( T ) ;
112+
113+ impl < T : Stream + Unpin > Stream for S < T > {
114+ type Item = T :: Item ;
115+
116+ fn poll_next ( mut self : Pin < & mut Self > , ctx : & mut Context ) -> Poll < Option < Self :: Item > > {
117+ unsafe { Pin :: new_unchecked ( & mut self . 0 ) } . poll_next ( ctx)
118+ }
119+ }
120+
121+ struct StrictOnce {
122+ polled : bool ,
123+ } ;
124+
125+ impl Stream for StrictOnce {
126+ type Item = ( ) ;
127+
128+ fn poll_next ( mut self : Pin < & mut Self > , _: & mut Context ) -> Poll < Option < Self :: Item > > {
129+ if !self . polled {
130+ self . polled = true ;
131+ Poll :: Ready ( None )
132+ } else {
133+ panic ! ( "Polled after completion!" ) ;
134+ }
135+ }
136+ }
137+
138+ struct Interchanger {
139+ polled : bool ,
140+ } ;
141+
142+ impl Stream for Interchanger {
143+ type Item = S < Box < dyn Stream < Item = ( ) > + Unpin > > ;
144+
145+ fn poll_next ( mut self : Pin < & mut Self > , ctx : & mut Context ) -> Poll < Option < Self :: Item > > {
146+ if self . polled {
147+ let waker = ctx. waker ( ) . clone ( ) ;
148+ std:: thread:: spawn ( move || {
149+ std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 10 ) ) ;
150+ waker. wake_by_ref ( ) ;
151+ } ) ;
152+ self . polled = false ;
153+ Poll :: Pending
154+ } else {
155+ self . polled = true ;
156+ Poll :: Ready ( Some ( S ( Box :: new ( StrictOnce { polled : false } ) ) ) )
157+ }
158+ }
159+ }
160+
161+ assert_eq ! (
162+ Interchanger { polled: false }
163+ . take( 2 )
164+ . flat_map( identity)
165+ . count( )
166+ . await ,
167+ 0
168+ ) ;
169+ } ) ;
170+ }
You can’t perform that action at this time.
0 commit comments