Skip to content

False negative with TailCall attribute #18365

@BoundedChenn31

Description

@BoundedChenn31

Repro steps

Consider the following code (the simplest example I could craft, don't expect anything sane):

type Value =
    { Code: string }

[<TailCall>]
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

fooArray isn't called in tail recursive manner, however compiler does not issue a warning.

Curiously, after rewrite to Seq functions compiler does issue Warning FS3569 : The member or function 'fooSeq' has the 'TailCallAttribute' attribute, but is not being used in a tail recursive way.

[<TailCall>]
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

Looking at decompiled code of assembly I would guess that compiler tries to optimise Array.map and TailCall analyser mistakes the result for tail-recursive function.

Expected behavior

Warning is issued for first code example.

Actual behavior

No warning.

Known workarounds

.

Related information

Provide any related information (optional):
.NET SDK 9.0.200

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-Compiler-OptimizationThe F# optimizer, release code gen etc.BugImpact-Low(Internal MS Team use only) Describes an issue with limited impact on existing code.

    Type

    Projects

    Status

    New

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions