@@ -115,10 +115,16 @@ macro_rules! select {
115115 // Main logic. This is matched at the end of the recursion.
116116 ( @ ( $( $max_index_underscores: tt) * ) ; $( ( $( $index_underscores: tt) * ) $v: pat = $f: expr => $b: block, ) +) => { {
117117 use core:: future:: Future ;
118+ use core:: pin:: pin;
118119
119120 // If a bit at case's index is set to 1, the case is disabled.
120121 let mut disabled_cases = 0_usize ;
121122
123+ // The pin! macro is necessary to pin futures that don't implement that Unpin trait, for example async functions and closures.
124+ // The use of the pin! macro is safe because select! awaits on the poll_fn immediately instad of returning the future.
125+ // If select was to return the future, the wrapping block would need to be async to capture the local variable crated by pin!.
126+ let mut pins = ( $( pin!( $f) , ) +) ;
127+
122128 core:: future:: poll_fn( |context| {
123129 // Create a block for each case and poll its future.
124130 // TODO: This will have to be a for loop over all futures if randomization is needed.
@@ -127,7 +133,7 @@ macro_rules! select {
127133 let case_mask = 1 << case_index;
128134
129135 if ( disabled_cases & case_mask) == 0 {
130- let mut pin = core :: pin :: Pin :: new ( & mut $f ) ;
136+ let ( $ ( $index_underscores , ) * pin, .. ) = & mut pins ;
131137
132138 match pin. as_mut( ) . poll( context) {
133139 core:: task:: Poll :: Ready ( result) => {
@@ -360,7 +366,7 @@ mod tests {
360366 #[ test]
361367 fn one_case ( ) {
362368 async fn test ( ) -> i32 {
363- let mut fut1 = future:: ready ( 111 ) ;
369+ let fut1 = future:: ready ( 111 ) ;
364370 let mut result = 0 ;
365371
366372 select ! {
@@ -381,9 +387,9 @@ mod tests {
381387 #[ test]
382388 fn case_1_first ( ) {
383389 async fn test ( ) -> i32 {
384- let mut fut1 = future:: ready ( 111 ) ;
385- let mut fut2 = future:: pending :: < i32 > ( ) ;
386- let mut fut3 = future:: pending :: < i32 > ( ) ;
390+ let fut1 = future:: ready ( 111 ) ;
391+ let fut2 = future:: pending :: < i32 > ( ) ;
392+ let fut3 = future:: pending :: < i32 > ( ) ;
387393 let mut result = 0 ;
388394
389395 select ! {
@@ -410,9 +416,9 @@ mod tests {
410416 #[ test]
411417 fn case_2_first ( ) {
412418 async fn test ( ) -> i32 {
413- let mut fut1 = future:: pending :: < i32 > ( ) ;
414- let mut fut2 = future:: ready ( 222 ) ;
415- let mut fut3 = future:: pending :: < i32 > ( ) ;
419+ let fut1 = future:: pending :: < i32 > ( ) ;
420+ let fut2 = future:: ready ( 222 ) ;
421+ let fut3 = future:: pending :: < i32 > ( ) ;
416422 let mut result = 0 ;
417423
418424 select ! {
@@ -439,9 +445,9 @@ mod tests {
439445 #[ test]
440446 fn case_3_first ( ) {
441447 async fn test ( ) -> i32 {
442- let mut fut1 = future:: pending :: < i32 > ( ) ;
443- let mut fut2 = future:: pending :: < i32 > ( ) ;
444- let mut fut3 = future:: ready ( 333 ) ;
448+ let fut1 = future:: pending :: < i32 > ( ) ;
449+ let fut2 = future:: pending :: < i32 > ( ) ;
450+ let fut3 = future:: ready ( 333 ) ;
445451 let mut result = 0 ;
446452
447453 select ! {
@@ -468,10 +474,10 @@ mod tests {
468474 #[ test]
469475 fn case_2_and_3_ready ( ) {
470476 async fn test ( ) -> i32 {
471- let mut fut1 = future:: pending :: < i32 > ( ) ;
477+ let fut1 = future:: pending :: < i32 > ( ) ;
472478 // Both futures are ready, but since there's no randomization, the 2nd will return first.
473- let mut fut2 = future:: ready ( 222 ) ;
474- let mut fut3 = future:: ready ( 333 ) ;
479+ let fut2 = future:: ready ( 222 ) ;
480+ let fut3 = future:: ready ( 333 ) ;
475481 let mut result = 0 ;
476482
477483 select ! {
@@ -498,10 +504,10 @@ mod tests {
498504 #[ test]
499505 fn optional_case_matches ( ) {
500506 async fn test ( ) -> i32 {
501- let mut fut1 = future:: pending :: < i32 > ( ) ;
502- let mut fut2: future:: Ready < Option < i32 > > = future:: ready ( Some ( 222 ) ) ;
503- let mut fut3 = future:: ready ( 333 ) ;
504- let mut fut4 = future:: pending :: < i32 > ( ) ;
507+ let fut1 = future:: pending :: < i32 > ( ) ;
508+ let fut2: future:: Ready < Option < i32 > > = future:: ready ( Some ( 222 ) ) ;
509+ let fut3 = future:: ready ( 333 ) ;
510+ let fut4 = future:: pending :: < i32 > ( ) ;
505511 let mut result = 0 ;
506512
507513 select ! {
@@ -531,10 +537,10 @@ mod tests {
531537 #[ test]
532538 fn optional_case_fails_to_match ( ) {
533539 async fn test ( ) -> i32 {
534- let mut fut1 = future:: pending :: < i32 > ( ) ;
535- let mut fut2: future:: Ready < Option < i32 > > = future:: ready ( None ) ;
536- let mut fut3 = future:: ready ( 333 ) ;
537- let mut fut4 = future:: pending :: < i32 > ( ) ;
540+ let fut1 = future:: pending :: < i32 > ( ) ;
541+ let fut2: future:: Ready < Option < i32 > > = future:: ready ( None ) ;
542+ let fut3 = future:: ready ( 333 ) ;
543+ let fut4 = future:: pending :: < i32 > ( ) ;
538544 let mut result = 0 ;
539545
540546 select ! {
@@ -564,9 +570,9 @@ mod tests {
564570 #[ test]
565571 fn all_cases_pending ( ) {
566572 async fn test ( ) -> i32 {
567- let mut fut1 = future:: pending :: < i32 > ( ) ;
568- let mut fut2 = future:: pending :: < i32 > ( ) ;
569- let mut fut3 = future:: pending :: < i32 > ( ) ;
573+ let fut1 = future:: pending :: < i32 > ( ) ;
574+ let fut2 = future:: pending :: < i32 > ( ) ;
575+ let fut3 = future:: pending :: < i32 > ( ) ;
570576 let mut result = 0 ;
571577
572578 select ! {
@@ -596,9 +602,67 @@ mod tests {
596602 #[ test]
597603 fn select_returns_result ( ) {
598604 async fn test ( ) -> i32 {
599- let mut fut1 = future:: ready ( 111 ) ;
600- let mut fut2 = future:: pending :: < i32 > ( ) ;
601- let mut fut3 = future:: pending :: < i32 > ( ) ;
605+ let fut1 = future:: ready ( 111 ) ;
606+ let fut2 = future:: pending :: < i32 > ( ) ;
607+ let fut3 = future:: pending :: < i32 > ( ) ;
608+
609+ select ! {
610+ var1 = fut1 => {
611+ var1
612+ }
613+ _ = fut2 => {
614+ 222
615+ }
616+ _ = fut3 => {
617+ 333
618+ }
619+ }
620+ }
621+
622+ let mut context = task:: Context :: from_waker ( task:: Waker :: noop ( ) ) ;
623+ let mut future = Box :: pin ( test ( ) ) ;
624+ let result = future. as_mut ( ) . poll ( & mut context) ;
625+ assert_eq ! ( result, task:: Poll :: Ready ( 111 ) ) ;
626+ }
627+
628+ #[ test]
629+ fn select_called_with_async_function ( ) {
630+ async fn test ( ) -> i32 {
631+ async fn first ( ) -> i32 {
632+ 111
633+ }
634+
635+ let fut1 = first ( ) ;
636+ let fut2 = future:: pending :: < i32 > ( ) ;
637+ let fut3 = future:: pending :: < i32 > ( ) ;
638+
639+ select ! {
640+ var1 = fut1 => {
641+ var1
642+ }
643+ _ = fut2 => {
644+ 222
645+ }
646+ _ = fut3 => {
647+ 333
648+ }
649+ }
650+ }
651+
652+ let mut context = task:: Context :: from_waker ( task:: Waker :: noop ( ) ) ;
653+ let mut future = Box :: pin ( test ( ) ) ;
654+ let result = future. as_mut ( ) . poll ( & mut context) ;
655+ assert_eq ! ( result, task:: Poll :: Ready ( 111 ) ) ;
656+ }
657+
658+ #[ test]
659+ fn select_called_with_async_closure ( ) {
660+ async fn test ( ) -> i32 {
661+ let first = async || 111 ;
662+
663+ let fut1 = first ( ) ;
664+ let fut2 = future:: pending :: < i32 > ( ) ;
665+ let fut3 = future:: pending :: < i32 > ( ) ;
602666
603667 select ! {
604668 var1 = fut1 => {
0 commit comments