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 df7ea7a5f38..eee6e9d09e3 100644 --- a/docs/release-notes/FSharp.Compiler.Service/8.0.200.md +++ b/docs/release-notes/FSharp.Compiler.Service/8.0.200.md @@ -3,4 +3,5 @@ - Parens analysis: fix some parenthesization corner-cases in record expressions - https://github.com/dotnet/fsharp/pull/16370 - Parens analysis: keep parens in method calls in dot-lambdas - https://github.com/dotnet/fsharp/pull/16395 - Fixes #16359 - correctly handle imports with 0 length public key tokens - https://github.com/dotnet/fsharp/pull/16363 -- Raise a new error when interfaces with auto properties are implemented on constructor-less types - https://github.com/dotnet/fsharp/pull/16352 \ No newline at end of file +- Raise a new error when interfaces with auto properties are implemented on constructor-less types - https://github.com/dotnet/fsharp/pull/16352 +- Allow usage of `[]` with older `FSharp.Core` package versions - https://github.com/dotnet/fsharp/pull/16373 diff --git a/src/Compiler/Checking/TailCallChecks.fs b/src/Compiler/Checking/TailCallChecks.fs index 1faa9a50a35..a962252fe7f 100644 --- a/src/Compiler/Checking/TailCallChecks.fs +++ b/src/Compiler/Checking/TailCallChecks.fs @@ -738,10 +738,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) && 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 @@ -807,7 +804,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 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 4755bd6c915..fa90f06ed55 100644 --- a/src/Compiler/TypedTree/TcGlobals.fs +++ b/src/Compiler/TypedTree/TcGlobals.fs @@ -1532,7 +1532,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 @@ -1870,6 +1869,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)], []) diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs index 3366ed91c3f..9bad5b4d0af 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs @@ -1486,3 +1486,29 @@ namespace N Message = "The TailCall attribute should only be applied to recursive functions." } ] + + [] + let ``Warn about self-defined attribute`` () = // is the analysis available for users of older FSharp.Core versions + """ +module Microsoft.FSharp.Core + + open System + + [] + type TailCallAttribute() = inherit Attribute() + + [] + let rec f x = 1 + f x + """ + |> FSharp + |> compile + |> shouldFail + |> withResults [ + { Error = Warning 3569 + 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." } + ] 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