@@ -670,7 +670,7 @@ mod tests {
670670 for _ in 0 ..16 {
671671 let cx_guard = Context :: current ( ) . with_value ( ValueA ( 1 ) ) . attach ( ) ;
672672 assert_eq ! ( cx_guard. cx_pos, ContextStack :: MAX_POS ) ;
673- assert_eq ! ( Context :: current( ) . get( ) , Some ( & ValueA ( 2 ) ) ) ;
673+ assert_eq ! ( Context :: current( ) . get:: < ValueA > ( ) , Some ( & ValueA ( 2 ) ) ) ;
674674 assert_eq ! ( Context :: current( ) . get( ) , Some ( & ValueB ( stack_max_pos - 2 ) ) ) ;
675675 guards. push ( cx_guard) ;
676676 }
@@ -783,7 +783,6 @@ mod tests {
783783 /// 2. Values added during async operations do not affect parent context
784784 #[ tokio:: test]
785785 async fn test_async_context_propagation ( ) {
786-
787786 // A nested async operation we'll use to test propagation
788787 async fn nested_operation ( ) {
789788 // Verify we can see the parent context's value
@@ -795,7 +794,7 @@ mod tests {
795794
796795 // Create new context
797796 let cx_with_both = Context :: current ( )
798- . with_value ( ValueA ( 43 ) ) // override ValueA
797+ . with_value ( ValueA ( 43 ) ) // override ValueA
799798 . with_value ( ValueB ( 24 ) ) ; // Add new ValueB
800799
801800 // Run nested async operation with both values
@@ -827,8 +826,8 @@ mod tests {
827826 "New value should persist across await points"
828827 ) ;
829828 }
830- . with_context ( cx_with_both)
831- . await ;
829+ . with_context ( cx_with_both)
830+ . await ;
832831 }
833832
834833 // Set up initial context with ValueA
@@ -862,4 +861,35 @@ mod tests {
862861 "Current context should not have async operation's values"
863862 ) ;
864863 }
864+
865+ #[ tokio:: test]
866+ async fn test_out_of_order_context_detachment_futures ( ) {
867+ // This function returns a future, but doesn't await it
868+ // It will complete before the future that it creates.
869+ async fn create_a_future ( ) -> impl std:: future:: Future < Output = ( ) > {
870+ // Create a future that will do some work, referencing our current
871+ // context, but don't await it.
872+ async {
873+ let _guard = Context :: new ( ) . with_value ( ValueB ( 2 ) ) . attach ( ) ;
874+ // Longer work
875+ sleep ( Duration :: from_millis ( 50 ) ) . await ;
876+ }
877+ . with_context ( Context :: current ( ) )
878+ }
879+
880+ // Create our base context
881+ let parent_cx = Context :: new ( ) . with_value ( ValueA ( 42 ) ) ;
882+
883+ // await our nested function, which will create and detach a context
884+ let future = create_a_future ( ) . with_context ( parent_cx) . await ;
885+
886+ // Execute the future. The completion of the future will result in an out-of-order drop,
887+ // as the parent context created by create_a_future was already dropped earlier.
888+ future. await ;
889+
890+ // Nothing terrible (e.g., panics!) should happen, and we should definitely not have any
891+ // values attached to our current context that were set in the nested operations.
892+ assert_eq ! ( Context :: current( ) . get:: <ValueA >( ) , None ) ;
893+ assert_eq ! ( Context :: current( ) . get:: <ValueB >( ) , None ) ;
894+ }
865895}
0 commit comments