diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ControlFlowExpressions/SequenceIteration/IEnumerableIterationGenericDisposal01.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ControlFlowExpressions/SequenceIteration/IEnumerableIterationGenericDisposal01.fs new file mode 100644 index 00000000000..e6b0b0f34f2 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ControlFlowExpressions/SequenceIteration/IEnumerableIterationGenericDisposal01.fs @@ -0,0 +1,70 @@ +// #Conformance #ControlFlow #Sequences #Regression #InterfacesAndImplementations +// Ensure generic IEnumerable iteration calls GetEnumerator and disposes enumerators via try/finally. + +open System +open System.Collections +open System.Collections.Generic + +type CountingEnumerable(values: int[]) = + static let mutable getEnumeratorCalls = 0 + static let mutable disposeCalls = 0 + + static member Reset() = + getEnumeratorCalls <- 0 + disposeCalls <- 0 + + static member GetEnumeratorCalls = getEnumeratorCalls + static member DisposeCalls = disposeCalls + + interface IEnumerable with + member _.GetEnumerator() = + getEnumeratorCalls <- getEnumeratorCalls + 1 + let mutable i = -1 + + { new IEnumerator with + member _.Current = values[i] + + interface IEnumerator with + member _.Current = box values[i] + member _.MoveNext() = + i <- i + 1 + i < values.Length + member _.Reset() = i <- -1 + + interface IDisposable with + member _.Dispose() = disposeCalls <- disposeCalls + 1 } + + interface IEnumerable with + member this.GetEnumerator() = + (this :> IEnumerable).GetEnumerator() :> IEnumerator + +let runSuccessfulIteration () = + CountingEnumerable.Reset() + + let enumerable = CountingEnumerable([| 1; 2; 3 |]) :> IEnumerable + let mutable sum = 0 + + for x in enumerable do + sum <- sum + x + + sum = 6 + && CountingEnumerable.GetEnumeratorCalls = 1 + && CountingEnumerable.DisposeCalls = 1 + +let runExceptionalIteration () = + CountingEnumerable.Reset() + + let enumerable = CountingEnumerable([| 1; 2; 3 |]) :> IEnumerable + + try + for x in enumerable do + if x = 2 then + failwith "boom" + with _ -> + () + + CountingEnumerable.GetEnumeratorCalls = 1 + && CountingEnumerable.DisposeCalls = 1 + +let ok = runSuccessfulIteration () && runExceptionalIteration () +exit (if ok then 0 else 1) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ControlFlowExpressions/SequenceIteration/SequenceIteration.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ControlFlowExpressions/SequenceIteration/SequenceIteration.fs index cef9f9b4abb..70713d2de19 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ControlFlowExpressions/SequenceIteration/SequenceIteration.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ControlFlowExpressions/SequenceIteration/SequenceIteration.fs @@ -9,7 +9,37 @@ open FSharp.Test.Compiler module SequenceIteration = // This test was automatically generated (moved from FSharpQA suite - Conformance/Expressions/ControlFlowExpressions/SequenceIteration) - + + let verifyCompileAndRun compilation = + compilation + |> asExe + |> withOptions ["--nowarn:3370"] + |> compileExeAndRun + + [] + let ``IEnumerableIteration01_fs`` compilation = + compilation + |> getCompilation + |> asFsx + |> verifyCompileAndRun + |> shouldSucceed + + [] + let ``IEnumerableIterationGenericDisposal01_fs`` compilation = + compilation + |> getCompilation + |> asFsx + |> verifyCompileAndRun + |> shouldSucceed + + [] + let ``E_BadIEnumerable01_fs`` compilation = + compilation + |> getCompilation + |> asFsx + |> typecheck + |> shouldFail + [] let ``W_IncompleteMatchFor01_fs`` compilation = compilation @@ -26,4 +56,3 @@ module SequenceIteration = (Warning 25, Line 22, Col 9, Line 22, Col 17, "Incomplete pattern matches on this expression. For example, the value 'None' may indicate a case not covered by the pattern(s).") (Warning 25, Line 27, Col 20, Line 27, Col 28, "Incomplete pattern matches on this expression. For example, the value 'None' may indicate a case not covered by the pattern(s).") ] -