diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md index 29dac7317ee..a58c104587e 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md @@ -23,6 +23,6 @@ ### Changed * Enforce `AttributeTargets.Interface` ([PR #17173](https://github.com/dotnet/fsharp/pull/17173)) * Minor compiler perf improvements. ([PR #17130](https://github.com/dotnet/fsharp/pull/17130)) -* Improve error of Active Pattern case Argument Count Not Match ([PR #16846](https://github.com/dotnet/fsharp/pull/16846)) +* Improve error messages for active pattern argument count mismatch ([PR #16846](https://github.com/dotnet/fsharp/pull/16846), [PR #17186](https://github.com/dotnet/fsharp/pull/17186)) * AsyncLocal diagnostics context. ([PR #16779](https://github.com/dotnet/fsharp/pull/16779)) * Reduce allocations in compiler checking via `ValueOption` usage ([PR #16822](https://github.com/dotnet/fsharp/pull/16822)) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 4aa56135baf..89253bd6783 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -5119,17 +5119,41 @@ and TcPatLongIdentActivePatternCase warnOnUpper (cenv: cenv) (env: TcEnv) vFlags let vExprTy = vExpr.Type let activePatArgsAsSynPats, patArg = - let rec IsNotSolved ty = - match ty with - | TType_var(v, _) when v.IsSolved -> - match v.Solution with - | Some t -> IsNotSolved t - | None -> false - | TType_var _ -> true - | _ -> false - - // only cases which return unit or unresolved type (in AP definition) can omit output arg - let canOmit retTy = isUnitTy g retTy || IsNotSolved retTy + // only cases which return unit or unresolved type (in AP definition) compatible with unit can omit output arg + let canOmit retTy = + let couldResolveToUnit ty = + tryDestTyparTy g ty + |> ValueOption.exists (fun typar -> + not typar.IsSolved + && typar.Constraints |> List.forall (fun c -> + let (|Unit|_|) ty = if isUnitTy g ty then Some Unit else None + + match c with + // These apply or could apply to unit. + | TyparConstraint.IsReferenceType _ + | TyparConstraint.SupportsComparison _ + | TyparConstraint.SupportsEquality _ + | TyparConstraint.DefaultsTo (ty = Unit) + | TyparConstraint.MayResolveMember _ -> true + + // Any other kind of constraint is incompatible with unit. + | TyparConstraint.CoercesTo _ + | TyparConstraint.DefaultsTo _ + | TyparConstraint.IsDelegate _ + | TyparConstraint.IsEnum _ + | TyparConstraint.IsNonNullableStruct _ + | TyparConstraint.IsUnmanaged _ + | TyparConstraint.RequiresDefaultConstructor _ + | TyparConstraint.SimpleChoice _ + | TyparConstraint.SupportsNull _ -> false)) + + let caseRetTy = + if isOptionTy g retTy then destOptionTy g retTy + elif isValueOptionTy g retTy then destValueOptionTy g retTy + elif isChoiceTy g retTy then destChoiceTy g retTy idx + else retTy + + isUnitTy g caseRetTy || couldResolveToUnit caseRetTy // This bit of type-directed analysis ensures that parameterized partial active patterns returning unit do not need to take an argument let dtys, retTy = stripFunTy g vExprTy @@ -5169,25 +5193,27 @@ and TcPatLongIdentActivePatternCase warnOnUpper (cenv: cenv) (env: TcEnv) vFlags // active pattern cases returning unit or unknown things (in AP definition) can omit output arg elif paramCount = args.Length then - let caseRetTy = - if isOptionTy g retTy then destOptionTy g retTy - elif isValueOptionTy g retTy then destValueOptionTy g retTy - elif isChoiceTy g retTy then destChoiceTy g retTy idx - else retTy - // only cases which return unit or unresolved type (in AP definition) can omit output arg - if canOmit caseRetTy then + if canOmit retTy then args, SynPat.Const(SynConst.Unit, m) else showErrMsg 1 // active pattern in function param (e.g. let f (|P|_|) = ...) - elif IsNotSolved vExprTy then + elif tryDestTyparTy g vExprTy |> ValueOption.exists (fun typar -> not typar.IsSolved) then List.frontAndBack args // args count should equal to AP function params count elif dtys.Length <> args.Length then - showErrMsg 1 + let returnCount = + match dtys with + // val (|P|) : expr1:_ -> unit + // val (|P|_|) : expr1:_ -> unit option + // val (|P|_|) : expr1:_ -> unit voption + | [_] when canOmit retTy -> 0 + | _ -> 1 + + showErrMsg returnCount else List.frontAndBack args diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ActivePatternArgCountMismatchTest.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ActivePatternArgCountMismatchTest.fs index 77fd98449b0..e2a988ec0c3 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ActivePatternArgCountMismatchTest.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/ActivePatternArgCountMismatchTest.fs @@ -1,40 +1,1300 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. -namespace ErrorMessages +module ErrorMessages.``Active pattern arg counts`` open Xunit open FSharp.Test.Compiler -module ``Active Pattern argument count mismatch test`` = +/// Warning FS0025: Incomplete pattern matches on this expression. +/// We suppress this warning in the assertions below so that we +/// don't need to add a wildcard case to every match. +let [] IncompletePatternMatches = 25 - [] - let ``test``() = - FSharp """ -let (|IsEven|_|) x = x % 2 = 0 -match 1 with -| IsEven xxx -> () -| _ -> printfn "Odd!" +module TooFew = + module ``int → int → unit`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|) (expr2 : int) (expr1 : int) = P +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 15, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → unit option`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then Some P else None +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 15, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → unit voption`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then ValueSome P else ValueNone +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 15, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → Choice`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|Q|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then P else Q +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 15, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → bool`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = expr1 = expr2 +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 15, "This active pattern expects 1 expression argument(s), e.g., 'P e1'.") + + module ``int → int → int`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|) expr2 expr1 = P (expr1 + expr2) +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 15, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → int option`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then Some (P (expr1 + expr2)) else None +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 15, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then Some (P (expr1 + expr2)) else None +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 19, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then Some (P (expr1 + expr2)) else None +let expr2 = 2 +match 1 with P expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 21, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") -let (|Ignore|) x = () -match 1 with -| Ignore () () -> printfn "Ignored!" -| _ -> () + module ``int → int → int voption`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then ValueSome (P (expr1 + expr2)) else ValueNone +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 15, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") -let (|Equals|_|) z y x = x = y -match 1 with -| Equals "" 2 xxx -> () -| _ -> printfn "Not Equal" + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then ValueSome (P (expr1 + expr2)) else ValueNone +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 19, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") -let (|A|) a b c d = d -match 1 with -| A -> () -| _ -> () - """ |> withLangVersionPreview + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then ValueSome (P (expr1 + expr2)) else ValueNone +let expr2 = 2 +match 1 with P expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 21, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → Choice`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|Q|) expr2 expr1 = if expr1 = expr2 then P (expr1 + expr2) else Q +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 15, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|Q|) expr2 expr1 = if expr1 = expr2 then P (expr1 + expr2) else Q +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 19, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|Q|) expr2 expr1 = if expr1 = expr2 then P (expr1 + expr2) else Q +let expr2 = 2 +match 1 with P expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 21, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + +module Enough = + module ``int → unit`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|) expr1 = P +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // pat is unit. + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|) expr1 = P +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + [] + let ``match expr1 with P () -> …`` () = + FSharp """ +let (|P|) expr1 = P +match 1 with P () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → unit option`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|_|) expr1 = if expr1 = 1 then Some P else None +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // pat is unit. + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|_|) expr1 = if expr1 = 1 then Some P else None +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + [] + let ``match expr1 with P () -> …`` () = + FSharp """ +let (|P|_|) expr1 = if expr1 = 1 then Some P else None +match 1 with P () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → unit voption`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|_|) expr1 = if expr1 = 1 then ValueSome P else ValueNone +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // pat is unit. + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|_|) expr1 = if expr1 = 1 then ValueSome P else ValueNone +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + [] + let ``match expr1 with P () -> …`` () = + FSharp """ +let (|P|_|) expr1 = if expr1 = 1 then ValueSome P else ValueNone +match 1 with P () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → Choice`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|Q|) expr1 = if expr1 = 1 then P else Q +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // pat is unit. + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|Q|) expr1 = if expr1 = 1 then P else Q +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + [] + let ``match expr1 with P () -> …`` () = + FSharp """ +let (|P|Q|) expr1 = if expr1 = 1 then P else Q +match 1 with P () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → bool`` = + [] + let ``match expr1 with P -> …`` () = + FSharp """ +let (|P|_|) expr1 = expr1 = 1 +match 1 with P -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → int`` = + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|) (expr1 : int) = P expr1 +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → int option`` = + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then Some (P expr1) else None +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → int voption`` = + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then ValueSome (P expr1) else ValueNone +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → Choice`` = + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|Q|) (expr1 : int) = if expr1 = 1 then P expr1 else Q +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → int → unit`` = + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|) (expr2 : int) (expr1 : int) = P +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // pat is unit. + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|) (expr2 : int) (expr1 : int) = P +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // expr3 is actually a pattern bound to unit. + [] + let ``match expr1 with P expr2 expr3 -> …`` () = + FSharp """ +let (|P|) (expr2 : int) (expr1 : int) = P +let expr2 = 2 +let expr3 = 3 +match 1 with P expr2 expr3 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // pat is bound to a value of type (int -> unit). + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|) (expr2 : int) (expr1 : int) = P +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // expr2 is actually a pattern bound to a value of type (int -> unit). + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|) (expr2 : int) (expr1 : int) = P +let expr2 = 2 +match 1 with P expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → int → unit option`` = + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then Some P else None +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // pat is unit. + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then Some P else None +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // expr3 is actually a pattern bound to unit. + [] + let ``match expr1 with P expr2 expr3 -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then Some P else None +let expr2 = 2 +let expr3 = 3 +match 1 with P expr2 expr3 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then Some P else None +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 39, Line 3, Col 16, Line 3, Col 19, "The value or constructor 'pat' is not defined.") + + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then Some P else None +let expr2 = 2 +match 1 with P expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → int → unit voption`` = + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then ValueSome P else ValueNone +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // pat is unit. + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then ValueSome P else ValueNone +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // expr3 is actually a pattern bound to unit. + [] + let ``match expr1 with P expr2 expr3 -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then ValueSome P else ValueNone +let expr2 = 2 +let expr3 = 3 +match 1 with P expr2 expr3 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then ValueSome P else ValueNone +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 39, Line 3, Col 16, Line 3, Col 19, "The value or constructor 'pat' is not defined.") + + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then ValueSome P else ValueNone +let expr2 = 2 +match 1 with P expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → int → Choice`` = + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|Q|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then P else Q +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 722, Line 4, Col 14, Line 4, Col 24, "Only active patterns returning exactly one result may accept arguments") + + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|Q|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then P else Q +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 722, Line 4, Col 14, Line 4, Col 25, "Only active patterns returning exactly one result may accept arguments") + + [] + let ``match expr1 with P expr2 expr3 -> …`` () = + FSharp """ +let (|P|Q|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then P else Q +let expr2 = 2 +let expr3 = 3 +match 1 with P expr2 expr3 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 722, Line 5, Col 14, Line 5, Col 27, "Only active patterns returning exactly one result may accept arguments") + + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|Q|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then P else Q +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3868, Line 4, Col 3, Line 4, Col 13, "This active pattern does not expect any arguments, i.e., it should be used like 'IsEven' instead of 'IsEven x'.") - (Error 3868, Line 9, Col 3, Line 9, Col 15, "This active pattern expects exactly one pattern argument, e.g., 'Ignore pat'.") - (Error 3868, Line 14, Col 3, Line 14, Col 18, "This active pattern expects 2 expression argument(s), e.g., 'Equals e1 e2'.") - (Error 3868, Line 19, Col 3, Line 19, Col 4, "This active pattern expects 3 expression argument(s) and a pattern argument, e.g., 'A e1 e2 e3 pat'.") - ] + Error 722, Line 3, Col 14, Line 3, Col 19, "Only active patterns returning exactly one result may accept arguments" + Error 39, Line 3, Col 16, Line 3, Col 19, "The value or constructor 'pat' is not defined." + ] + + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|Q|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then P else Q +let expr2 = 2 +match 1 with P expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 722, Line 4, Col 14, Line 4, Col 21, "Only active patterns returning exactly one result may accept arguments") + + module ``int → int → bool`` = + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = expr1 = expr2 +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern expects 1 expression argument(s), e.g., 'P e1'.") + + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = expr1 = expr2 +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 25, "This active pattern expects 1 expression argument(s), e.g., 'P e1'.") + + [] + let ``match expr1 with P expr2 expr3 -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = expr1 = expr2 +let expr2 = 2 +let expr3 = 3 +match 1 with P expr2 expr3 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 5, Col 14, Line 5, Col 27, "This active pattern expects 1 expression argument(s), e.g., 'P e1'.") + + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = expr1 = expr2 +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 39, Line 3, Col 16, Line 3, Col 19, "The value or constructor 'pat' is not defined.") + + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = expr1 = expr2 +let expr2 = 2 +match 1 with P expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → int → int`` = + // Normal usage; pat is int. + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|) expr2 expr1 = P (expr1 + expr2) +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // expr3 is actually a pattern bound to a value of type int. + [] + let ``match expr1 with P expr2 expr3 -> …`` () = + FSharp """ +let (|P|) expr2 expr1 = P (expr1 + expr2) +let expr2 = 2 +let expr3 = 2 +match 1 with P expr2 expr3 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // pat is bound to a value of type (int -> int). + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|) expr2 expr1 = P (expr1 + expr2) +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // expr2 is actually a pattern bound to a value of type (int -> int). + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|) expr2 expr1 = P (expr1 + expr2) +let expr2 = 2 +match 1 with P expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → int → int option`` = + // Normal usage; pat is int. + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then Some (P (expr1 + expr2)) else None +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // expr3 is actually a pattern bound to a value of type int. + [] + let ``match expr1 with P expr2 expr3 -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then Some (P (expr1 + expr2)) else None +let expr2 = 2 +let expr3 = 2 +match 1 with P expr2 expr3 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then Some (P (expr1 + expr2)) else None +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → int → int voption`` = + // Normal usage; pat is int. + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then ValueSome (P (expr1 + expr2)) else ValueNone +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + // expr3 is actually a pattern bound to a value of type int. + [] + let ``match expr1 with P expr2 expr3 -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then ValueSome (P (expr1 + expr2)) else ValueNone +let expr2 = 2 +let expr3 = 2 +match 1 with P expr2 expr3 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then ValueSome (P (expr1 + expr2)) else ValueNone +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldSucceed + + module ``int → int → Choice`` = + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|Q|) expr2 expr1 = if expr1 = expr2 then P (expr1 + expr2) else Q +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 722, Line 4, Col 14, Line 4, Col 25, "Only active patterns returning exactly one result may accept arguments") + + [] + let ``match expr1 with P expr2 expr3 -> …`` () = + FSharp """ +let (|P|Q|) expr2 expr1 = if expr1 = expr2 then P (expr1 + expr2) else Q +let expr2 = 2 +let expr3 = 2 +match 1 with P expr2 expr3 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 722, Line 5, Col 14, Line 5, Col 27, "Only active patterns returning exactly one result may accept arguments") + + [] + let ``match expr1 with P expr2 -> …`` () = + FSharp """ +let (|P|Q|) expr2 expr1 = if expr1 = expr2 then P (expr1 + expr2) else Q +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 722, Line 4, Col 14, Line 4, Col 25, "Only active patterns returning exactly one result may accept arguments") + +module TooMany = + module ``int → unit`` = + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|) (expr1 : int) = P +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 25, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|) (expr1 : int) = P +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + [] + let ``match expr1 with P () expr2 -> …`` () = + FSharp """ +let (|P|) (expr1 : int) = P +let expr2 = 2 +match 1 with P () expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + module ``int → unit option`` = + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then Some P else None +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 25, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then Some P else None +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + [] + let ``match expr1 with P () expr2 -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then Some P else None +let expr2 = 2 +match 1 with P () expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + module ``int → unit voption`` = + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then ValueSome P else ValueNone +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 25, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then ValueSome P else ValueNone +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + [] + let ``match expr1 with P () expr2 -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then ValueSome P else ValueNone +let expr2 = 2 +match 1 with P () expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + module ``int → Choice`` = + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|Q|) (expr1 : int) = if expr1 = 1 then P else Q +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 25, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|Q|) (expr1 : int) = if expr1 = 1 then P else Q +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + [] + let ``match expr1 with P () expr2 -> …`` () = + FSharp """ +let (|P|Q|) (expr1 : int) = if expr1 = 1 then P else Q +let expr2 = 2 +match 1 with P () expr2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + module ``int → bool`` = + [] + let ``match expr1 with P pat -> …`` () = + FSharp """ +let (|P|_|) expr1 = expr1 = 1 +match 1 with P pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 3, Col 14, Line 3, Col 19, "This active pattern does not expect any arguments, i.e., it should be used like 'P' instead of 'P x'.") + + module ``int → int`` = + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|) (expr1 : int) = P expr1 +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 25, "This active pattern expects exactly one pattern argument, e.g., 'P pat'.") + + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|) (expr1 : int) = P expr1 +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern expects exactly one pattern argument, e.g., 'P pat'.") + + module ``int → int option`` = + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then Some (P expr1) else None +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 25, "This active pattern expects exactly one pattern argument, e.g., 'P pat'.") + + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then Some (P expr1) else None +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern expects exactly one pattern argument, e.g., 'P pat'.") + + module ``int → int voption`` = + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then ValueSome (P expr1) else ValueNone +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 25, "This active pattern expects exactly one pattern argument, e.g., 'P pat'.") + + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|_|) (expr1 : int) = if expr1 = 1 then ValueSome (P expr1) else ValueNone +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern expects exactly one pattern argument, e.g., 'P pat'.") + + module ``int → Choice`` = + [] + let ``match expr1 with P expr2 pat -> …`` () = + FSharp """ +let (|P|Q|) (expr1 : int) = if expr1 = 1 then P expr1 else Q +let expr2 = 2 +match 1 with P expr2 pat -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 25, "This active pattern expects exactly one pattern argument, e.g., 'P pat'.") + + [] + let ``match expr1 with P expr2 () -> …`` () = + FSharp """ +let (|P|Q|) (expr1 : int) = if expr1 = 1 then P expr1 else Q +let expr2 = 2 +match 1 with P expr2 () -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 24, "This active pattern expects exactly one pattern argument, e.g., 'P pat'.") + + module ``int → int → unit`` = + [] + let ``match expr1 with P expr2 pat1 pat2 -> …`` () = + FSharp """ +let (|P|) (expr2 : int) (expr1 : int) = P +let expr2 = 2 +match 1 with P expr2 pat1 pat2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 31, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → unit option`` = + [] + let ``match expr1 with P expr2 pat1 pat2 -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then Some P else None +let expr2 = 2 +match 1 with P expr2 pat1 pat2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 31, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → unit voption`` = + [] + let ``match expr1 with P expr2 pat1 pat2 -> …`` () = + FSharp """ +let (|P|_|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then ValueSome P else ValueNone +let expr2 = 2 +match 1 with P expr2 pat1 pat2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 31, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → Choice`` = + [] + let ``match expr1 with P expr2 pat1 pat2 -> …`` () = + FSharp """ +let (|P|Q|) (expr2 : int) (expr1 : int) = if expr1 = expr2 then P else Q +let expr2 = 2 +match 1 with P expr2 pat1 pat2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 31, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → int`` = + [] + let ``match expr1 with P expr2 pat1 pat2 -> …`` () = + FSharp """ +let (|P|) expr2 expr1 = P (expr1 + expr2) +let expr2 = 2 +match 1 with P expr2 pat1 pat2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 31, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → int option`` = + [] + let ``match expr1 with P expr2 pat1 pat2 -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then Some (P (expr1 + expr2)) else None +let expr2 = 2 +match 1 with P expr2 pat1 pat2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 31, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → int voption`` = + [] + let ``match expr1 with P expr2 pat1 pat2 -> …`` () = + FSharp """ +let (|P|_|) expr2 expr1 = if expr1 = expr2 then ValueSome (P (expr1 + expr2)) else ValueNone +let expr2 = 2 +match 1 with P expr2 pat1 pat2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 31, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.") + + module ``int → int → Choice`` = + [] + let ``match expr1 with P expr2 pat1 pat2 -> …`` () = + FSharp """ +let (|P|Q|) expr2 expr1 = if expr1 = expr2 then P (expr1 + expr2) else Q +let expr2 = 2 +match 1 with P expr2 pat1 pat2 -> () + """ + |> withLangVersionPreview + |> withNoWarn IncompletePatternMatches + |> typecheck + |> shouldFail + |> withSingleDiagnostic (Error 3868, Line 4, Col 14, Line 4, Col 31, "This active pattern expects 1 expression argument(s) and a pattern argument, e.g., 'P e1 pat'.")