Skip to content

Commit bff7135

Browse files
committed
Use FromExceptions, update raise and ignore
1 parent 2b382bc commit bff7135

File tree

2 files changed

+49
-58
lines changed

2 files changed

+49
-58
lines changed

src/FSharpPlus/Extensions/Task.fs

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,6 @@ module Task =
1111
open System.Threading
1212
open System.Threading.Tasks
1313
open FSharpPlus.Internals.Errors
14-
15-
module private Unit =
16-
/// Active pattern to match the state of a completed Task
17-
let (|Succeeded|Canceled|Faulted|) (t: Task) =
18-
if t.IsCompletedSuccessfully then Succeeded
19-
elif t.IsFaulted then Faulted (Unchecked.nonNull (t.Exception))
20-
elif t.IsCanceled then Canceled
21-
else invalidOp "The task is not yet completed."
2214

2315
/// Active pattern to match the state of a completed Task
2416
let inline internal (|Succeeded|Canceled|Faulted|) (t: Task<'a>) =
@@ -37,23 +29,19 @@ module Task =
3729
/// <returns>A Task that is completed successfully with the specified value.</returns>
3830
let result (value: 'T) : Task<'T> = Task.FromResult value
3931

40-
/// <summary>Creates a Task that's completed unsuccessfully with the specified exception.</summary>
41-
/// <param name="exn">The exception to be raised.</param>
42-
/// <returns>A Task that is completed unsuccessfully with the specified exception.</returns>
32+
/// <summary>Creates a Task that's completed unsuccessfully with the specified exceptions.</summary>
33+
/// <param name="exn">The AggregateException to be raised.</param>
34+
/// <returns>A Task that is completed unsuccessfully with the specified exceptions.</returns>
4335
/// <remarks>
44-
/// If the exception is not an AggregateException it is wrapped into one.
45-
/// Prefer this function over Task.FromException as it handles AggregateExceptions correctly.
36+
/// Prefer this function to handle AggregateExceptions over Task.FromException as it handles them correctly.
4637
/// </remarks>
47-
let raise<'T> (exn: exn) : Task<'T> =
48-
match exn with
49-
// AggregateException with multiple exceptions - use TCS
50-
| :? AggregateException as agg when agg.InnerExceptions.Count > 1 ->
38+
let internal FromExceptions<'T> (aex: AggregateException) : Task<'T> =
39+
match aex with
40+
| agg when agg.InnerExceptions.Count = 1 -> Task.FromException<'T> agg.InnerExceptions[0]
41+
| agg ->
5142
let tcs = TaskCompletionSource<'T> ()
5243
tcs.SetException agg.InnerExceptions
5344
tcs.Task
54-
// Single exception / Single non-aggregate exception -> use optimized path
55-
| :? AggregateException as agg -> Task.FromException<'T> agg.InnerExceptions[0]
56-
| exn -> Task.FromException<'T> exn
5745

5846
let private cancellationTokenSingleton = CancellationToken true
5947

@@ -85,10 +73,10 @@ module Task =
8573

8674
if x.IsCompleted && y.IsCompleted then
8775
match x, y with
88-
| Succeeded r1, Succeeded r2 -> try result (mapper r1 r2) with e -> raise e
89-
| Succeeded _ , Faulted exn -> raise exn
76+
| Succeeded r1, Succeeded r2 -> try result (mapper r1 r2) with e -> Task.FromException<_> e
77+
| Succeeded _ , Faulted exn -> FromExceptions exn
9078
| Succeeded _ , Canceled -> canceled
91-
| Faulted exn , _ -> raise exn
79+
| Faulted exn , _ -> FromExceptions exn
9280
| Canceled , _ -> canceled
9381
else
9482
let tcs = TaskCompletionSource<'U> ()
@@ -392,23 +380,22 @@ module Task =
392380
}
393381

394382
/// <summary>Creates a task that ignores the result of the source task.</summary>
383+
/// <param name="source">The source Task.</param>
384+
/// <returns>A Task that completes when the source completes.</returns>
395385
/// <remarks>It can be used to convert non-generic Task to unit Task.</remarks>
396-
let ignore (task: Task) =
397-
let task = nullArgCheck (nameof task) task
398-
399-
if task.IsCompleted then
400-
let t = result ()
401-
match task with
402-
| Unit.Succeeded -> t
403-
| Unit.Faulted e -> raise<unit> e
404-
| Unit.Canceled -> canceled<unit>
386+
let ignore (source: Task) =
387+
let source = nullArgCheck (nameof source) source
388+
389+
if source.IsCompletedSuccessfully then result ()
390+
elif source.IsFaulted then FromExceptions (Unchecked.nonNull source.Exception)
391+
elif source.IsCanceled then canceled
405392
else
406393
let tcs = TaskCompletionSource<unit> ()
407-
let k = function
408-
| Unit.Succeeded -> tcs.SetResult ()
409-
| Unit.Faulted e -> tcs.SetException e.InnerExceptions
410-
| Unit.Canceled -> tcs.SetCanceled ()
411-
task.ContinueWith k |> ignore
394+
let k (t: Task) : unit =
395+
if t.IsCanceled then tcs.SetCanceled ()
396+
elif t.IsFaulted then tcs.SetException (Unchecked.nonNull source.Exception).InnerExceptions
397+
else tcs.SetResult ()
398+
source.ContinueWith k |> ignore
412399
tcs.Task
413400

414401
[<ObsoleteAttribute("Swap parameters")>]
@@ -452,7 +439,10 @@ module Task =
452439

453440
orElseWith (fun _ -> fallbackTask) source
454441

455-
442+
/// <summary>Creates a Task that's completed unsuccessfully with the specified exception.</summary>
443+
/// <param name="exn">The exception to be raised.</param>
444+
/// <returns>A Task that is completed unsuccessfully with the specified exception.</returns>
445+
let raise<'T> (exn: exn) : Task<'T> = Task.FromException<'T> exn
456446

457447

458448
/// Workaround to fix signatures without breaking binary compatibility.

src/FSharpPlus/Extensions/ValueTask.fs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,19 @@ module ValueTask =
4343
ValueTask<'T> tcs.Task
4444
#endif
4545

46-
/// <summary>Creates a ValueTask that's completed unsuccessfully with the specified exception.</summary>
47-
/// <param name="exn">The exception to be raised.</param>
48-
/// <returns>A ValueTask that is completed unsuccessfully with the specified exception.</returns>
46+
/// <summary>Creates a Task that's completed unsuccessfully with the specified exceptions.</summary>
47+
/// <param name="exn">The AggregateException to be raised.</param>
48+
/// <returns>A Task that is completed unsuccessfully with the specified exceptions.</returns>
4949
/// <remarks>
50-
/// If the exception is not an AggregateException it is wrapped into one.
51-
/// Prefer this function over ValueTask.FromException as it handles AggregateExceptions correctly.
50+
/// Prefer this function to handle AggregateExceptions over Task.FromException as it handles them correctly.
5251
/// </remarks>
53-
let raise<'T> (exn: exn) : ValueTask<'T> =
54-
match exn with
55-
| :? AggregateException as agg when agg.InnerExceptions.Count > 1 ->
52+
let internal FromExceptions<'T> (aex: AggregateException) : ValueTask<'T> =
53+
match aex with
54+
| agg when agg.InnerExceptions.Count = 1 -> ValueTask.FromException<'T> agg.InnerExceptions[0]
55+
| agg ->
5656
let tcs = TaskCompletionSource<'T> ()
5757
tcs.SetException agg.InnerExceptions
5858
ValueTask<'T> tcs.Task
59-
| :? AggregateException as agg -> ValueTask.FromException<'T> agg.InnerExceptions[0]
60-
| exn -> ValueTask.FromException<'T> exn
6159

6260
let private cancellationTokenSingleton = CancellationToken true
6361

@@ -241,22 +239,20 @@ module ValueTask =
241239
} |> ValueTask<'U>
242240

