From a1c4a7cc78a93b17a74f9a09f99ef511851f1c8d Mon Sep 17 00:00:00 2001 From: ijklam <43789618+Tangent-90@users.noreply.github.com> Date: Sat, 15 Mar 2025 20:22:22 +0800 Subject: [PATCH 1/6] fix delegate with option parameter --- src/Compiler/Checking/CheckDeclarations.fs | 15 +++++++++++- .../DelegateTypes/DelegateDefinition.fs | 23 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index 8422bd40833..78acf62bb98 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -3697,7 +3697,20 @@ module EstablishTypeDefinitionCores = if curriedArgInfos.Length < 1 then error(Error(FSComp.SR.tcInvalidDelegateSpecification(), m)) if curriedArgInfos.Length > 1 then error(Error(FSComp.SR.tcDelegatesCannotBeCurried(), m)) let ttps = thisTyconRef.Typars m - let fparams = curriedArgInfos.Head |> List.map MakeSlotParam + 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 + + MakeSlotParam(ty, argInfo)) TFSharpDelegate (MakeSlotSig("Invoke", thisTy, ttps, [], [fparams], returnTy)) | _ -> error(InternalError("should have inferred tycon kind", m)) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs index b14bc83ce3f..74e21061194 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs @@ -46,3 +46,26 @@ namespace FSharpTest """ |> compile |> shouldSucceed + + [] + let ``Delegate with optional parameter`` () = + FSharp """open System.Runtime.CompilerServices +type A = delegate of [] ?a: int -> unit +let f = fun (a: int option) -> defaultArg a 100 |> printfn "line: %d" +let a = A f +a.Invoke()""" + |> compileExeAndRun + |> shouldSucceed + |> verifyOutput "line: 5" + + [] + let ``Delegate with struct optional parameter`` () = + FSharp """open System.Runtime.CompilerServices +type A = delegate of [] ?a: int -> unit +let f = fun (a: int voption) -> defaultArg a 100 |> printfn "line: %d" +let a = A f +a.Invoke()""" + |> withLangVersionPreview + |> compileExeAndRun + |> shouldSucceed + |> verifyOutput "line: 5" From e09f59203949cb7c84783da26a01f7db15564297 Mon Sep 17 00:00:00 2001 From: ijklam <43789618+Tangent-90@users.noreply.github.com> Date: Sat, 15 Mar 2025 20:31:06 +0800 Subject: [PATCH 2/6] release note --- docs/release-notes/.FSharp.Compiler.Service/9.0.300.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md index 12f4074a4a0..73c5e1d47de 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md @@ -16,6 +16,7 @@ * 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)) * Fix for missing parse diagnostics in TransparentCompiler.ParseAndCheckProject ([PR #18366](https://github.com/dotnet/fsharp/pull/18366)) * Miscellanous parentheses analyzer fixes. ([PR #18350](https://github.com/dotnet/fsharp/pull/18350)) +* 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)) ### Added * Added missing type constraints in FCS. ([PR #18241](https://github.com/dotnet/fsharp/pull/18241)) From d9824a4d0be97a21210de598c463fa5ca5da7609 Mon Sep 17 00:00:00 2001 From: ijklam <43789618+Tangent-90@users.noreply.github.com> Date: Sat, 15 Mar 2025 20:34:19 +0800 Subject: [PATCH 3/6] typo --- .../BasicGrammarElements/DelegateTypes/DelegateDefinition.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs index 74e21061194..3551af86250 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs @@ -62,7 +62,7 @@ a.Invoke()""" let ``Delegate with struct optional parameter`` () = FSharp """open System.Runtime.CompilerServices type A = delegate of [] ?a: int -> unit -let f = fun (a: int voption) -> defaultArg a 100 |> printfn "line: %d" +let f = fun (a: int voption) -> defaultValueArg a 100 |> printfn "line: %d" let a = A f a.Invoke()""" |> withLangVersionPreview From bcedeca9ab551cad65bdc3ea8aaa5b17754672ac Mon Sep 17 00:00:00 2001 From: ijklam <43789618+Tangent-90@users.noreply.github.com> Date: Sat, 15 Mar 2025 21:06:16 +0800 Subject: [PATCH 4/6] fix struct optional parameter --- src/Compiler/Checking/CheckPatterns.fs | 8 -------- src/Compiler/Checking/Expressions/CheckExpressions.fs | 4 ++-- src/Compiler/Checking/Expressions/CheckExpressionsOps.fs | 9 +++++++++ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index cdffd9acb7f..9587c3b5e9f 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -58,14 +58,6 @@ let UnifyRefTupleType contextInfo (cenv: cenv) denv m ty ps = AddCxTypeEqualsType contextInfo denv cenv.css m ty (TType_tuple (tupInfoRef, ptys)) ptys -let inline mkOptionalParamTyBasedOnAttribute (g: TcGlobals) tyarg attribs = - if g.langVersion.SupportsFeature(LanguageFeature.SupportValueOptionsAsOptionalParameters) - && findSynAttribute "StructAttribute" attribs - then - mkValueOptionTy g tyarg - else - mkOptionTy g tyarg - let rec TryAdjustHiddenVarNameToCompGenName (cenv: cenv) env (id: Ident) altNameRefCellOpt = match altNameRefCellOpt with | Some ({contents = SynSimplePatAlternativeIdInfo.Undecided altId } as altNameRefCell) -> diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index 9dba2586e0f..f1e6960cc21 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -4307,8 +4307,8 @@ and TcValSpec (cenv: cenv) env declKind newOk containerInfo memFlagsOpt thisTyOp ((List.mapSquared fst curriedArgTys), valSynInfo.CurriedArgInfos) ||> List.map2 (fun argTys argInfos -> (argTys, argInfos) - ||> List.map2 (fun argTy argInfo -> - if SynInfo.IsOptionalArg argInfo then mkOptionTy g argTy + ||> List.map2 (fun argTy (SynArgInfo(attribs, _, _) as argInfo) -> + if SynInfo.IsOptionalArg argInfo then mkOptionalParamTyBasedOnAttribute g argTy attribs else argTy)) mkIteratedFunTy g (List.map (mkRefTupledTy g) curriedArgTys) returnTy else tyR diff --git a/src/Compiler/Checking/Expressions/CheckExpressionsOps.fs b/src/Compiler/Checking/Expressions/CheckExpressionsOps.fs index 4b9de82d758..7f5ff2f9f64 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressionsOps.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressionsOps.fs @@ -384,3 +384,12 @@ let compileSeqExprMatchClauses (cenv: TcFileState) env inputExprMark (pat: Patte bindPatTy genInnerTy tclauses + +let inline mkOptionalParamTyBasedOnAttribute (g: TcGlobals.TcGlobals) tyarg attribs = + if + g.langVersion.SupportsFeature(LanguageFeature.SupportValueOptionsAsOptionalParameters) + && findSynAttribute "StructAttribute" attribs + then + mkValueOptionTy g tyarg + else + mkOptionTy g tyarg From 91971de34c01242085f5e1cce95b6232dc38b119 Mon Sep 17 00:00:00 2001 From: ijklam <43789618+Tangent-90@users.noreply.github.com> Date: Sat, 15 Mar 2025 21:07:41 +0800 Subject: [PATCH 5/6] fix test --- .../BasicGrammarElements/DelegateTypes/DelegateDefinition.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs index 3551af86250..23b1ba6073e 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs @@ -51,7 +51,7 @@ namespace FSharpTest let ``Delegate with optional parameter`` () = FSharp """open System.Runtime.CompilerServices type A = delegate of [] ?a: int -> unit -let f = fun (a: int option) -> defaultArg a 100 |> printfn "line: %d" +let f = fun (a: int option) -> defaultArg a 100 |> printf "line: %d" let a = A f a.Invoke()""" |> compileExeAndRun @@ -62,7 +62,7 @@ a.Invoke()""" let ``Delegate with struct optional parameter`` () = FSharp """open System.Runtime.CompilerServices type A = delegate of [] ?a: int -> unit -let f = fun (a: int voption) -> defaultValueArg a 100 |> printfn "line: %d" +let f = fun (a: int voption) -> defaultValueArg a 100 |> printf "line: %d" let a = A f a.Invoke()""" |> withLangVersionPreview From f8f2b2b033a310dcc9e234152824a54c53ba7f8d Mon Sep 17 00:00:00 2001 From: ijklam <43789618+Tangent-90@users.noreply.github.com> Date: Sat, 15 Mar 2025 21:10:39 +0800 Subject: [PATCH 6/6] fix test --- .../BasicGrammarElements/DelegateTypes/DelegateDefinition.fs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs index 23b1ba6073e..1f4462fa6d3 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/DelegateTypes/DelegateDefinition.fs @@ -60,11 +60,10 @@ a.Invoke()""" [] let ``Delegate with struct optional parameter`` () = - FSharp """open System.Runtime.CompilerServices -type A = delegate of [] ?a: int -> unit + FSharp """type A = delegate of [] ?a: int -> unit let f = fun (a: int voption) -> defaultValueArg a 100 |> printf "line: %d" let a = A f -a.Invoke()""" +a.Invoke(5)""" |> withLangVersionPreview |> compileExeAndRun |> shouldSucceed