Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 3 additions & 10 deletions src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3715,16 +3715,9 @@ module EstablishTypeDefinitionCores =
let fparams =
curriedArgInfos.Head
|> List.map (fun (ty, argInfo: ArgReprInfo) ->
let ty =
if HasFSharpAttribute g g.attrib_OptionalArgumentAttribute argInfo.Attribs then
match TryFindFSharpAttribute g g.attrib_StructAttribute argInfo.Attribs with
| Some (Attrib(range=m)) ->
checkLanguageFeatureAndRecover g.langVersion LanguageFeature.SupportValueOptionsAsOptionalParameters m
mkValueOptionTy g ty
| _ ->
mkOptionTy g ty
else ty

// For delegates, we don't use CrackParamAttribsInfo or isOptional
// Delegates with optional parameters should use the ?param syntax
// which is handled elsewhere in the compiler
MakeSlotParam(ty, argInfo))
TFSharpDelegate (MakeSlotSig("Invoke", thisTy, ttps, [], [fparams], returnTy))
| _ ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ namespace FSharpTest
|> shouldSucceed

[<Fact>]
let ``Delegate with optional parameter`` () =
let ``Delegate with optional parameter and CallerLineNumber`` () =
FSharp """open System.Runtime.CompilerServices
type A = delegate of [<CallerLineNumber>] ?a: int -> unit
let f = fun (a: int option) -> defaultArg a 100 |> printf "line: %d"
Expand All @@ -59,11 +59,49 @@ a.Invoke()"""
|> verifyOutput "line: 5"

[<Fact>]
let ``Delegate with struct optional parameter`` () =
FSharp """type A = delegate of [<Struct>] ?a: int -> unit
let f = fun (a: int voption) -> defaultValueArg a 100 |> printf "line: %d"
let ``Delegate with optional parameter and CallerFilePath`` () =
FSharp """open System.Runtime.CompilerServices
type A = delegate of [<CallerFilePath>] ?path: string -> unit
let f = fun (path: string option) ->
match path with
| Some p -> if p.Contains("DelegateDefinition.fs") then printfn "SUCCESS" else printfn "FAIL: %s" p
| None -> printfn "FAIL: None"
let a = A f
a.Invoke(5)"""
a.Invoke()"""
|> compileExeAndRun
|> shouldSucceed
|> verifyOutput "line: 5"
|> verifyOutput "SUCCESS"

[<Fact>]
let ``Delegate with CallerFilePath without optional should fail`` () =
FSharp """namespace Test
open System.Runtime.CompilerServices
type TestDelegate = delegate of [<CallerFilePath>] path: string -> unit"""
|> compile
|> shouldFail
|> withDiagnostics [
(Error 1247, Line 3, Col 52, Line 3, Col 56, "'CallerFilePath' can only be applied to optional arguments")
]

[<Fact>]
let ``Delegate with CallerFilePath on wrong type should fail`` () =
FSharp """namespace Test
open System.Runtime.CompilerServices
type TestDelegate = delegate of [<CallerFilePath>] ?x: int -> unit"""
|> compile
|> shouldFail
|> withDiagnostics [
(Error 1246, Line 3, Col 53, Line 3, Col 54, "'CallerFilePath' must be applied to an argument of type 'string', but has been applied to an argument of type 'int'")
]

[<Fact>]
let ``Delegate with CallerLineNumber on wrong type should fail`` () =
FSharp """namespace Test
open System.Runtime.CompilerServices
type TestDelegate = delegate of [<CallerLineNumber>] ?x: string -> unit"""
|> compile
|> shouldFail
|> withDiagnostics [
(Error 1246, Line 3, Col 54, Line 3, Col 55, "'CallerLineNumber' must be applied to an argument of type 'int', but has been applied to an argument of type 'string'")
]

Loading