243241
/// <summary>Creates a ValueTask that ignores the result of the source ValueTask.</summary>
242+
/// <param name="source">The source ValueTask.</param>
243+
/// <returns>A ValueTask that completes when the source completes.</returns>
244244
/// <remarks>It can be used to convert non-generic ValueTask to unit ValueTask.</remarks>
245245
let ignore (source: ValueTask) : ValueTask<unit> =
246246
if source.IsCompleted then Unchecked.defaultof<_>
247-
elif source.IsFaulted then raise (Unchecked.nonNull (source.AsTask().Exception))
247+
elif source.IsFaulted then FromExceptions (Unchecked.nonNull (source.AsTask().Exception))
248248
elif source.IsCanceled then canceled
249249
else
250250
let tcs = TaskCompletionSource<unit> ()
251-
if source.IsFaulted then tcs.SetException (Unchecked.nonNull (source.AsTask().Exception)).InnerExceptions
252-
elif source.IsCanceled then tcs.SetCanceled ()
253-
else
254-
let k (t: ValueTask) : unit =
255-
if t.IsCanceled then tcs.SetCanceled ()
256-
elif t.IsFaulted then tcs.SetException (Unchecked.nonNull (source.AsTask().Exception)).InnerExceptions
257-
else tcs.SetResult ()
258-
if source.IsCompleted then k source
259-
else source.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted (fun () -> k source)
251+
let k (t: ValueTask) : unit =
252+
if t.IsCanceled then tcs.SetCanceled ()
253+
elif t.IsFaulted then tcs.SetException (Unchecked.nonNull (source.AsTask().Exception)).InnerExceptions
254+
else tcs.SetResult ()
255+
source.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted (fun () -> k source)
260256
ValueTask<unit> tcs.Task
261257

262258
/// Used to de-sugar try .. with .. blocks in Computation Expressions.
@@ -297,4 +293,9 @@ module ValueTask =
297293
/// <returns>The option if the option is Some, else the alternate option.</returns>
298294
let orElse (fallbackValueTask: ValueTask<'T>) (source: ValueTask<'T>) : ValueTask<'T> = orElseWith (fun _ -> fallbackValueTask) source
299295

296+
/// <summary>Creates a ValueTask that's completed unsuccessfully with the specified exception.</summary>
297+
/// <param name="exn">The exception to be raised.</param>
298+
/// <returns>A ValueTask that is completed unsuccessfully with the specified exception.</returns>
299+
let raise<'T> (exn: exn) : ValueTask<'T> = ValueTask.FromException<'T> exn
300+
300301
#endif

0 commit comments

Comments
 (0)