Skip to content

Commit 22eb612

Browse files
authored
Merge branch 'main' into patch-2
2 parents ac21db4 + 0ee794b commit 22eb612

File tree

10 files changed

+82
-69
lines changed

10 files changed

+82
-69
lines changed

.github/workflows/test-report.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: ci-report
2+
3+
# See Dorny instructions for why we need a separate yaml for creating a test report
4+
# for public repositories that accept forks:
5+
# https://github.com/dorny/test-reporter#recommended-setup-for-public-repositories
6+
7+
on:
8+
workflow_run:
9+
workflows: ['ci-test'] # runs after CI workflow
10+
types:
11+
- completed
12+
jobs:
13+
test-report-release:
14+
runs-on: windows-latest
15+
steps:
16+
- uses: dorny/test-reporter@v1
17+
with:
18+
artifact: test-results-release # artifact name
19+
name: Report release tests # Name of the check run which will be created
20+
path: '*.trx' # Path to test results (inside artifact .zip)
21+
reporter: dotnet-trx # Format of test results
22+
23+
test-report-debug:
24+
runs-on: windows-latest
25+
steps:
26+
- uses: dorny/test-reporter@v1
27+
with:
28+
artifact: test-results-debug # artifact name
29+
name: Report debug tests # Name of the check run which will be created
30+
path: '*.trx' # Path to test results (inside artifact .zip)
31+
reporter: dotnet-trx # Format of test results

.github/workflows/test.yaml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@ name: ci-test
22

33
on: [pull_request]
44

5-
permissions:
6-
id-token: write
7-
contents: read
8-
checks: write
9-
105
jobs:
116
test-release:
127
name: Test Release Build
@@ -17,20 +12,23 @@ jobs:
1712
uses: actions/checkout@v3
1813
with:
1914
fetch-depth: 0
15+
2016
# setup dotnet based on global.json
2117
- name: setup-dotnet
2218
uses: actions/setup-dotnet@v3
19+
2320
# build it, test it
2421
- name: Run dotnet test - release
2522
run: ./build.cmd ci -release
26-
- name: Publish test results - release
27-
uses: dorny/test-reporter@v1
28-
if: always()
23+
24+
# upload test results
25+
- uses: actions/upload-artifact@v2
26+
if: success() || failure()
2927
with:
30-
name: Report release tests
28+
name: test-results-release
3129
# this path glob pattern requires forward slashes!
3230
path: ./src/FSharp.Control.TaskSeq.Test/TestResults/test-results-release.trx
33-
reporter: dotnet-trx
31+
3432

3533
test-debug:
3634
name: Test Debug Build
@@ -41,17 +39,19 @@ jobs:
4139
uses: actions/checkout@v3
4240
with:
4341
fetch-depth: 0
42+
4443
# setup dotnet based on global.json
4544
- name: setup-dotnet
4645
uses: actions/setup-dotnet@v3
46+
4747
# build it, test it
4848
- name: Run dotnet test - debug
4949
run: ./build.cmd ci -debug
50-
- name: Publish test results - debug
51-
uses: dorny/test-reporter@v1
52-
if: always()
50+
51+
# upload test results
52+
- uses: actions/upload-artifact@v2
53+
if: success() || failure()
5354
with:
54-
name: Report debug tests
55+
name: test-results-debug
5556
# this path glob pattern requires forward slashes!
5657
path: ./src/FSharp.Control.TaskSeq.Test/TestResults/test-results-debug.trx
57-
reporter: dotnet-trx

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
<!-- align test project with minimal required version for TaskSeq -->
5555
<!-- we use 6.0.3 here and not 6.0.2 because TaskResult lib requires it-->
5656
<PackageReference Update="FSharp.Core" Version="6.0.3" />
57-
<PackageReference Include="FsToolkit.ErrorHandling.TaskResult" Version="3.2.0" />
57+
<PackageReference Include="FsToolkit.ErrorHandling.TaskResult" Version="4.0.0" />
5858
<PackageReference Include="FsUnit.xUnit" Version="5.1.0" />
5959
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
6060
<PackageReference Include="xunit" Version="2.4.2" />

src/FSharp.Control.TaskSeq.Test/TaskSeq.Zip.Tests.fs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -132,32 +132,3 @@ module Other =
132132

