@@ -113,7 +113,7 @@ doc! {macro_rules! join {
113113 ( @ {
114114 // Type of rotator that controls which inner future to start with
115115 // when polling our output future.
116- rotator=$rotator : ty;
116+ rotator_select=$rotator_select : ty;
117117
118118 // One `_` for each branch in the `join!` macro. This is not used once
119119 // normalization is complete.
@@ -126,7 +126,7 @@ doc! {macro_rules! join {
126126 $( ( $( $skip: tt) * ) $e: expr, ) *
127127
128128 } ) => { {
129- use $crate :: macros:: support:: { maybe_done, poll_fn, Future , Pin } ;
129+ use $crate :: macros:: support:: { maybe_done, poll_fn, Future , Pin , RotatorSelect } ;
130130 use $crate :: macros:: support:: Poll :: { Ready , Pending } ;
131131
132132 // Safety: nothing must be moved out of `futures`. This is to satisfy
@@ -143,14 +143,14 @@ doc! {macro_rules! join {
143143 // <https://internals.rust-lang.org/t/surprising-soundness-trouble-around-pollfn/17484>
144144 let mut futures = & mut futures;
145145
146- const COUNT : u32 = $( $total) * ;
147-
148146 // Each time the future created by poll_fn is polled, if not using biased mode,
149147 // a different future is polled first to ensure every future passed to join!
150148 // 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 ( ) ;
152150
153151 poll_fn( move |cx| {
152+ const COUNT : u32 = $( $total) * ;
153+
154154 let mut is_pending = false ;
155155 let mut to_run = COUNT ;
156156
@@ -205,24 +205,48 @@ doc! {macro_rules! join {
205205
206206 // ===== Normalize =====
207207
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) * )
210210 } ;
211211
212212 // ===== Entry point =====
213213 ( biased; $( $e: expr) , + $( , ) ?) => {
214- $crate :: join!( @{ rotator =$crate :: macros:: support:: BiasedRotator ; ( ) ( 0 ) } $( $e, ) * )
214+ $crate :: join!( @{ rotator_select =$crate :: macros:: support:: SelectBiased ; ( ) ( 0 ) } $( $e, ) * )
215215 } ;
216216
217217 ( $( $e: expr) , + $( , ) ?) => {
218- $crate :: join!( @{ rotator =$crate :: macros:: support:: Rotator < COUNT > ; ( ) ( 0 ) } $( $e, ) * )
218+ $crate :: join!( @{ rotator_select =$crate :: macros:: support:: SelectNormal ; ( ) ( 0 ) } $( $e, ) * )
219219 } ;
220220
221221 ( biased; ) => { async { } . await } ;
222222
223223 ( ) => { async { } . await }
224224} }
225225
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+
226250/// Rotates by one each [`Self::num_skip`] call up to COUNT - 1.
227251#[ derive( Default , Debug ) ]
228252pub struct Rotator < const COUNT : u32 > {
0 commit comments