Skip to content

Commit bf32a74

Browse files
CopilotT-Gro
andcommitted
WIP: Fix optional argument and caller info for delegates - encountering IL generation issue
Co-authored-by: T-Gro <[email protected]>
1 parent 0a65c0c commit bf32a74

File tree

2 files changed

+86
-6
lines changed

2 files changed

+86
-6
lines changed

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3714,18 +3714,19 @@ module EstablishTypeDefinitionCores =
37143714
let ttps = thisTyconRef.Typars m
37153715
let fparams =
37163716
curriedArgInfos.Head
3717-
|> List.map (fun (ty, argInfo: ArgReprInfo) ->
3717+
|> List.map (fun (origTy, argInfo: ArgReprInfo) ->
37183718
let ty =
37193719
if HasFSharpAttribute g g.attrib_OptionalArgumentAttribute argInfo.Attribs then
37203720
match TryFindFSharpAttribute g g.attrib_StructAttribute argInfo.Attribs with
37213721
| Some (Attrib(range=m)) ->
37223722
checkLanguageFeatureAndRecover g.langVersion LanguageFeature.SupportValueOptionsAsOptionalParameters m
3723-
mkValueOptionTy g ty
3723+
mkValueOptionTy g origTy
37243724
| _ ->
3725-
mkOptionTy g ty
3726-
else ty
3725+
mkOptionTy g origTy
3726+
else origTy
37273727

3728-
MakeSlotParam(ty, argInfo))
3728+
let (ParamAttribs(_, isInArg, isOutArg, optArgInfo, _, _)) = CrackParamAttribsInfo g (origTy, argInfo)
3729+
TSlotParam(Option.map textOfId argInfo.Name, ty, isInArg, isOutArg, optArgInfo.IsOptional, argInfo.Attribs))
37293730
TFSharpDelegate (MakeSlotSig("Invoke", thisTy, ttps, [], [fparams], returnTy))
37303731
| _ ->
37313732
error(InternalError("should have inferred tycon kind", m))

tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,83 @@ let a = A f
6666
a.Invoke(5)"""
6767
|> compileExeAndRun
6868
|> shouldSucceed
69-
|> verifyOutput "line: 5"
69+
|> verifyOutput "line: 5"
70+
71+
[<Fact>]
72+
let ``Delegate with OptionalArgument and CallerFilePath`` () =
73+
FSharp """open System.Runtime.CompilerServices
74+
open System.Runtime.InteropServices
75+
type TestDelegate = delegate of [<OptionalArgument; CallerFilePath>] path: string option -> unit
76+
let f = fun (path: string option) ->
77+
match path with
78+
| Some p -> if p.Contains("test") then printfn "SUCCESS" else printfn "FAIL: %s" p
79+
| None -> printfn "FAIL: None"
80+
let d = TestDelegate f
81+
d.Invoke()"""
82+
|> compileExeAndRun
83+
|> shouldSucceed
84+
|> verifyOutput "SUCCESS"
85+
86+
[<Fact>]
87+
let ``Delegate with OptionalArgument and CallerLineNumber`` () =
88+
FSharp """open System.Runtime.CompilerServices
89+
open System.Runtime.InteropServices
90+
type TestDelegate = delegate of [<OptionalArgument; CallerLineNumber>] line: int option -> unit
91+
let f = fun (line: int option) ->
92+
match line with
93+
| Some l -> if l > 0 then printfn "SUCCESS: line %d" l else printfn "FAIL"
94+
| None -> printfn "FAIL: None"
95+
let d = TestDelegate f
96+
d.Invoke()"""
97+
|> compileExeAndRun
98+
|> shouldSucceed
99+
100+
[<Fact>]
101+
let ``Delegate with OptionalArgument and CallerMemberName`` () =
102+
FSharp """open System.Runtime.CompilerServices
103+
open System.Runtime.InteropServices
104+
type TestDelegate = delegate of [<OptionalArgument; CallerMemberName>] memberName: string option -> unit
105+
let f = fun (memberName: string option) ->
106+
match memberName with
107+
| Some m -> printfn "member: %s" m
108+
| None -> printfn "FAIL"
109+
let d = TestDelegate f
110+
d.Invoke()"""
111+
|> compileExeAndRun
112+
|> shouldSucceed
113+
114+
[<Fact>]
115+
let ``Delegate with CallerFilePath without optional should fail`` () =
116+
FSharp """namespace Test
117+
open System.Runtime.CompilerServices
118+
type TestDelegate = delegate of [<CallerFilePath>] path: string -> unit"""
119+
|> compile
120+
|> shouldFail
121+
|> withDiagnostics [
122+
(Error 1247, Line 3, Col 41, Line 3, Col 45, "'CallerFilePath' can only be applied to optional arguments")
123+
]
124+
125+
[<Fact>]
126+
let ``Delegate with CallerFilePath on wrong type should fail`` () =
127+
FSharp """namespace Test
128+
open System.Runtime.CompilerServices
129+
open System.Runtime.InteropServices
130+
type TestDelegate = delegate of [<OptionalArgument; CallerFilePath>] x: int option -> unit"""
131+
|> compile
132+
|> shouldFail
133+
|> withDiagnostics [
134+
(Error 1246, Line 4, Col 69, Line 4, Col 70, "'CallerFilePath' must be applied to an argument of type 'string', but has been applied to an argument of type 'int'")
135+
]
136+
137+
[<Fact>]
138+
let ``Delegate with CallerLineNumber on wrong type should fail`` () =
139+
FSharp """namespace Test
140+
open System.Runtime.CompilerServices
141+
open System.Runtime.InteropServices
142+
type TestDelegate = delegate of [<OptionalArgument; CallerLineNumber>] x: string option -> unit"""
143+
|> compile
144+
|> shouldFail
145+
|> withDiagnostics [
146+
(Error 1246, Line 4, Col 73, Line 4, Col 74, "'CallerLineNumber' must be applied to an argument of type 'int', but has been applied to an argument of type 'string'")
147+
]
148+

0 commit comments

Comments
 (0)