From bd6ebe28eca267573d7828efa98036c571f80154 Mon Sep 17 00:00:00 2001 From: Rodrigo Vidal Date: Wed, 6 May 2026 00:33:23 +0100 Subject: [PATCH] Add IL coverage for foreach iterable shapes Co-authored-by: multica-agent --- .../EmittedIL/ForLoop/ForLoop.fs | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/ForLoop/ForLoop.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/ForLoop/ForLoop.fs index c7b13a4e60a..8da84c3a67f 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/ForLoop/ForLoop.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/ForLoop/ForLoop.fs @@ -222,3 +222,135 @@ module ForLoop = compilation |> getCompilation |> verifyCompilation + + [] + let ``ForEach over arrays uses index-based IL`` () = + let result = + FSharp """ +module Test + +let sumArray (xs: int[]) = + let mutable acc = 0 + for x in xs do + acc <- acc + x + acc +""" + |> asLibrary + |> withOptimize + |> compile + |> shouldSucceed + |> verifyILContains [ + "ldelem.i4" + "ldlen" + ] + |> shouldSucceed + + result |> verifyILNotPresent [ + "GetEnumerator()" + ] + + [] + let ``ForEach over lists uses list traversal IL`` () = + let result = + FSharp """ +module Test + +let sumList (xs: int list) = + let mutable acc = 0 + for x in xs do + acc <- acc + x + acc +""" + |> asLibrary + |> withOptimize + |> compile + |> shouldSucceed + |> verifyILContains [ + "FSharpList`1::get_TailOrNull()" + "FSharpList`1::get_HeadOrDefault()" + ] + |> shouldSucceed + + result |> verifyILNotPresent [ + "GetEnumerator()" + ] + + [] + let ``ForEach over ranges uses integer loop IL`` () = + let result = + FSharp """ +module Test + +let sumRange start finish = + let mutable acc = 0 + for x in start .. finish do + acc <- acc + x + acc +""" + |> asLibrary + |> withOptimize + |> compile + |> shouldSucceed + |> verifyILContains [ + "ldc.i4.1" + "add" + ] + |> shouldSucceed + + result |> verifyILNotPresent [ + "GetEnumerator()" + ] + + [] + let ``ForEach over sequences uses enumerator IL`` () = + FSharp """ +module Test + +let sumSeq (xs: int seq) = + let mutable acc = 0 + for x in xs do + acc <- acc + x + acc +""" + |> asLibrary + |> withOptimize + |> compile + |> shouldSucceed + |> verifyILContains [ + "System.Collections.Generic.IEnumerable`1::GetEnumerator()" + "System.Collections.IEnumerator::MoveNext()" + "System.IDisposable::Dispose()" + ] + |> shouldSucceed + + [] + let ``ForEach over custom IEnumerable uses interface enumerator IL`` () = + FSharp """ +module Test + +open System.Collections +open System.Collections.Generic + +type CustomEnumerable(items: int[]) = + interface IEnumerable with + member _.GetEnumerator() = (items :> IEnumerable).GetEnumerator() + + interface IEnumerable with + member _.GetEnumerator() = (items :> IEnumerable).GetEnumerator() + +let sumCustom (xs: CustomEnumerable) = + let mutable acc = 0 + for x in xs do + acc <- acc + x + acc +""" + |> asLibrary + |> withOptimize + |> compile + |> shouldSucceed + |> verifyILContains [ + "System.Collections.Generic.IEnumerable`1::GetEnumerator()" + "System.Collections.IEnumerator::MoveNext()" + "System.IDisposable::Dispose()" + ] + |> shouldSucceed