From bae08ee706766e1a025323c85408827f52f86d0f Mon Sep 17 00:00:00 2001 From: dawe Date: Thu, 30 Nov 2023 15:05:16 +0100 Subject: [PATCH 1/8] allow the TailCall attribute to be defined outside of FSharp.Core by just checking the CompiledName to be "TailCallAttribute" --- src/Compiler/Checking/TailCallChecks.fs | 10 +++---- .../ErrorMessages/TailCallAttribute.fs | 29 +++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/Compiler/Checking/TailCallChecks.fs b/src/Compiler/Checking/TailCallChecks.fs index 1faa9a50a35..05b4672de5e 100644 --- a/src/Compiler/Checking/TailCallChecks.fs +++ b/src/Compiler/Checking/TailCallChecks.fs @@ -56,6 +56,9 @@ type TailCall = | TailCall.Yes _ -> TailCall.Yes TailCallReturnType.NonVoid | TailCall.No -> TailCall.No +let hasTailCallAttrib (attribs: Attribs) = + attribs |> List.exists (fun a -> a.TyconRef.CompiledName = "TailCallAttribute") + let IsValRefIsDllImport g (vref: ValRef) = vref.Attribs |> HasFSharpAttributeOpt g g.attrib_DllImportAttribute @@ -738,10 +741,7 @@ let CheckModuleBinding cenv (isRec: bool) (TBind _ as bind) = | Some info -> info.HasNoArgs | _ -> false - if - (not isRec || isNotAFunction) - && HasFSharpAttribute cenv.g cenv.g.attrib_TailCallAttribute bind.Var.Attribs - then + if (not isRec || isNotAFunction) && hasTailCallAttrib bind.Var.Attribs then warning (Error(FSComp.SR.chkTailCallAttrOnNonRec (), bind.Var.Range)) // Check if a let binding to the result of a rec expression is not inside the rec expression @@ -807,7 +807,7 @@ and CheckDefnInModule cenv mdef = let mustTailCall = Seq.fold (fun mustTailCall (v: Val) -> - if HasFSharpAttribute cenv.g cenv.g.attrib_TailCallAttribute v.Attribs then + if hasTailCallAttrib v.Attribs then let newSet = Zset.add v mustTailCall newSet else diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs index 3366ed91c3f..e2ba506696d 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs @@ -1486,3 +1486,32 @@ namespace N Message = "The TailCall attribute should only be applied to recursive functions." } ] + + [] + let ``Warn about alternative attribute on recursive let-bound value`` () = + """ +namespace N + + open System + + module M = + + [] + type TailCallAttribute() = inherit Attribute() + + [] + let rec f x = 1 + f x + """ + |> FSharp + |> withLangVersionPreview + |> compile + |> shouldFail + |> withResults [ + { Error = Warning 3569 + Range = { StartLine = 12 + StartColumn = 27 + EndLine = 12 + EndColumn = 30 } + Message = + "The member or function 'f' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way." } + ] From efde7e78272bc02234915524104eb6e0fca9fa4f Mon Sep 17 00:00:00 2001 From: dawe Date: Mon, 4 Dec 2023 10:59:50 +0100 Subject: [PATCH 2/8] check the FullName to make sure it's in the FSharp.Core namespace --- src/Compiler/Checking/TailCallChecks.fs | 3 ++- .../ErrorMessages/TailCallAttribute.fs | 22 +++++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/Compiler/Checking/TailCallChecks.fs b/src/Compiler/Checking/TailCallChecks.fs index 05b4672de5e..47ced444000 100644 --- a/src/Compiler/Checking/TailCallChecks.fs +++ b/src/Compiler/Checking/TailCallChecks.fs @@ -57,7 +57,8 @@ type TailCall = | TailCall.No -> TailCall.No let hasTailCallAttrib (attribs: Attribs) = - attribs |> List.exists (fun a -> a.TyconRef.CompiledName = "TailCallAttribute") + attribs + |> List.exists (fun a -> a.TyconRef.CompiledRepresentationForNamedType.FullName = "Microsoft.FSharp.Core.TailCallAttribute") let IsValRefIsDllImport g (vref: ValRef) = vref.Attribs |> HasFSharpAttributeOpt g g.attrib_DllImportAttribute diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs index e2ba506696d..0fe5c608ef6 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs @@ -1488,19 +1488,17 @@ namespace N ] [] - let ``Warn about alternative attribute on recursive let-bound value`` () = + let ``Warn about self-defined attribute`` () = // is the analysis available for uers of older FSharp.Core versions """ -namespace N +module Microsoft.FSharp.Core open System - module M = - - [] - type TailCallAttribute() = inherit Attribute() + [] + type TailCallAttribute() = inherit Attribute() - [] - let rec f x = 1 + f x + [] + let rec f x = 1 + f x """ |> FSharp |> withLangVersionPreview @@ -1508,10 +1506,10 @@ namespace N |> shouldFail |> withResults [ { Error = Warning 3569 - Range = { StartLine = 12 - StartColumn = 27 - EndLine = 12 - EndColumn = 30 } + Range = { StartLine = 10 + StartColumn = 23 + EndLine = 10 + EndColumn = 26 } Message = "The member or function 'f' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way." } ] From e85b80d4530f00c1de2f51b2ac8f34b6764d9961 Mon Sep 17 00:00:00 2001 From: dawe Date: Mon, 4 Dec 2023 11:23:05 +0100 Subject: [PATCH 3/8] add changelog entry --- docs/release-notes/FSharp.Compiler.Service/8.0.200.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/FSharp.Compiler.Service/8.0.200.md b/docs/release-notes/FSharp.Compiler.Service/8.0.200.md index c0d199a7864..f7c1fff5284 100644 --- a/docs/release-notes/FSharp.Compiler.Service/8.0.200.md +++ b/docs/release-notes/FSharp.Compiler.Service/8.0.200.md @@ -1,2 +1,3 @@ - Miscellaneous fixes to parens analysis - https://github.com/dotnet/fsharp/pull/16262 -- Fixes #16359 - correctly handle imports with 0 length public key tokens - https://github.com/dotnet/fsharp/pull/16363 \ No newline at end of file +- Fixes #16359 - correctly handle imports with 0 length public key tokens - https://github.com/dotnet/fsharp/pull/16363 +- Allow usage of `[]` with older `FSharp.Core` package versions - https://github.com/dotnet/fsharp/pull/TODO \ No newline at end of file From 8f218d2aac6d444a6786f61869f38d5e11f6d836 Mon Sep 17 00:00:00 2001 From: dawe Date: Mon, 4 Dec 2023 11:27:36 +0100 Subject: [PATCH 4/8] add PR number to changelog entry --- docs/release-notes/FSharp.Compiler.Service/8.0.200.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/release-notes/FSharp.Compiler.Service/8.0.200.md b/docs/release-notes/FSharp.Compiler.Service/8.0.200.md index f7c1fff5284..54065130a1c 100644 --- a/docs/release-notes/FSharp.Compiler.Service/8.0.200.md +++ b/docs/release-notes/FSharp.Compiler.Service/8.0.200.md @@ -1,3 +1,3 @@ - Miscellaneous fixes to parens analysis - https://github.com/dotnet/fsharp/pull/16262 - Fixes #16359 - correctly handle imports with 0 length public key tokens - https://github.com/dotnet/fsharp/pull/16363 -- Allow usage of `[]` with older `FSharp.Core` package versions - https://github.com/dotnet/fsharp/pull/TODO \ No newline at end of file +- Allow usage of `[]` with older `FSharp.Core` package versions - https://github.com/dotnet/fsharp/pull/16373 \ No newline at end of file From 1ce4cde9a6bb32724031abace1475beb5402e5e5 Mon Sep 17 00:00:00 2001 From: dawe Date: Mon, 4 Dec 2023 13:35:14 +0100 Subject: [PATCH 5/8] - remove member attrib_TailCallAttribute from TcGlobals - move hasTailCallAttrib from TailCallChecks.fs to TcGlobals --- src/Compiler/Checking/TailCallChecks.fs | 8 ++------ src/Compiler/TypedTree/TcGlobals.fs | 5 ++++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Compiler/Checking/TailCallChecks.fs b/src/Compiler/Checking/TailCallChecks.fs index 47ced444000..a962252fe7f 100644 --- a/src/Compiler/Checking/TailCallChecks.fs +++ b/src/Compiler/Checking/TailCallChecks.fs @@ -56,10 +56,6 @@ type TailCall = | TailCall.Yes _ -> TailCall.Yes TailCallReturnType.NonVoid | TailCall.No -> TailCall.No -let hasTailCallAttrib (attribs: Attribs) = - attribs - |> List.exists (fun a -> a.TyconRef.CompiledRepresentationForNamedType.FullName = "Microsoft.FSharp.Core.TailCallAttribute") - let IsValRefIsDllImport g (vref: ValRef) = vref.Attribs |> HasFSharpAttributeOpt g g.attrib_DllImportAttribute @@ -742,7 +738,7 @@ let CheckModuleBinding cenv (isRec: bool) (TBind _ as bind) = | Some info -> info.HasNoArgs | _ -> false - if (not isRec || isNotAFunction) && hasTailCallAttrib bind.Var.Attribs then + if (not isRec || isNotAFunction) && cenv.g.HasTailCallAttrib bind.Var.Attribs then warning (Error(FSComp.SR.chkTailCallAttrOnNonRec (), bind.Var.Range)) // Check if a let binding to the result of a rec expression is not inside the rec expression @@ -808,7 +804,7 @@ and CheckDefnInModule cenv mdef = let mustTailCall = Seq.fold (fun mustTailCall (v: Val) -> - if hasTailCallAttrib v.Attribs then + if cenv.g.HasTailCallAttrib v.Attribs then let newSet = Zset.add v mustTailCall newSet else diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs index e754a5ad4ae..675d24e8165 100755 --- a/src/Compiler/TypedTree/TcGlobals.fs +++ b/src/Compiler/TypedTree/TcGlobals.fs @@ -1516,7 +1516,6 @@ type TcGlobals( member val attrib_CompilerFeatureRequiredAttribute = findSysAttrib "System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute" member val attrib_SetsRequiredMembersAttribute = findSysAttrib "System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute" member val attrib_RequiredMemberAttribute = findSysAttrib "System.Runtime.CompilerServices.RequiredMemberAttribute" - member val attrib_TailCallAttribute = mk_MFCore_attrib "TailCallAttribute" member g.improveType tcref tinst = improveTy tcref tinst @@ -1852,6 +1851,10 @@ type TcGlobals( member _.DebuggerNonUserCodeAttribute = debuggerNonUserCodeAttribute + member _.HasTailCallAttrib (attribs: Attribs) = + attribs + |> List.exists (fun a -> a.TyconRef.CompiledRepresentationForNamedType.FullName = "Microsoft.FSharp.Core.TailCallAttribute") + member _.MakeInternalsVisibleToAttribute(simpleAssemName) = mkILCustomAttribute (tref_InternalsVisibleToAttribute, [ilg.typ_String], [ILAttribElem.String (Some simpleAssemName)], []) From 1b41204ea51aec9f34cd809b94cdbffb737b3cea Mon Sep 17 00:00:00 2001 From: dawe Date: Wed, 13 Dec 2023 11:25:28 +0100 Subject: [PATCH 6/8] Update tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs Co-authored-by: Petr --- .../ErrorMessages/TailCallAttribute.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs index 0fe5c608ef6..639aaab83b9 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs @@ -1488,7 +1488,7 @@ namespace N ] [] - let ``Warn about self-defined attribute`` () = // is the analysis available for uers of older FSharp.Core versions + let ``Warn about self-defined attribute`` () = // is the analysis available for users of older FSharp.Core versions """ module Microsoft.FSharp.Core From 016810475721805db2e4cf43629fd4e7fb8afcf0 Mon Sep 17 00:00:00 2001 From: dawe Date: Wed, 13 Dec 2023 15:18:30 +0100 Subject: [PATCH 7/8] remote "withLangVersionPreview" from test for self-defined attribute --- .../ErrorMessages/TailCallAttribute.fs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs index 639aaab83b9..9bad5b4d0af 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs @@ -1501,7 +1501,6 @@ module Microsoft.FSharp.Core let rec f x = 1 + f x """ |> FSharp - |> withLangVersionPreview |> compile |> shouldFail |> withResults [ From 6226e9633b74147c939667eb4b398f8d8c8e8b01 Mon Sep 17 00:00:00 2001 From: dawe Date: Wed, 13 Dec 2023 16:46:28 +0100 Subject: [PATCH 8/8] add sample project to demonstrate --- .../SelfDefinedTailCallAttribute/Attribute.fs | 6 ++++++ .../SelfDefinedTailCallAttribute/Program.fs | 13 ++++++++++++ .../tailcallaltattr.fsproj | 20 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 tests/projects/misc/SelfDefinedTailCallAttribute/Attribute.fs create mode 100644 tests/projects/misc/SelfDefinedTailCallAttribute/Program.fs create mode 100644 tests/projects/misc/SelfDefinedTailCallAttribute/tailcallaltattr.fsproj diff --git a/tests/projects/misc/SelfDefinedTailCallAttribute/Attribute.fs b/tests/projects/misc/SelfDefinedTailCallAttribute/Attribute.fs new file mode 100644 index 00000000000..afa7331896d --- /dev/null +++ b/tests/projects/misc/SelfDefinedTailCallAttribute/Attribute.fs @@ -0,0 +1,6 @@ +module Microsoft.FSharp.Core + + open System + + [] + type TailCallAttribute() = inherit Attribute() diff --git a/tests/projects/misc/SelfDefinedTailCallAttribute/Program.fs b/tests/projects/misc/SelfDefinedTailCallAttribute/Program.fs new file mode 100644 index 00000000000..7652c7c2ecb --- /dev/null +++ b/tests/projects/misc/SelfDefinedTailCallAttribute/Program.fs @@ -0,0 +1,13 @@ +namespace N + + module M = + + open Microsoft.FSharp.Core + + [] + let rec f x = 1 + f x + + [] + let main argv = + printfn "Hello from F#" + 0 diff --git a/tests/projects/misc/SelfDefinedTailCallAttribute/tailcallaltattr.fsproj b/tests/projects/misc/SelfDefinedTailCallAttribute/tailcallaltattr.fsproj new file mode 100644 index 00000000000..92c5ae861d4 --- /dev/null +++ b/tests/projects/misc/SelfDefinedTailCallAttribute/tailcallaltattr.fsproj @@ -0,0 +1,20 @@ + + + Exe + net6.0 + true + preview + + + + $(MSBuildThisFileDirectory)../../../../artifacts/bin/fsc/Debug/net8.0/fsc.dll + + + + + + + + + + \ No newline at end of file