From b4dc66c3d3cd4b45614d2b1b903890c9c846895a Mon Sep 17 00:00:00 2001 From: dawe Date: Sat, 25 Nov 2023 00:38:56 +0100 Subject: [PATCH] warn about the TailCall attribute being applied to non-rec functions or let-bound values (#16336) Co-authored-by: Tomas Grosup --- 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 f96093bfcec..c888cebdc99 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 if a let binding to the result of a rec expression is not inside the rec expression // Check if a call of a rec expression is not inside a TryWith/TryFinally operation // see test ``Warn for invalid tailcalls in seq expression because of bind`` for an example diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 7d4e4ed6264..35f5dbf06f1 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 b37ce1ae696..a9f06c45ead 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 74efd84b92e..a94265a5913 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 cf581fbe6ee..9be392ac59c 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 d614ff991d6..9c511cc41e9 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 2e0e8e45720..000c2b00a51 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 b552c7f75c6..56d4e17511a 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 204e1cbe697..6a00f11b763 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 4ac88820bc4..d8c2d0d5361 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 5d884a4cd90..456e9026a53 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 813e26a824b..8794eb00a3e 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 c04135d09a3..f783780369c 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 e1caa8bd9f2..893e35707bc 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 bef92b3a86c..a1342c08486 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 e516c1c8c35..f9f0299c828 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs @@ -1354,3 +1354,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." } + ]