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))