Skip to content

Commit a58a47e

Browse files
ijklampsfinaki
andauthored
Fix delegate with option parameter (#18385)
* fix delegate with option parameter * release note * typo * fix struct optional parameter * fix test * fix test --------- Co-authored-by: ijklam <[email protected]> Co-authored-by: Petr <[email protected]>
1 parent 52843f7 commit a58a47e

File tree

6 files changed

+48
-11
lines changed

6 files changed

+48
-11
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* Fix "type inference problem too complicated" for SRTP with T:null and T:struct dummy constraint([Issue #18288](https://github.com/dotnet/fsharp/issues/18288), [PR #18345](https://github.com/dotnet/fsharp/pull/18345))
1717
* Fix for missing parse diagnostics in TransparentCompiler.ParseAndCheckProject ([PR #18366](https://github.com/dotnet/fsharp/pull/18366))
1818
* Miscellanous parentheses analyzer fixes. ([PR #18350](https://github.com/dotnet/fsharp/pull/18350))
19+
* Fix MethodDefNotFound when compiling code invoking delegate with option parameter ([Issue #5171](https://github.com/dotnet/fsharp/issues/5171), [PR #18385](https://github.com/dotnet/fsharp/pull/18385))
1920

2021
### Added
2122
* Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241))

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3697,7 +3697,20 @@ module EstablishTypeDefinitionCores =
36973697
if curriedArgInfos.Length < 1 then error(Error(FSComp.SR.tcInvalidDelegateSpecification(), m))
36983698
if curriedArgInfos.Length > 1 then error(Error(FSComp.SR.tcDelegatesCannotBeCurried(), m))
36993699
let ttps = thisTyconRef.Typars m
3700-
let fparams = curriedArgInfos.Head |> List.map MakeSlotParam
3700+
let fparams =
3701+
curriedArgInfos.Head
3702+
|> List.map (fun (ty, argInfo: ArgReprInfo) ->
3703+
let ty =
3704+
if HasFSharpAttribute g g.attrib_OptionalArgumentAttribute argInfo.Attribs then
3705+
match TryFindFSharpAttribute g g.attrib_StructAttribute argInfo.Attribs with
3706+
| Some (Attrib(range=m)) ->
3707+
checkLanguageFeatureAndRecover g.langVersion LanguageFeature.SupportValueOptionsAsOptionalParameters m
3708+
mkValueOptionTy g ty
3709+
| _ ->
3710+
mkOptionTy g ty
3711+
else ty
3712+
3713+
MakeSlotParam(ty, argInfo))
37013714
TFSharpDelegate (MakeSlotSig("Invoke", thisTy, ttps, [], [fparams], returnTy))
37023715
| _ ->
37033716
error(InternalError("should have inferred tycon kind", m))

src/Compiler/Checking/CheckPatterns.fs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,6 @@ let UnifyRefTupleType contextInfo (cenv: cenv) denv m ty ps =
5858
AddCxTypeEqualsType contextInfo denv cenv.css m ty (TType_tuple (tupInfoRef, ptys))
5959
ptys
6060

61-
let inline mkOptionalParamTyBasedOnAttribute (g: TcGlobals) tyarg attribs =
62-
if g.langVersion.SupportsFeature(LanguageFeature.SupportValueOptionsAsOptionalParameters)
63-
&& findSynAttribute "StructAttribute" attribs
64-
then
65-
mkValueOptionTy g tyarg
66-
else
67-
mkOptionTy g tyarg
68-
6961
let rec TryAdjustHiddenVarNameToCompGenName (cenv: cenv) env (id: Ident) altNameRefCellOpt =
7062
match altNameRefCellOpt with
7163
| Some ({contents = SynSimplePatAlternativeIdInfo.Undecided altId } as altNameRefCell) ->

src/Compiler/Checking/Expressions/CheckExpressions.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4307,8 +4307,8 @@ and TcValSpec (cenv: cenv) env declKind newOk containerInfo memFlagsOpt thisTyOp
43074307
((List.mapSquared fst curriedArgTys), valSynInfo.CurriedArgInfos)
43084308
||> List.map2 (fun argTys argInfos ->
43094309
(argTys, argInfos)
4310-
||> List.map2 (fun argTy argInfo ->
4311-
if SynInfo.IsOptionalArg argInfo then mkOptionTy g argTy
4310+
||> List.map2 (fun argTy (SynArgInfo(attribs, _, _) as argInfo) ->
4311+
if SynInfo.IsOptionalArg argInfo then mkOptionalParamTyBasedOnAttribute g argTy attribs
43124312
else argTy))
43134313
mkIteratedFunTy g (List.map (mkRefTupledTy g) curriedArgTys) returnTy
43144314
else tyR

src/Compiler/Checking/Expressions/CheckExpressionsOps.fs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,3 +384,12 @@ let compileSeqExprMatchClauses (cenv: TcFileState) env inputExprMark (pat: Patte
384384
bindPatTy
385385
genInnerTy
386386
tclauses
387+
388+
let inline mkOptionalParamTyBasedOnAttribute (g: TcGlobals.TcGlobals) tyarg attribs =
389+
if
390+
g.langVersion.SupportsFeature(LanguageFeature.SupportValueOptionsAsOptionalParameters)
391+
&& findSynAttribute "StructAttribute" attribs
392+
then
393+
mkValueOptionTy g tyarg
394+
else
395+
mkOptionTy g tyarg

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,25 @@ namespace FSharpTest
4646
"""
4747
|> compile
4848
|> shouldSucceed
49+
50+
[<Fact>]
51+
let ``Delegate with optional parameter`` () =
52+
FSharp """open System.Runtime.CompilerServices
53+
type A = delegate of [<CallerLineNumber>] ?a: int -> unit
54+
let f = fun (a: int option) -> defaultArg a 100 |> printf "line: %d"
55+
let a = A f
56+
a.Invoke()"""
57+
|> compileExeAndRun
58+
|> shouldSucceed
59+
|> verifyOutput "line: 5"
60+
61+
[<Fact>]
62+
let ``Delegate with struct optional parameter`` () =
63+
FSharp """type A = delegate of [<Struct>] ?a: int -> unit
64+
let f = fun (a: int voption) -> defaultValueArg a 100 |> printf "line: %d"
65+
let a = A f
66+
a.Invoke(5)"""
67+
|> withLangVersionPreview
68+
|> compileExeAndRun
69+
|> shouldSucceed
70+
|> verifyOutput "line: 5"

0 commit comments

Comments
 (0)