@@ -113,7 +113,7 @@ doc! {macro_rules! join {
113
113
( @ {
114
114
// Type of rotator that controls which inner future to start with
115
115
// when polling our output future.
116
- rotator=$rotator : ty;
116
+ rotator_select=$rotator_select : ty;
117
117
118
118
// One `_` for each branch in the `join!` macro. This is not used once
119
119
// normalization is complete.
@@ -126,7 +126,7 @@ doc! {macro_rules! join {
126
126
$( ( $( $skip: tt) * ) $e: expr, ) *
127
127
128
128
} ) => { {
129
- use $crate :: macros:: support:: { maybe_done, poll_fn, Future , Pin } ;
129
+ use $crate :: macros:: support:: { maybe_done, poll_fn, Future , Pin , RotatorSelect } ;
130
130
use $crate :: macros:: support:: Poll :: { Ready , Pending } ;
131
131
132
132
// Safety: nothing must be moved out of `futures`. This is to satisfy
@@ -143,14 +143,14 @@ doc! {macro_rules! join {
143
143
// <https://internals.rust-lang.org/t/surprising-soundness-trouble-around-pollfn/17484>
144
144
let mut futures = & mut futures;
145
145
146
- const COUNT : u32 = $( $total) * ;
147
-
148
146
// Each time the future created by poll_fn is polled, if not using biased mode,
149
147
// a different future is polled first to ensure every future passed to join!
150
148
// can make progress even if one of the futures consumes the whole budget.
151
- let mut rotator = <$rotator >:: default ( ) ;
149
+ let mut rotator = <$rotator_select as RotatorSelect > :: Rotator :: < { $ ( $total ) * } >:: default ( ) ;
152
150
153
151
poll_fn( move |cx| {
152
+ const COUNT : u32 = $( $total) * ;
153
+
154
154
let mut is_pending = false ;
155
155
let mut to_run = COUNT ;
156
156
@@ -205,24 +205,48 @@ doc! {macro_rules! join {
205
205
206
206
// ===== Normalize =====
207
207
208
- ( @ { rotator=$rotator : ty; ( $( $s: tt) * ) ( $( $n: tt) * ) $( $t: tt) * } $e: expr, $( $r: tt) * ) => {
209
- $crate :: join!( @{ rotator=$rotator ; ( $( $s) * _) ( $( $n) * + 1 ) $( $t) * ( $( $s) * ) $e, } $( $r) * )
208
+ ( @ { rotator_select=$rotator_select : ty; ( $( $s: tt) * ) ( $( $n: tt) * ) $( $t: tt) * } $e: expr, $( $r: tt) * ) => {
209
+ $crate :: join!( @{ rotator_select=$rotator_select ; ( $( $s) * _) ( $( $n) * + 1 ) $( $t) * ( $( $s) * ) $e, } $( $r) * )
210
210
} ;
211
211
212
212
// ===== Entry point =====
213
213
( biased; $( $e: expr) , + $( , ) ?) => {
214
- $crate :: join!( @{ rotator =$crate :: macros:: support:: BiasedRotator ; ( ) ( 0 ) } $( $e, ) * )
214
+ $crate :: join!( @{ rotator_select =$crate :: macros:: support:: SelectBiased ; ( ) ( 0 ) } $( $e, ) * )
215
215
} ;
216
216
217
217
( $( $e: expr) , + $( , ) ?) => {
218
- $crate :: join!( @{ rotator =$crate :: macros:: support:: Rotator < COUNT > ; ( ) ( 0 ) } $( $e, ) * )
218
+ $crate :: join!( @{ rotator_select =$crate :: macros:: support:: SelectNormal ; ( ) ( 0 ) } $( $e, ) * )
219
219
} ;
220
220
221
221
( biased; ) => { async { } . await } ;
222
222
223
223
( ) => { async { } . await }
224
224
} }
225
225
226
+ /// Helper trait to select which type of `Rotator` to use.
227
+ // We need this to allow specifying a const generic without
228
+ // colliding with caller const names due to macro hygiene.
229
+ pub trait RotatorSelect {
230
+ type Rotator < const COUNT : u32 > : Default ;
231
+ }
232
+
233
+ /// Marker type indicating that the starting branch should
234
+ /// rotate each poll.
235
+ #[ derive( Debug ) ]
236
+ pub struct SelectNormal ;
237
+ /// Marker type indicating that the starting branch should
238
+ /// be the first declared branch each poll.
239
+ #[ derive( Debug ) ]
240
+ pub struct SelectBiased ;
241
+
242
+ impl RotatorSelect for SelectNormal {
243
+ type Rotator < const COUNT : u32 > = Rotator < COUNT > ;
244
+ }
245
+
246
+ impl RotatorSelect for SelectBiased {
247
+ type Rotator < const COUNT : u32 > = BiasedRotator ;
248
+ }
249
+
226
250
/// Rotates by one each [`Self::num_skip`] call up to COUNT - 1.
227
251
#[ derive( Default , Debug ) ]
228
252
pub struct Rotator < const COUNT : u32 > {
0 commit comments