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