@@ -558,54 +558,83 @@ private static bool QueueContinuationFollowUpActionIfNecessary<T, TOps>(T task,
558558#pragma warning disable CA1859
559559 // When a Task-returning thunk gets a continuation result
560560 // it calls here to make a Task that awaits on the current async state.
561- private static Task < T ? > FinalizeTaskReturningThunk < T > ( Continuation continuation )
561+ private static Task < T ? > FinalizeTaskReturningThunk < T > ( Continuation continuation , Exception ex )
562562 {
563- Continuation finalContinuation = new Continuation ( ) ;
564-
565- // Note that the exact location the return value is placed is tied
566- // into getAsyncResumptionStub in the VM, so do not change this
567- // without also changing that code (and the JIT).
568- if ( RuntimeHelpers . IsReferenceOrContainsReferences < T > ( ) )
563+ if ( continuation is not null )
569564 {
570- finalContinuation . Flags = CorInfoContinuationFlags . CORINFO_CONTINUATION_RESULT_IN_GCDATA | CorInfoContinuationFlags . CORINFO_CONTINUATION_NEEDS_EXCEPTION ;
571- finalContinuation . GCData = new object [ 1 ] ;
565+ Continuation finalContinuation = new Continuation ( ) ;
566+
567+ // Note that the exact location the return value is placed is tied
568+ // into getAsyncResumptionStub in the VM, so do not change this
569+ // without also changing that code (and the JIT).
570+ if ( RuntimeHelpers . IsReferenceOrContainsReferences < T > ( ) )
571+ {
572+ finalContinuation . Flags = CorInfoContinuationFlags . CORINFO_CONTINUATION_RESULT_IN_GCDATA | CorInfoContinuationFlags . CORINFO_CONTINUATION_NEEDS_EXCEPTION ;
573+ finalContinuation . GCData = new object [ 1 ] ;
574+ }
575+ else
576+ {
577+ finalContinuation . Flags = CorInfoContinuationFlags . CORINFO_CONTINUATION_NEEDS_EXCEPTION ;
578+ finalContinuation . Data = new byte [ Unsafe . SizeOf < T > ( ) ] ;
579+ }
580+
581+ continuation . Next = finalContinuation ;
582+
583+ ThunkTask < T ? > result = new ( ) ;
584+ result . HandleSuspended ( continuation ) ;
585+ return result ;
572586 }
573587 else
574588 {
575- finalContinuation . Flags = CorInfoContinuationFlags . CORINFO_CONTINUATION_NEEDS_EXCEPTION ;
576- finalContinuation . Data = new byte [ Unsafe . SizeOf < T > ( ) ] ;
589+ Task < T ? > task = new ( ) ;
590+ // Tail of AsyncTaskMethodBuilderT.SetException
591+ bool successfullySet = ex is OperationCanceledException oce ?
592+ task . TrySetCanceled ( oce . CancellationToken , oce ) :
593+ task . TrySetException ( ex ) ;
594+
595+ Debug . Assert ( successfullySet ) ;
596+ return task ;
577597 }
578-
579- continuation . Next = finalContinuation ;
580-
581- ThunkTask < T ? > result = new ( ) ;
582- result . HandleSuspended ( continuation ) ;
583- return result ;
584598 }
585599
586- private static Task FinalizeTaskReturningThunk ( Continuation continuation )
600+ private static Task FinalizeTaskReturningThunk ( Continuation continuation , Exception ex )
587601 {
588- Continuation finalContinuation = new Continuation
602+ if ( continuation is not null )
589603 {
590- Flags = CorInfoContinuationFlags . CORINFO_CONTINUATION_NEEDS_EXCEPTION ,
591- } ;
592- continuation . Next = finalContinuation ;
604+ Continuation finalContinuation = new Continuation
605+ {
606+ Flags = CorInfoContinuationFlags . CORINFO_CONTINUATION_NEEDS_EXCEPTION ,
607+ } ;
608+ continuation . Next = finalContinuation ;
593609
594- ThunkTask result = new ( ) ;
595- result . HandleSuspended ( continuation ) ;
596- return result ;
610+ ThunkTask result = new ( ) ;
611+ result . HandleSuspended ( continuation ) ;
612+ return result ;
613+ }
614+ else
615+ {
616+ Debug . Assert ( ex is not null ) ;
617+ Task task = new ( ) ;
618+ // Tail of AsyncTaskMethodBuilderT.SetException
619+ bool successfullySet = ex is OperationCanceledException oce ?
620+ task . TrySetCanceled ( oce . CancellationToken , oce ) :
621+ task . TrySetException ( ex ) ;
622+
623+ Debug . Assert ( successfullySet ) ;
624+ return task ;
625+ }
597626 }
598627
599- private static ValueTask < T ? > FinalizeValueTaskReturningThunk < T > ( Continuation continuation )
628+ private static ValueTask < T ? > FinalizeValueTaskReturningThunk < T > ( Continuation continuation , Exception ex )
600629 {
601630 // We only come to these methods in the expensive case (already
602631 // suspended), so ValueTask optimization here is not relevant.
603- return new ValueTask < T ? > ( FinalizeTaskReturningThunk < T > ( continuation ) ) ;
632+ return new ValueTask < T ? > ( FinalizeTaskReturningThunk < T > ( continuation , ex ) ) ;
604633 }
605634
606- private static ValueTask FinalizeValueTaskReturningThunk ( Continuation continuation )
635+ private static ValueTask FinalizeValueTaskReturningThunk ( Continuation continuation , Exception ex )
607636 {
608- return new ValueTask ( FinalizeTaskReturningThunk ( continuation ) ) ;
637+ return new ValueTask ( FinalizeTaskReturningThunk ( continuation , ex ) ) ;
609638 }
610639
611640 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
0 commit comments