diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md index b9772f3f5ac..c4e4a6a1403 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.300.md @@ -1,4 +1,5 @@ ### Fixed +* Fix missing TailCall warning in TOp.IntegerForLoop ([PR #18399](https://github.com/dotnet/fsharp/pull/18399)) * Fix classification of `nameof` in `nameof<'T>`, `match … with nameof ident -> …`. ([Issue #10026](https://github.com/dotnet/fsharp/issues/10026), [PR #18300](https://github.com/dotnet/fsharp/pull/18300)) * Fix Realsig+ generates nested closures with incorrect Generic ([Issue #17797](https://github.com/dotnet/fsharp/issues/17797), [PR #17877](https://github.com/dotnet/fsharp/pull/17877)) * Fix optimizer internal error for records with static fields ([Issue #18165](https://github.com/dotnet/fsharp/issues/18165), [PR #18280](https://github.com/dotnet/fsharp/pull/18280)) diff --git a/src/Compiler/Checking/TailCallChecks.fs b/src/Compiler/Checking/TailCallChecks.fs index a7ea9ad802a..20e9bec8945 100644 --- a/src/Compiler/Checking/TailCallChecks.fs +++ b/src/Compiler/Checking/TailCallChecks.fs @@ -792,7 +792,12 @@ let CheckModuleBinding cenv (isRec: bool) (TBind _ as bind) = // warn for recursive calls in TryWith/TryFinally operations exprs |> Seq.iter (checkTailCall true) | Expr.Op(args = exprs) -> exprs |> Seq.iter (checkTailCall insideSubBindingOrTry) - | Expr.Sequential(expr2 = expr2) -> checkTailCall insideSubBindingOrTry expr2 + | Expr.Sequential(expr1 = expr1; expr2 = expr2) -> + match expr1 with + | Expr.Op(args = exprs; op = TOp.IntegerForLoop _) -> checkTailCall insideSubBindingOrTry expr1 + | _ -> () + + checkTailCall insideSubBindingOrTry expr2 | _ -> () checkTailCall false bodyExpr diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs index 693833ef4b8..1b68505ab1e 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/TailCallAttribute.fs @@ -773,13 +773,6 @@ namespace N |> compile |> shouldFail |> withResults [ - { Error = Warning 3569 - Range = { StartLine = 21 - StartColumn = 27 - EndLine = 21 - EndColumn = 35 } - Message = - "The member or function 'instType' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way." } { Error = Warning 3569 Range = { StartLine = 17 StartColumn = 32 @@ -787,6 +780,13 @@ namespace N EndColumn = 77 } Message = "The member or function 'instType' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way." } + { Error = Warning 3569 + Range = { StartLine = 21 + StartColumn = 27 + EndLine = 21 + EndColumn = 35 } + Message = + "The member or function 'instType' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way." } ] [] @@ -1769,3 +1769,72 @@ module M = |> withLangVersion80 |> compile |> shouldSucceed + + [] + let ``Warn successfully in Array-mapped recursive call`` () = + """ +namespace N + +module M = + + type Value = + { Code: string } + + [] + let rec fooArray (values: Value[], code: string) = + match values with + | [||] -> seq { code } + | values -> + let replicatedValues = + values + |> Array.map (fun value -> fooArray (values, value.Code)) + replicatedValues |> Seq.concat + """ + |> FSharp + |> withLangVersion80 + |> compile + |> shouldFail + |> withResults [ + { Error = Warning 3569 + Range = { StartLine = 16 + StartColumn = 20 + EndLine = 16 + EndColumn = 74 } + Message = + "The member or function 'fooArray' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way." } + ] + + [] + let ``Warn successfully in Seq-mapped recursive call`` () = + """ +namespace N + +module M = + + type Value = + { Code: string } + + [] + let rec fooSeq (values: Value[], code: string) = + match values with + | [||] -> seq { code } + | values -> + let replicatedValues = + values + |> Seq.map (fun value -> fooSeq (values, value.Code)) + |> Seq.toArray + replicatedValues |> Seq.concat + """ + |> FSharp + |> withLangVersion80 + |> compile + |> shouldFail + |> withResults [ + { Error = Warning 3569 + Range = { StartLine = 16 + StartColumn = 42 + EndLine = 16 + EndColumn = 48 } + Message = + "The member or function 'fooSeq' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way." } + ]