From 4a8c0c19dc9be3daad12af2cf61296653c98964f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 7 Mar 2026 20:09:06 +0000 Subject: [PATCH 1/2] test: add nested for-loop tests for task and async CE extensions Add a NestedLoops module to both TaskExtensions and AsyncExtensions test files covering: - Outer taskSeq (IAsyncEnumerable) + inner regular list - Outer taskSeq + inner regular array - Outer taskSeq + inner zipped array with tuple destructuring (reproducing the pattern from issue #269) - Outer taskSeq + inner taskSeq (nested async enumeration) - Three levels of nesting (task CE only) These tests document and guard the behaviour of nested iteration in both the task {} and async {} computation expressions when the outer sequence is an IAsyncEnumerable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../TaskSeq.AsyncExtensions.Tests.fs | 81 +++++++++++++++ .../TaskSeq.TaskExtensions.Tests.fs | 99 +++++++++++++++++++ 2 files changed, 180 insertions(+) diff --git a/src/FSharp.Control.TaskSeq.Test/TaskSeq.AsyncExtensions.Tests.fs b/src/FSharp.Control.TaskSeq.Test/TaskSeq.AsyncExtensions.Tests.fs index f36fe920..1ccb781d 100644 --- a/src/FSharp.Control.TaskSeq.Test/TaskSeq.AsyncExtensions.Tests.fs +++ b/src/FSharp.Control.TaskSeq.Test/TaskSeq.AsyncExtensions.Tests.fs @@ -141,3 +141,84 @@ module Other = disposed.Value |> should equal 1 sum |> should equal 42 } + +// Tests for nested for loops in the async CE with IAsyncEnumerable as the outer sequence. +// Related to: https://github.com/fsprojects/FSharp.Control.TaskSeq/issues/269 +module NestedLoops = + [] + let ``Async-for CE with nested regular list inside taskSeq loop`` () = async { + // outer: IAsyncEnumerable, inner: regular list + let outer = taskSeq { + yield [ 1; 2; 3 ] + yield [ 4; 5 ] + yield [ 6; 7; 8; 9; 10 ] + } + + let mutable sum = 0 + + for inner in outer do + for x in inner do + sum <- sum + x + + sum |> should equal 55 + } + + [] + let ``Async-for CE with nested array inside taskSeq loop`` () = async { + // outer: IAsyncEnumerable, inner: regular array + let outer = taskSeq { + yield [| 1; 2; 3 |] + yield [| 4; 5 |] + } + + let mutable sum = 0 + + for inner in outer do + for x in inner do + sum <- sum + x + + sum |> should equal 15 + } + + [] + let ``Async-for CE with nested tuple-destructuring array inside taskSeq loop`` () = async { + // outer: IAsyncEnumerable, inner: zipped array with tuple destructuring + // this pattern reproduces the scenario from issue #269 + let outer = taskSeq { yield [| 1; 2; 3 |] } + let mutable sum = 0 + + for arr in outer do + for (a, b) in Array.zip arr arr do + sum <- sum + a + b + + // (1+1) + (2+2) + (3+3) = 12 + sum |> should equal 12 + } + + [] + let ``Async-for CE with nested taskSeq inside taskSeq loop`` () = async { + // outer: IAsyncEnumerable>, inner: taskSeq + let inner1 = taskSeq { + yield 1 + yield 2 + yield 3 + } + + let inner2 = taskSeq { + yield 4 + yield 5 + } + + let outer = taskSeq { + yield inner1 + yield inner2 + } + + let mutable sum = 0 + + for inner in outer do + for x in inner do + sum <- sum + x + + sum |> should equal 15 + } diff --git a/src/FSharp.Control.TaskSeq.Test/TaskSeq.TaskExtensions.Tests.fs b/src/FSharp.Control.TaskSeq.Test/TaskSeq.TaskExtensions.Tests.fs index d50b8667..ad263f1d 100644 --- a/src/FSharp.Control.TaskSeq.Test/TaskSeq.TaskExtensions.Tests.fs +++ b/src/FSharp.Control.TaskSeq.Test/TaskSeq.TaskExtensions.Tests.fs @@ -140,3 +140,102 @@ module Other = disposed.Value |> should equal 1 sum |> should equal 42 } + +// Tests for nested for loops in the task CE with IAsyncEnumerable as the outer sequence. +// Related to: https://github.com/fsprojects/FSharp.Control.TaskSeq/issues/269 +module NestedLoops = + [] + let ``Task-for CE with nested regular list inside taskSeq loop`` () = task { + // outer: IAsyncEnumerable, inner: regular list + let outer = taskSeq { + yield [ 1; 2; 3 ] + yield [ 4; 5 ] + yield [ 6; 7; 8; 9; 10 ] + } + + let mutable sum = 0 + + for inner in outer do + for x in inner do + sum <- sum + x + + sum |> should equal 55 + } + + [] + let ``Task-for CE with nested array inside taskSeq loop`` () = task { + // outer: IAsyncEnumerable, inner: regular array + let outer = taskSeq { + yield [| 1; 2; 3 |] + yield [| 4; 5 |] + } + + let mutable sum = 0 + + for inner in outer do + for x in inner do + sum <- sum + x + + sum |> should equal 15 + } + + [] + let ``Task-for CE with nested tuple-destructuring array inside taskSeq loop`` () = task { + // outer: IAsyncEnumerable, inner: zipped array with tuple destructuring + // this pattern reproduces the scenario from issue #269 + let outer = taskSeq { yield [| 1; 2; 3 |] } + let mutable sum = 0 + + for arr in outer do + for (a, b) in Array.zip arr arr do + sum <- sum + a + b + + // (1+1) + (2+2) + (3+3) = 12 + sum |> should equal 12 + } + + [] + let ``Task-for CE with nested taskSeq inside taskSeq loop`` () = task { + // outer: IAsyncEnumerable>, inner: taskSeq + let inner1 = taskSeq { + yield 1 + yield 2 + yield 3 + } + + let inner2 = taskSeq { + yield 4 + yield 5 + } + + let outer = taskSeq { + yield inner1 + yield inner2 + } + + let mutable sum = 0 + + for inner in outer do + for x in inner do + sum <- sum + x + + sum |> should equal 15 + } + + [] + let ``Task-for CE with three levels of nesting`` () = task { + // outer: IAsyncEnumerable, mid: array, inner: array + let outer = taskSeq { + yield [| [| 1; 2 |]; [| 3; 4 |] |] + yield [| [| 5 |] |] + } + + let mutable sum = 0 + + for mid in outer do + for inner in mid do + for x in inner do + sum <- sum + x + + sum |> should equal 15 + } From 5ba5546dabbc6edca90c370ee81cf54051cda6e9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 7 Mar 2026 20:11:39 +0000 Subject: [PATCH 2/2] ci: trigger checks