Skip to content

Commit c1b2c41

Browse files
committed
Remove ValueTask, now handled by ^TaskLike, see comments in code
1 parent 5173bbd commit c1b2c41

File tree

2 files changed

+25
-33
lines changed

2 files changed

+25
-33
lines changed

src/FSharp.Control.TaskSeq.Test/FSharp.Control.TaskSeq.Test.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
<Compile Include="TaskSeq.AsyncExtensions.Tests.fs" />
5050
<Compile Include="TaskSeq.TaskExtensions.Tests.fs" />
5151
<Compile Include="TaskSeq.Do.Tests.fs" />
52+
<Compile Include="TaskSeq.Let.Tests.fs" />
5253
<Compile Include="TaskSeq.Using.Tests.fs" />
5354
<Compile Include="Program.fs" />
5455
</ItemGroup>

src/FSharp.Control.TaskSeq/TaskSeqBuilder.fs

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -524,11 +524,19 @@ module LowPriority =
524524
//
525525
// Note: we cannot place _.Bind directly on the type, as the NoEagerXXX attribute
526526
// has no effect, and each use of `do!` will give an overload error (because the
527-
// `TaskLike` type and the `Task<_>` type are interchangeable).
527+
// `TaskLike` type and the `Task<_>` type are partially interchangeable, see notes there).
528528
//
529529
// However, we cannot unify these two methods, because Task<_> inherits from Task (non-generic)
530530
// and we need a way to distinguish these two methods.
531531
//
532+
// Types handled:
533+
// - ValueTask (non-generic, because it implements GetResult() -> unit)
534+
// - ValueTask<'T> (because it implements GetResult() -> 'TResult)
535+
// - Task (non-generic, because it implements GetResult() -> unit)
536+
// - any other type that implements GetAwaiter()
537+
//
538+
// Not handled:
539+
// - Task<'T> (because it only implements GetResult() -> unit, not GetResult() -> 'TResult)
532540

533541
[<NoEagerConstraintApplication>]
534542
member inline _.Bind< ^TaskLike, 'TResult1, 'TResult2, ^Awaiter, 'TOverall
@@ -545,24 +553,24 @@ module LowPriority =
545553
let mutable awaiter = (^TaskLike: (member GetAwaiter: unit -> ^Awaiter) (task))
546554
let mutable __stack_fin = true
547555

548-
Debug.logInfo "at TaskLike bind!"
556+
Debug.logInfo "at TaskLike bind"
549557

550558
if not (^Awaiter: (member get_IsCompleted: unit -> bool) (awaiter)) then
551559
// This will yield with __stack_fin2 = false
552560
// This will resume with __stack_fin2 = true
553561
let __stack_fin2 = ResumableCode.Yield().Invoke(&sm)
554562
__stack_fin <- __stack_fin2
555563

556-
Debug.logInfo ("at TaskLike bind!: with __stack_fin = ", __stack_fin)
557-
Debug.logInfo ("at TaskLike bind!: this.completed = ", sm.Data.completed)
564+
Debug.logInfo ("at TaskLike bind: with __stack_fin = ", __stack_fin)
565+
Debug.logInfo ("at TaskLike bind: this.completed = ", sm.Data.completed)
558566

559567
if __stack_fin then
560568
Debug.logInfo "at TaskLike bind!: finished awaiting, calling continuation"
561569
let result = (^Awaiter: (member GetResult: unit -> 'TResult1) (awaiter))
562570
(continuation result).Invoke(&sm)
563571

564572
else
565-
Debug.logInfo "at TaskLike bind!: await further"
573+
Debug.logInfo "at TaskLike bind: await further"
566574

567575
sm.Data.awaiter <- awaiter
568576
sm.Data.current <- ValueNone
@@ -615,9 +623,19 @@ module MediumPriority =
615623
module HighPriority =
616624
type TaskSeqBuilder with
617625

626+
//
627+
// Notes Task:
628+
// - Task<_> implements GetAwaiter(), but TaskAwaiter does not implement GetResult() -> TResult
629+
// - Instead, it has GetResult() -> unit, which is not '^TaskLike'
630+
// - Conclusion: we need an extra high-prio overload to allow support for Task<_>
631+
//
632+
// Notes ValueTask:
633+
// - In contrast, ValueTask<_> *does have* GetResult() -> 'TResult
634+
// - Conclusion: we do not need an extra overload anymore for ValueTask
635+
//
618636
member inline _.Bind(task: Task<'TResult1>, continuation: ('TResult1 -> TaskSeqCode<'T>)) : TaskSeqCode<'T> =
619637
TaskSeqCode<'T>(fun sm ->
620-
let mutable awaiter = task.GetAwaiter()
638+
let mutable awaiter: TaskAwaiter<'TResult1> = task.GetAwaiter()
621639
let mutable __stack_fin = true
622640

623641
Debug.logInfo "at Bind"
@@ -642,30 +660,3 @@ module HighPriority =
642660
sm.Data.awaiter <- awaiter
643661
sm.Data.current <- ValueNone
644662
false)
645-
646-
member inline _.Bind
647-
(
648-
task: ValueTask<'TResult1>,
649-
continuation: ('TResult1 -> TaskSeqCode<'T>)
650-
) : TaskSeqCode<'T> =
651-
TaskSeqCode<'T>(fun sm ->
652-
let mutable awaiter = task.GetAwaiter()
653-
let mutable __stack_fin = true
654-
655-
Debug.logInfo "at BindV"
656-
657-
if not awaiter.IsCompleted then
658-
// This will yield with __stack_fin2 = false
659-
// This will resume with __stack_fin2 = true
660-
let __stack_fin2 = ResumableCode.Yield().Invoke(&sm)
661-
__stack_fin <- __stack_fin2
662-
663-
if __stack_fin then
664-
let result = awaiter.GetResult()
665-
(continuation result).Invoke(&sm)
666-
else
667-
Debug.logInfo "at BindV: calling AwaitUnsafeOnCompleted"
668-
669-
sm.Data.awaiter <- awaiter
670-
sm.Data.current <- ValueNone
671-
false)

0 commit comments

Comments
 (0)