133133
combined |> should equal [| ("one", 42L); ("two", 43L) |]
134134
}
135-
136-
[<Theory; InlineData true; InlineData false>]
137-
let ``TaskSeq-zip throws on unequal lengths, variant`` leftThrows = task {
138-
let long = Gen.sideEffectTaskSeq 11
139-
let short = Gen.sideEffectTaskSeq 10
140-
141-
let combined =
142-
if leftThrows then
143-
TaskSeq.zip short long
144-
else
145-
TaskSeq.zip long short
146-
147-
fun () -> TaskSeq.toArrayAsync combined |> Task.ignore
148-
|> should throwAsyncExact typeof<ArgumentException>
149-
}
150-
151-
[<Theory; InlineData true; InlineData false>]
152-
let ``TaskSeq-zip throws on unequal lengths with empty seq`` leftThrows = task {
153-
let one = Gen.sideEffectTaskSeq 1
154-
155-
let combined =
156-
if leftThrows then
157-
TaskSeq.zip TaskSeq.empty one
158-
else
159-
TaskSeq.zip one TaskSeq.empty
160-
161-
fun () -> TaskSeq.toArrayAsync combined |> Task.ignore
162-
|> should throwAsyncExact typeof<ArgumentException>
163-
}

src/FSharp.Control.TaskSeq.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
2121
..\.github\dependabot.yml = ..\.github\dependabot.yml
2222
..\.github\workflows\main.yaml = ..\.github\workflows\main.yaml
2323
..\.github\workflows\publish.yaml = ..\.github\workflows\publish.yaml
24+
..\.github\workflows\test-report.yaml = ..\.github\workflows\test-report.yaml
2425
..\.github\workflows\test.yaml = ..\.github\workflows\test.yaml
2526
EndProjectSection
2627
EndProject

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ Generates optimized IL code through the new resumable state machines, and comes
2323
<PackageReadmeFile>nuget-package-readme.md</PackageReadmeFile>
2424
<PackageReleaseNotes>
2525
Release notes:
26+
0.2.3
27+
- improve TaskSeq.empty by not relying on resumable state, #89
28+
- do not throw exception for unequal lengths in TaskSeq.zip, fixes #32
2629
0.2.2
2730
- removes TaskSeq.toSeqCachedAsync, which was incorrectly named. Use toSeq or toListAsync instead.
2831
- renames TaskSeq.toSeqCached to TaskSeq.toSeq, which was its actual operational behavior.

src/FSharp.Control.TaskSeq/TaskSeq.fs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@ module TaskSeq =
1111
// Just for convenience
1212
module Internal = TaskSeqInternal
1313

14-
let empty<'T> = taskSeq {
15-
for c: 'T in [] do
16-
yield c
17-
}
18-
14+
let empty<'T> =
15+
{ new IAsyncEnumerable<'T> with
16+
member _.GetAsyncEnumerator(_) =
17+
{ new IAsyncEnumerator<'T> with
18+
member _.MoveNextAsync() = ValueTask.False
19+
member _.Current = Unchecked.defaultof<'T>
20+
member _.DisposeAsync() = ValueTask.CompletedTask
21+
}
22+
}
23+
1924
let singleton (source: 'T) =
2025
{ new IAsyncEnumerable<'T> with
2126
member _.GetAsyncEnumerator(_) =
@@ -27,8 +32,6 @@ module TaskSeq =
2732
r
2833
member _.get_Current () : 'T = if started then source else invalidOp "Enumeration has not started. Call MoveNextAsync."
2934
member _.DisposeAsync () = ValueTask.CompletedTask
30-
}
31-
}
3235

3336
let isEmpty source = Internal.isEmpty source
3437

src/FSharp.Control.TaskSeq/TaskSeqBuilder.fs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ open System.Threading.Tasks.Sources
1313

1414
open FSharp.Core.CompilerServices
1515
open FSharp.Core.CompilerServices.StateMachineHelpers
16+
open FSharp.Control
1617

1718

1819
[<AutoOpen>]
@@ -279,14 +280,14 @@ and [<NoComparison; NoEquality>] TaskSeq<'Machine, 'T
279280
if this._machine.ResumptionPoint = -1 then // can't use as IAsyncEnumerator before IAsyncEnumerable
280281
logInfo "at MoveNextAsync: Resumption point = -1"
281282

