From 6ba4d2c672151596086a71e132ffee73b8ae91af Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 16 Oct 2025 09:16:14 +0000
Subject: [PATCH 1/2] Initial plan
From fd8508f58f0eff6eb6c8f224341467e83357ce07 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 16 Oct 2025 09:50:56 +0000
Subject: [PATCH 2/2] Add FSharpPlus regression tests for F# 9 issues
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
---
.../FSharp.Compiler.ComponentTests.fsproj | 1 +
.../Language/FSharpPlusRegressionTests.fs | 130 ++++++++++++++++++
2 files changed, 131 insertions(+)
create mode 100644 tests/FSharp.Compiler.ComponentTests/Language/FSharpPlusRegressionTests.fs
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 29847415be2..c3641d31f65 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -234,6 +234,7 @@
+
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/FSharpPlusRegressionTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/FSharpPlusRegressionTests.fs
new file mode 100644
index 00000000000..5aa448516d4
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Language/FSharpPlusRegressionTests.fs
@@ -0,0 +1,130 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace Language
+
+open System
+open Xunit
+open FSharp.Test.ScriptHelpers
+open FSharp.Compiler.Diagnostics
+
+module FSharpPlusRegressionTests =
+
+ ///
+ /// Regression test for FSharpPlus issue #613 - monad.plus usage scenario.
+ /// This test reproduces a consumer-side failure where using monad.plus in F# 9
+ /// causes compilation issues. The code should compile successfully.
+ /// Issue: https://github.com/fsprojects/FSharpPlus/issues/613
+ ///
+ []
+ []
+ []
+ []
+ let ``monad.plus usage should compile successfully`` (langVersion: string, [] additionalArgs: string[]) =
+ let allArgs = Array.concat [[| "--langversion:" + langVersion |]; additionalArgs]
+ use script = new FSharpScript(additionalArgs = allArgs, quiet = true)
+
+ let code = """
+// Simulated monad.plus pattern from FSharpPlus
+// This pattern uses statically resolved type parameters (SRTP) for ad-hoc polymorphism
+type MonadPlusClass =
+ static member inline MPlus (x: option<'a>, y: option<'a>) =
+ match x with
+ | Some _ -> x
+ | None -> y
+
+ static member inline MPlus (x: list<'a>, y: list<'a>) = x @ y
+
+// Generic mplus function using SRTP to dispatch to appropriate implementation
+let inline mplus (x: ^M) (y: ^M) : ^M =
+ ((^MonadPlusClass or ^M) : (static member MPlus : ^M * ^M -> ^M) (x, y))
+
+// Direct usage with concrete types
+let testOption() =
+ let result : int option = mplus (Some 1) (Some 2)
+ printfn "Option result = %A" result
+
+let testList() =
+ let result : int list = mplus [1; 2] [3; 4]
+ printfn "List result = %A" result
+
+testOption()
+testList()
+"""
+
+ let evalResult, diagnostics = script.Eval(code)
+
+ // The code should compile successfully
+ match evalResult with
+ | Ok _ ->
+ // Filter out informational diagnostics
+ let errors = diagnostics |> Array.filter (fun d ->
+ d.Severity = FSharpDiagnosticSeverity.Error)
+ Assert.Empty(errors)
+ | Error ex ->
+ Assert.True(false, sprintf "Evaluation failed with exception: %s\nDiagnostics: %A" ex.Message diagnostics)
+
+ ///
+ /// Regression test for FSharpPlus issue #613 - custom ResultTBuilder scenario.
+ /// This test reproduces a consumer-side failure where defining a custom ResultTBuilder
+ /// in F# 9 causes compilation issues. The code should compile successfully.
+ /// Issue: https://github.com/fsprojects/FSharpPlus/issues/613
+ ///
+ []
+ []
+ []
+ []
+ let ``custom ResultTBuilder should compile successfully`` (langVersion: string, [] additionalArgs: string[]) =
+ let allArgs = Array.concat [[| "--langversion:" + langVersion |]; additionalArgs]
+ use script = new FSharpScript(additionalArgs = allArgs, quiet = true)
+
+ let code = """
+// Custom ResultTBuilder pattern from FSharpPlus
+type ResultTBuilder() =
+ member inline _.Return(x: 'T) : Result<'T, 'Error> = Ok x
+
+ member inline _.ReturnFrom(m: Result<'T, 'Error>) : Result<'T, 'Error> = m
+
+ member inline _.Bind(m: Result<'T, 'Error>, f: 'T -> Result<'U, 'Error>) : Result<'U, 'Error> =
+ match m with
+ | Ok x -> f x
+ | Error e -> Error e
+
+ member inline _.Zero() : Result = Ok ()
+
+ member inline _.Combine(m1: Result, m2: Result<'T, 'Error>) : Result<'T, 'Error> =
+ match m1 with
+ | Ok () -> m2
+ | Error e -> Error e
+
+ member inline _.Delay(f: unit -> Result<'T, 'Error>) : unit -> Result<'T, 'Error> = f
+
+ member inline _.Run(f: unit -> Result<'T, 'Error>) : Result<'T, 'Error> = f()
+
+let resultT = ResultTBuilder()
+
+// Usage example
+let compute x y =
+ resultT {
+ let! a = Ok x
+ let! b = Ok y
+ return a + b
+ }
+
+// Apply the function to avoid value restriction
+let testResult : Result = compute 5 10
+
+// Verify result
+printfn "testResult = %A" testResult
+"""
+
+ let evalResult, diagnostics = script.Eval(code)
+
+ // The code should compile successfully
+ match evalResult with
+ | Ok _ ->
+ // Filter out informational diagnostics
+ let errors = diagnostics |> Array.filter (fun d ->
+ d.Severity = FSharpDiagnosticSeverity.Error)
+ Assert.Empty(errors)
+ | Error ex ->
+ Assert.True(false, sprintf "Evaluation failed with exception: %s\nDiagnostics: %A" ex.Message diagnostics)