Skip to content

Commit c4a9f34

Browse files
Handle active patterns with inferred function ty & unsolved range typar (#18642)
* Add test for active pattern w/fun ty w/unsolved range typar * Treat `(|P|) : 'a -> 'b` similarly to `(|P|) : 'a` That is, for an active pattern whose type is known to be a function type but whose range type is not yet solved, assume that it _could_ be solved to, e.g., another function type. This can show up in, e.g., an active pattern that is defined mutually-recursively with `and`, has no type annotations, and returns a lambda with `fun` or `function`. * Update release notes
1 parent 573191b commit c4a9f34

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

docs/release-notes/.FSharp.Compiler.Service/10.0.100.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* Fix find all references for F# exceptions ([PR #18565](https://github.com/dotnet/fsharp/pull/18565))
1212
* Shorthand lambda: fix completion for chained calls and analysis for unfinished expression ([PR #18560](https://github.com/dotnet/fsharp/pull/18560))
1313
* Completion: fix previous namespace considered opened [PR #18609](https://github.com/dotnet/fsharp/pull/18609)
14+
* Fix active pattern typechecking regression. ([Issue #18638](https://github.com/dotnet/fsharp/issues/18638), [PR #18642](https://github.com/dotnet/fsharp/pull/18642))
1415

1516
### Added
1617

src/Compiler/Checking/Expressions/CheckExpressions.fs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5259,6 +5259,8 @@ and TcPatLongIdentActivePatternCase warnOnUpper (cenv: cenv) (env: TcEnv) vFlags
52595259
| _, _ -> FSComp.SR.tcActivePatternArgsCountNotMatchArgsAndPat(paramCount, caseName, fmtExprArgs paramCount)
52605260
error(Error(msg, m))
52615261

5262+
let isUnsolvedTyparTy g ty = tryDestTyparTy g ty |> ValueOption.exists (fun typar -> not typar.IsSolved)
5263+
52625264
// partial active pattern (returning bool) doesn't have output arg
52635265
if (not apinfo.IsTotal && isBoolTy g retTy) then
52645266
checkLanguageFeatureError g.langVersion LanguageFeature.BooleanReturningAndReturnTypeDirectedPartialActivePattern m
@@ -5281,7 +5283,8 @@ and TcPatLongIdentActivePatternCase warnOnUpper (cenv: cenv) (env: TcEnv) vFlags
52815283
showErrMsg 1
52825284

52835285
// active pattern in function param (e.g. let f (|P|_|) = ...)
5284-
elif tryDestTyparTy g vExprTy |> ValueOption.exists (fun typar -> not typar.IsSolved) then
5286+
// or in mutual recursion with a lambda: `and (|P|) x = fun y -> …`
5287+
elif isUnsolvedTyparTy g vExprTy || tryDestFunTy g vExprTy |> ValueOption.exists (fun (_, rangeTy) -> isUnsolvedTyparTy g rangeTy) then
52855288
List.frontAndBack args
52865289

52875290
// args count should equal to AP function params count

tests/FSharp.Compiler.ComponentTests/ErrorMessages/ActivePatternArgCountMismatchTest.fs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,26 @@ match 1 with P expr2 pat -> ()
761761
|> typecheck
762762
|> shouldSucceed
763763

764+
module ``Recursive active pattern definition with and`` =
765+
/// See https://github.com/dotnet/fsharp/issues/18638
766+
[<Fact>]
767+
let ``match expr1 with P expr2 pat -> …`` () =
768+
FSharp """
769+
let rec parse p =
770+
function
771+
| IsSomething p v -> Some v
772+
| _ -> None
773+
774+
and (|IsSomething|_|) p =
775+
function
776+
| "nested" -> parse p "42"
777+
| "42" -> Some 42
778+
| _ -> None
779+
"""
780+
|> withNoWarn IncompletePatternMatches
781+
|> typecheck
782+
|> shouldSucceed
783+
764784
module ``int → int → int voption`` =
765785
// Normal usage; pat is int.
766786
[<Fact>]

0 commit comments

Comments
 (0)