282-
ValueTask<bool>()
283+
ValueTask.False
283284

284285
elif this._machine.Data.completed then
285286
logInfo "at MoveNextAsync: completed = true"
286287

287288
// return False when beyond the last item
288289
this._machine.Data.promiseOfValueOrEnd.Reset()
289-
ValueTask<bool>()
290+
ValueTask.False
290291

291292
else
292293
logInfo "at MoveNextAsync: normal resumption scenario"
@@ -343,18 +344,18 @@ and [<NoComparison; NoEquality>] TaskSeq<'Machine, 'T
343344
// the Current value
344345
data.current <- ValueNone
345346

346-
ValueTask<bool>(result)
347+
ValueTask.FromResult result
347348

348349
| ValueTaskSourceStatus.Faulted
349350
| ValueTaskSourceStatus.Canceled
350351
| ValueTaskSourceStatus.Pending as state ->
351352
logInfo ("at MoveNextAsyncResult: case ", state)
352353

353-
ValueTask<bool>(this, version) // uses IValueTaskSource<'T>
354+
ValueTask.ofIValueTaskSource this version
354355
| _ ->
355356
logInfo "at MoveNextAsyncResult: Unexpected state"
356357
// assume it's a possibly new, not yet supported case, treat as default
357-
ValueTask<bool>(this, version) // uses IValueTaskSource<'T>
358+
ValueTask.ofIValueTaskSource this version
358359

359360
and TaskSeqCode<'T> = ResumableCode<TaskSeqStateMachineData<'T>, unit>
360361
and TaskSeqStateMachine<'T> = ResumableStateMachine<TaskSeqStateMachineData<'T>>

src/FSharp.Control.TaskSeq/TaskSeqInternal.fs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -272,28 +272,17 @@ module internal TaskSeqInternal =
272272
}
273273

274274
let zip (source1: taskSeq<_>) (source2: taskSeq<_>) = taskSeq {
275-
let inline validate step1 step2 =
276-
if step1 <> step2 then
277-
if step1 then
278-
invalidArg "taskSequence1" "The task sequences have different lengths."
279-
280-
if step2 then
281-
invalidArg "taskSequence2" "The task sequences have different lengths."
282-
283-
284275
use e1 = source1.GetAsyncEnumerator(CancellationToken())
285276
use e2 = source2.GetAsyncEnumerator(CancellationToken())
286277
let mutable go = true
287278
let! step1 = e1.MoveNextAsync()
288279
let! step2 = e2.MoveNextAsync()
289280
go <- step1 && step2
290-
validate step1 step2
291281

292282
while go do
293283
yield e1.Current, e2.Current
294284
let! step1 = e1.MoveNextAsync()
295285
let! step2 = e2.MoveNextAsync()
296-
validate step1 step2
297286
go <- step1 && step2
298287
}
299288

src/FSharp.Control.TaskSeq/Utils.fs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,26 @@ open System.Threading.Tasks
55
[<AutoOpen>]
66
module ValueTaskExtensions =
77
/// Extensions for ValueTask that are not available in NetStandard 2.1, but are
8-
/// available in .NET 5+.
8+
/// available in .NET 5+. We put them in Extension space to mimic the behavior of NetStandard 2.1
99
type ValueTask with
1010

1111
/// (Extension member) Gets a task that has already completed successfully.
1212
static member inline CompletedTask = Unchecked.defaultof<ValueTask>
1313

14+
15+
module ValueTask =
16+
/// A successfully completed ValueTask of boolean that has the value false.
17+
let False = ValueTask<bool>()
18+
19+
/// A successfully completed ValueTask of boolean that has the value true.
20+
let True = ValueTask<bool> true
21+
22+
/// Creates a ValueTask with the supplied result of the successful operation.
23+
let inline FromResult (x: 'T) = ValueTask<'T> x
24+
25+
/// Creates a ValueTask with an IValueTaskSource representing the operation
26+
let inline ofIValueTaskSource taskSource version = ValueTask<bool>(taskSource, version)
27+
1428
module Task =
1529
/// Convert an Async<'T> into a Task<'T>
1630
let inline ofAsync (async: Async<'T>) = task { return! async }

0 commit comments

Comments
 (0)