diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index 527a09cf1d0..02646ad53ac 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -9934,7 +9934,7 @@ and TcMethodApplication_SplitSynArguments // named optional arguments should always have option type // STRUCT OPTIONS: if we allow struct options as optional arguments then we should relax this and rely // on later inference to work out if this is a struct option or ref option - let ty = if isOpt then mkOptionTy denv.g ty else ty + let ty = if isOpt && not (denv.g.langVersion.SupportsFeature LanguageFeature.SupportValueOptionsAsOptionalParameters) then mkOptionTy denv.g ty else ty nm, isOpt, x, ty, x.Range) (Some (unnamedCurriedCallerArgs, namedCurriedCallerArgs), None, exprTy) diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs index 0a7f7f353bb..5d6bf970d7f 100644 --- a/src/Compiler/Checking/MethodCalls.fs +++ b/src/Compiler/Checking/MethodCalls.fs @@ -379,7 +379,7 @@ let AdjustCalledArgTypeForOptionals (infoReader: InfoReader) ad enforceNullableO // FSharpMethod(?x = arg), optional F#-style argument | CalleeSide -> - // In this case, the called argument will already have option type + // In this case, the called argument will already have option/voption type calledArgTy, TypeDirectedConversionUsed.No, None | NotOptional -> diff --git a/tests/fsharp/Compiler/Language/OptionalInteropTests.fs b/tests/fsharp/Compiler/Language/OptionalInteropTests.fs index 868d46de779..360851706a1 100644 --- a/tests/fsharp/Compiler/Language/OptionalInteropTests.fs +++ b/tests/fsharp/Compiler/Language/OptionalInteropTests.fs @@ -163,3 +163,86 @@ Test.OverloadedMethodTakingNullableOptionals(x = 6) |> ignore let fs = Compilation.Create(fsSrc, CompileOutput.Exe, options = [| $"--langversion:{langVersion}" |], cmplRefs = [cs]) CompilerAssert.Compile fs + // Tests for issue #19074: Support voption with optional parameter syntax (?x=) + [] + let ``F# method with voption optional parameter should accept ValueNone with question mark syntax`` () = + let fsSrc = + """ +open System.Runtime.InteropServices + +type MyClass() = + member _.Foo([] x: int voption) = + match x with + | ValueNone -> "none" + | ValueSome v -> string v + +let c = MyClass() +let r1 = c.Foo(?x=ValueNone) +printfn "%s" r1 + """ + + let fs = Compilation.Create(fsSrc, CompileOutput.Exe, options = [| "--langversion:preview" |]) + CompilerAssert.Compile fs + + [] + let ``F# method with voption optional parameter should accept ValueSome with question mark syntax`` () = + let fsSrc = + """ +open System.Runtime.InteropServices + +type MyClass() = + member _.Foo([] x: int voption) = + match x with + | ValueNone -> "none" + | ValueSome v -> string v + +let c = MyClass() +let r2 = c.Foo(?x=ValueSome 42) +printfn "%s" r2 + """ + + let fs = Compilation.Create(fsSrc, CompileOutput.Exe, options = [| "--langversion:preview" |]) + CompilerAssert.Compile fs + + [] + let ``F# method with voption optional parameter should work without question mark syntax`` () = + let fsSrc = + """ +open System.Runtime.InteropServices + +type MyClass() = + member _.Foo([] x: int voption) = + match x with + | ValueNone -> "none" + | ValueSome v -> string v + +let c = MyClass() +let r1 = c.Foo(x=ValueNone) +let r2 = c.Foo(x=ValueSome 42) +printfn "%s %s" r1 r2 + """ + + let fs = Compilation.Create(fsSrc, CompileOutput.Exe, options = [| "--langversion:preview" |]) + CompilerAssert.Compile fs + + [] + let ``F# method with option optional parameter should still work with question mark syntax`` () = + let fsSrc = + """ +open System.Runtime.InteropServices + +type MyClass() = + member _.Foo([] x: int option) = + match x with + | None -> "none" + | Some v -> string v + +let c = MyClass() +let r1 = c.Foo(?x=None) +let r2 = c.Foo(?x=Some 42) +printfn "%s %s" r1 r2 + """ + + let fs = Compilation.Create(fsSrc, CompileOutput.Exe, options = [| "--langversion:preview" |]) + CompilerAssert.Compile fs +