From 93ebb7541f9f63f352a0f1ad132ba79fd25ecd49 Mon Sep 17 00:00:00 2001 From: dawe Date: Thu, 23 Nov 2023 15:59:36 +0100 Subject: [PATCH] warn about the TailCall attribute being applied to non-rec functions or let-bound values --- src/Compiler/Checking/TailCallChecks.fs | 17 +++++ src/Compiler/FSComp.txt | 4 +- src/Compiler/Facilities/LanguageFeatures.fs | 3 + src/Compiler/Facilities/LanguageFeatures.fsi | 1 + src/Compiler/xlf/FSComp.txt.cs.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.de.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.es.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.fr.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.it.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.ja.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.ko.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.pl.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.ru.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.tr.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 10 +++ src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 10 +++ .../ErrorMessages/TailCallAttribute.fs | 72 +++++++++++++++++++ 18 files changed, 226 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Checking/TailCallChecks.fs b/src/Compiler/Checking/TailCallChecks.fs index 23dc7aa7748..ad29719c9df 100644 --- a/src/Compiler/Checking/TailCallChecks.fs +++ b/src/Compiler/Checking/TailCallChecks.fs @@ -727,6 +727,23 @@ and CheckBindings cenv binds = CheckBinding cenv false PermitByRefExpr.Yes bind let CheckModuleBinding cenv (isRec: bool) (TBind _ as bind) = + + // warn for non-rec functions which have the attribute + if + cenv.reportErrors + && cenv.g.langVersion.SupportsFeature LanguageFeature.WarningWhenTailCallAttrOnNonRec + then + let isNotAFunction = + match bind.Var.ValReprInfo with + | Some info -> info.HasNoArgs + | _ -> false + + if + (not isRec || isNotAFunction) + && HasFSharpAttribute cenv.g cenv.g.attrib_TailCallAttribute bind.Var.Attribs + then + warning (Error(FSComp.SR.chkTailCallAttrOnNonRec (), bind.Var.Range)) + // Check that a let binding to the result of a rec expression is not inside the rec expression // see test ``Warn for invalid tailcalls in seq expression because of bind`` for an example // see test ``Warn successfully for rec call in binding`` for an example diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 13aa99fd609..85195fce8ed 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1590,6 +1590,7 @@ featureExtendedFixedBindings,"extended fixed bindings for byref and GetPinnableR featurePreferStringGetPinnableReference,"prefer String.GetPinnableReference in fixed bindings" featurePreferExtensionMethodOverPlainProperty,"prefer extension method over plain property" featureWarningIndexedPropertiesGetSetSameType,"Indexed properties getter and setter must have the same type" +featureChkTailCallAttrOnNonRec,"Raises warnings if the 'TailCall' attribute is used on non-recursive functions." 3354,tcNotAFunctionButIndexerNamedIndexingNotYetEnabled,"This value supports indexing, e.g. '%s.[index]'. The syntax '%s[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation." 3354,tcNotAFunctionButIndexerIndexingNotYetEnabled,"This expression supports indexing, e.g. 'expr.[index]'. The syntax 'expr[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation." 3355,tcNotAnIndexerNamedIndexingNotYetEnabled,"The value '%s' is not a function and does not support index notation." @@ -1731,4 +1732,5 @@ featureUnmanagedConstraintCsharpInterop,"Interop between C#'s and F#'s unmanaged 3584,tcDotLambdaAtNotSupportedExpression,"Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'." 3855,tcNoStaticMemberFoundForOverride,"No static abstract member was found that corresponds to this override" 3859,tcNoStaticPropertyFoundForOverride,"No static abstract property was found that corresponds to this override" -3860,chkStaticMembersOnObjectExpressions,"Object expressions cannot implement interfaces with static abstract members or declare static members." \ No newline at end of file +3860,chkStaticMembersOnObjectExpressions,"Object expressions cannot implement interfaces with static abstract members or declare static members." +3861,chkTailCallAttrOnNonRec,"The TailCall attribute should only be applied to recursive functions." \ No newline at end of file diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index 7f9fb1f4b58..13a80b2187e 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -81,6 +81,7 @@ type LanguageFeature = | PreferStringGetPinnableReference | PreferExtensionMethodOverPlainProperty | WarningIndexedPropertiesGetSetSameType + | WarningWhenTailCallAttrOnNonRec /// LanguageVersion management type LanguageVersion(versionText) = @@ -189,6 +190,7 @@ type LanguageVersion(versionText) = LanguageFeature.UnmanagedConstraintCsharpInterop, previewVersion LanguageFeature.PreferExtensionMethodOverPlainProperty, previewVersion LanguageFeature.WarningIndexedPropertiesGetSetSameType, previewVersion + LanguageFeature.WarningWhenTailCallAttrOnNonRec, previewVersion ] static let defaultLanguageVersion = LanguageVersion("default") @@ -327,6 +329,7 @@ type LanguageVersion(versionText) = | LanguageFeature.PreferStringGetPinnableReference -> FSComp.SR.featurePreferStringGetPinnableReference () | LanguageFeature.PreferExtensionMethodOverPlainProperty -> FSComp.SR.featurePreferExtensionMethodOverPlainProperty () | LanguageFeature.WarningIndexedPropertiesGetSetSameType -> FSComp.SR.featureWarningIndexedPropertiesGetSetSameType () + | LanguageFeature.WarningWhenTailCallAttrOnNonRec -> FSComp.SR.featureChkTailCallAttrOnNonRec () /// Get a version string associated with the given feature. static member GetFeatureVersionString feature = diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index 93b8b231534..a804bd42824 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -72,6 +72,7 @@ type LanguageFeature = /// RFC-1137 | PreferExtensionMethodOverPlainProperty | WarningIndexedPropertiesGetSetSameType + | WarningWhenTailCallAttrOnNonRec /// LanguageVersion management type LanguageVersion = diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index e00ae35e455..ceda01eecd5 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. Atribut AssemblyKeyNameAttribute je zastaralý. Použijte místo něj AssemblyKeyFileAttribute. @@ -247,6 +252,11 @@ Vyvolá upozornění, pokud člen nebo funkce má atribut „TailCall“, ale nepoužívá se koncovým (tail) rekurzivním způsobem. + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types Průnik omezení u flexibilních typů diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 2ba20dfee57..72122cfac02 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. "AssemblyKeyNameAttribute" gilt als veraltet. Verwenden Sie stattdessen "AssemblyKeyFileAttribute". @@ -247,6 +252,11 @@ Löst Warnungen aus, wenn ein Member oder eine Funktion das Attribut "TailCall" aufweist, aber nicht endrekursiv verwendet wird. + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types Einschränkungsüberschneidung für flexible Typen diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index a240ae2b02a..8488c88e94a 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. El elemento "AssemblyKeyNameAttribute" está en desuso. Use "AssemblyKeyFileAttribute" en su lugar. @@ -247,6 +252,11 @@ Genera advertencias si un miembro o función tiene el atributo “TailCall”, pero no se usa de forma de recursión de cola. + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types Intersección de restricciones en tipos flexibles diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 6d18837734d..11cef351a82 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. 'AssemblyKeyNameAttribute' a été déprécié. Utilisez 'AssemblyKeyFileAttribute' à la place. @@ -247,6 +252,11 @@ Lève des avertissements si un membre ou une fonction possède l'attribut « TailCall », mais n'est pas utilisé de manière récursive. + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types Intersection de contraintes sur les types flexibles diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index d001d237f7b..a2019ef314d 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. L'attributo 'AssemblyKeyNameAttribute' è deprecato. In alternativa, usare 'AssemblyKeyFileAttribute'. @@ -247,6 +252,11 @@ Genera un avviso se un membro o una funzione ha l'attributo "TailCall", ma non è in uso in modo ricorsivo finale. + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types Intersezione di vincoli su tipi flessibili diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 95c48ab8f3e..81122e2575a 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. 'AssemblyKeyNameAttribute' は非推奨になりました。代わりに 'AssemblyKeyFileAttribute' を使用してください。 @@ -247,6 +252,11 @@ メンバーまたは関数に 'TailCall' 属性があるが、末尾の再帰的な方法で使用されていない場合に警告を発生させます。 + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types フレキシブル型の制約積集合 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 6eebf9bf1ff..3250f0b6c4d 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. 'AssemblyKeyNameAttribute'는 사용되지 않습니다. 대신 'AssemblyKeyFileAttribute'를 사용하세요. @@ -247,6 +252,11 @@ 멤버 또는 함수에 'TailCall' 특성이 있지만 비상 재귀적인 방식으로 사용되지 않는 경우 경고를 발생합니다. + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types 유연한 형식의 제약 조건 교집합 diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index e7b4c6348d1..eba503b5cfe 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. Element „AssemblyKeyNameAttribute” jest przestarzały. Zamiast niego użyj elementu „AssemblyKeyFileAttribute”. @@ -247,6 +252,11 @@ Zgłasza ostrzeżenia, jeśli składowa lub funkcja ma atrybut „TailCall”, ale nie jest używana w sposób cykliczny końca. + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types Przecięcie ograniczenia dla typów elastycznych diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 18e45a3e3cb..5e9d27979ca 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. O 'AssemblyKeyNameAttribute' foi preterido. Use o 'AssemblyKeyFileAttribute'. @@ -247,6 +252,11 @@ Gera avisos se um membro ou função tem o atributo "TailCall", mas não está sendo usado de maneira recursiva em cauda. + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types Interseção de restrição em tipos flexíveis diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 39bcb4d4881..326b0f97fc7 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. Атрибут "AssemblyKeyNameAttribute" является устаревшим. Используйте вместо него атрибут "AssemblyKeyFileAttribute". @@ -247,6 +252,11 @@ Выдает предупреждения, если элемент или функция имеет атрибут "TailCall", но не используется в рекурсивном хвостовом режиме. + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types Пересечение ограничений на гибких типах diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 2b41bf7ad5d..0da9467d4e3 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. 'AssemblyKeyNameAttribute' kullanım dışı bırakıldı. Bunun yerine 'AssemblyKeyFileAttribute' kullanın. @@ -247,6 +252,11 @@ Üye veya işlevi, 'TailCallAttribute' özniteliğine sahip olmasına karşın kuyruk özyinelemeli bir şekilde kullanılmıyorsa uyarı verir. + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types Esnek türlerde kısıtlama kesişimi diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index ed319784660..d0f17bbd828 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. "AssemblyKeyNameAttribute" 已被弃用。请改为使用 "AssemblyKeyFileAttribute"。 @@ -247,6 +252,11 @@ 如果成员或函数具有 "TailCall" 属性,但未以尾递归方式使用,则引发警告。 + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types 灵活类型的约束交集 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 6b693de3830..06178a6e09e 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -127,6 +127,11 @@ Object expressions cannot implement interfaces with static abstract members or declare static members. + + The TailCall attribute should only be applied to recursive functions. + The TailCall attribute should only be applied to recursive functions. + + The 'AssemblyKeyNameAttribute' has been deprecated. Use 'AssemblyKeyFileAttribute' instead. 'AssemblyKeyNameAttribute' 已淘汰。請改用 'AssemblyKeyFileAttribute'。 @@ -247,6 +252,11 @@ 如果成員或函式具有 'TailCall' 屬性,但未以尾遞迴方式使用,則引發警告。 + + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + Raises warnings if the 'TailCall' attribute is used on non-recursive functions. + + Constraint intersection on flexible types 彈性類型上的條件約束交集 diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs index 9b512c5d7e2..22549c3885a 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs @@ -1076,3 +1076,75 @@ module M = |> withLangVersion80 |> compile |> shouldSucceed + + [] + let ``Warn about attribute on non-rec function`` () = + """ +namespace N + + module M = + + [] + let someNonRecFun x = x + x + """ + |> FSharp + |> withLangVersionPreview + |> compile + |> shouldFail + |> withResults [ + { Error = Warning 3861 + Range = { StartLine = 7 + StartColumn = 13 + EndLine = 7 + EndColumn = 26 } + Message = + "The TailCall attribute should only be applied to recursive functions." } + ] + + [] + let ``Warn about attribute on non-recursive let-bound value`` () = + """ +namespace N + + module M = + + [] + let someX = 23 + """ + |> FSharp + |> withLangVersionPreview + |> compile + |> shouldFail + |> withResults [ + { Error = Warning 3861 + Range = { StartLine = 7 + StartColumn = 13 + EndLine = 7 + EndColumn = 18 } + Message = + "The TailCall attribute should only be applied to recursive functions." } + ] + + [] + let ``Warn about attribute on recursive let-bound value`` () = + """ +namespace N + + module M = + + [] + let rec someRecLetBoundValue = nameof(someRecLetBoundValue) + """ + |> FSharp + |> withLangVersionPreview + |> compile + |> shouldFail + |> withResults [ + { Error = Warning 3861 + Range = { StartLine = 7 + StartColumn = 17 + EndLine = 7 + EndColumn = 37 } + Message = + "The TailCall attribute should only be applied to recursive functions." } + ]