From b412d996457d033b456a8a35041fdc00c67533e2 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 18 May 2026 11:23:28 +0000
Subject: [PATCH 1/4] Initial plan
From b9398f6234a826c0e2a9eeece7463cc8c39174b1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 18 May 2026 12:22:51 +0000
Subject: [PATCH 2/4] Reject non-function single and partial active pattern
bindings
Agent-Logs-Url: https://github.com/dotnet/fsharp/sessions/588bbe30-9352-45a1-8895-c59b79395ad3
Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com>
---
src/Compiler/Checking/PostInferenceChecks.fs | 8 +++++---
.../PatternMatching/Named/E_ActivePatternNotAFunction.fs | 6 +++++-
.../Conformance/PatternMatching/Named/Named.fs | 8 ++++++--
3 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs
index 7924394c743..b0891f9ecf3 100644
--- a/src/Compiler/Checking/PostInferenceChecks.fs
+++ b/src/Compiler/Checking/PostInferenceChecks.fs
@@ -2089,10 +2089,12 @@ and CheckBinding cenv env alwaysCheckNoReraise ctxt (TBind(v, bindRhs, _) as bin
let env = { env with external = env.external || ValHasWellKnownAttribute g WellKnownValAttributes.DllImportAttribute v }
- // Check that active patterns don't have free type variables in their result
+ // Check active pattern shape/type constraints
match TryGetActivePatternInfo vref with
- | Some _apinfo when _apinfo.ActiveTags.Length > 1 ->
- if doesActivePatternHaveFreeTypars g vref then
+ | Some apinfo ->
+ let hasFreeTypars = doesActivePatternHaveFreeTypars g vref
+
+ if apinfo.ActiveTags.Length > 1 && hasFreeTypars then
errorR(Error(FSComp.SR.activePatternChoiceHasFreeTypars(v.LogicalName), v.Range))
| _ -> ()
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Named/E_ActivePatternNotAFunction.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Named/E_ActivePatternNotAFunction.fs
index aa1ff9f0165..e9d1703943b 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Named/E_ActivePatternNotAFunction.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Named/E_ActivePatternNotAFunction.fs
@@ -1,5 +1,9 @@
// #Regression #Conformance #PatternMatching #ActivePatterns
// Regression test for FSHARP1.0:5590
-//Active pattern '|A|B|' is not a function$
+//Active pattern '|A|B|' is not a function$
+//Active pattern '|C|' is not a function$
+//Active pattern '|D|_|' is not a function$
let (|A|B|) = failwith "" : Choice
+let (|C|) = 3
+let (|D|_|) = None
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Named/Named.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Named/Named.fs
index c1bfa90f03d..ba48761e5f3 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Named/Named.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/PatternMatching/Named/Named.fs
@@ -184,7 +184,11 @@ module Named =
|> withOptions ["--test:ErrorRanges"]
|> typecheck
|> shouldFail
- |> withSingleDiagnostic (Error 1209, Line 5, Col 6, Line 5, Col 11, "Active pattern '|A|B|' is not a function")
+ |> withDiagnostics [
+ (Error 1209, Line 7, Col 6, Line 7, Col 11, "Active pattern '|A|B|' is not a function")
+ (Error 1209, Line 8, Col 6, Line 8, Col 9, "Active pattern '|C|' is not a function")
+ (Error 1209, Line 9, Col 6, Line 9, Col 11, "Active pattern '|D|_|' is not a function")
+ ]
// This test was automatically generated (moved from FSharpQA suite - Conformance/PatternMatching/Named)
[]
@@ -621,4 +625,4 @@ but here has type
|> asFs
|> withOptions ["--test:ErrorRanges"]
|> typecheck
- |> shouldSucceed
\ No newline at end of file
+ |> shouldSucceed
From f461262ff361b23ddc074c1c5de583a56853517e Mon Sep 17 00:00:00 2001
From: Tomas Grosup
Date: Tue, 19 May 2026 12:54:57 +0200
Subject: [PATCH 3/4] Fix RelaxWhitespace2 tests: make active patterns
function-typed
The PR's new validation rejects non-function active pattern bindings for
single-case and partial patterns (extending the existing multi-case check).
The RelaxWhitespace2.fs test file had several active patterns defined as
non-function values (|C|, |F|_|, |G|_|, etc.) since it tests whitespace
relaxation, not active pattern semantics.
Add parameters to make these active patterns function-typed while preserving
the multiline whitespace structure being tested.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../OffsideExceptions/RelaxWhitespace2.fs | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/RelaxWhitespace2.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/RelaxWhitespace2.fs
index 42e8dc1ad9e..ef83e1ba871 100644
--- a/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/RelaxWhitespace2.fs
+++ b/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/RelaxWhitespace2.fs
@@ -237,7 +237,7 @@ module ActivePatterns =
|) _ = (|
A
|)
- let (|C|) =
+ let (|C|) _ =
if true then ignore (|
A
|)
@@ -255,7 +255,7 @@ module ActivePatterns =
F
|
_
- |) as f = Some (|
+ |) _ = Some (|
C
|)
let (|
@@ -1265,7 +1265,7 @@ type ActivePatterns() =
|) = (|
A
|)
- let (|C|) =
+ let (|C|) _ =
if true then ignore (|
A
|)
@@ -1283,7 +1283,7 @@ type ActivePatterns() =
F
|
_
- |) as f = Some (|
+ |) _ = Some (|
C
|)
let (|
@@ -1305,7 +1305,7 @@ type ActivePatterns() =
|) = (|
A_
|)
- static let (|C_|) =
+ static let (|C_|) _ =
if true then ignore (|
A_
|)
@@ -1323,7 +1323,7 @@ type ActivePatterns() =
F_
|
_
- |) as f_ = Some (|
+ |) _ = Some (|
C_
|)
static let (|
@@ -2593,7 +2593,7 @@ let ActivePatterns<'a> =
|) _ = (|
A
|)
- let (|C|) =
+ let (|C|) _ =
if true then ignore (|
A
|)
@@ -2611,7 +2611,7 @@ let ActivePatterns<'a> =
F
|
_
- |) as f = Some (|
+ |) _ = Some (|
C
|)
let (|
From 9239c8a591131aeb03ab6bcab44cd25bfda8fc64 Mon Sep 17 00:00:00 2001
From: Tomas Grosup
Date: Tue, 19 May 2026 13:03:40 +0200
Subject: [PATCH 4/4] Add release notes for PR #19763
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
docs/release-notes/.FSharp.Compiler.Service/11.0.100.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
index 4a6110cf514..f3560fda3e2 100644
--- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
+++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
@@ -1,5 +1,6 @@
### Fixed
+* Reject non-function bindings for single-case and partial active pattern names with FS1209, matching the existing multi-case behavior. ([PR #19763](https://github.com/dotnet/fsharp/pull/19763))
* Fix attributes on return type of unparenthesized tuple methods being silently dropped from IL. ([Issue #462](https://github.com/dotnet/fsharp/issues/462), [PR #19714](https://github.com/dotnet/fsharp/pull/19714))
* Fix internal error FS0073 "Undefined or unsolved type variable" in IlxGen when nested inline SRTP functions with multiple overloads leave unsolved typars in the non-witness codegen path. ([Issue #19709](https://github.com/dotnet/fsharp/issues/19709), [PR #19710](https://github.com/dotnet/fsharp/pull/19710))
* Fix NRE when calling virtual Object methods on value types through inline SRTP functions. ([Issue #8098](https://github.com/dotnet/fsharp/issues/8098), [PR #19511](https://github.com/dotnet/fsharp/pull/19511))