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.
+
+ 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.
+
+ 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.
+
+ "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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ '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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 'AssemblyKeyNameAttribute' は非推奨になりました。代わりに 'AssemblyKeyFileAttribute' を使用してください。
@@ -247,6 +252,11 @@
メンバーまたは関数に 'TailCall' 属性があるが、末尾の再帰的な方法で使用されていない場合に警告を発生させます。
+
+
+ Raises warnings if the 'TailCall' attribute is used on non-recursive functions.
+
+ フレキシブル型の制約積集合
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.
+
+ 'AssemblyKeyNameAttribute'는 사용되지 않습니다. 대신 'AssemblyKeyFileAttribute'를 사용하세요.
@@ -247,6 +252,11 @@
멤버 또는 함수에 'TailCall' 특성이 있지만 비상 재귀적인 방식으로 사용되지 않는 경우 경고를 발생합니다.
+
+
+ Raises warnings if the 'TailCall' attribute is used on non-recursive functions.
+
+ 유연한 형식의 제약 조건 교집합
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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ 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.
+
+ Атрибут "AssemblyKeyNameAttribute" является устаревшим. Используйте вместо него атрибут "AssemblyKeyFileAttribute".
@@ -247,6 +252,11 @@
Выдает предупреждения, если элемент или функция имеет атрибут "TailCall", но не используется в рекурсивном хвостовом режиме.
+
+
+ Raises warnings if the 'TailCall' attribute is used on non-recursive functions.
+
+ Пересечение ограничений на гибких типах
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.
+
+ '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.
+
+ 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.
+
+ "AssemblyKeyNameAttribute" 已被弃用。请改为使用 "AssemblyKeyFileAttribute"。
@@ -247,6 +252,11 @@
如果成员或函数具有 "TailCall" 属性,但未以尾递归方式使用,则引发警告。
+
+
+ Raises warnings if the 'TailCall' attribute is used on non-recursive functions.
+
+ 灵活类型的约束交集
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.
+
+ 'AssemblyKeyNameAttribute' 已淘汰。請改用 'AssemblyKeyFileAttribute'。
@@ -247,6 +252,11 @@
如果成員或函式具有 'TailCall' 屬性,但未以尾遞迴方式使用,則引發警告。
+
+
+ Raises warnings if the 'TailCall' attribute is used on non-recursive functions.
+
+ 彈性類型上的條件約束交集
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." }
+ ]