Skip to content

Mutually recursive computation expression raises NullReferenceException under some conditions #3783

@aqtq314

Description

@aqtq314

Given the following function definition,

let x () =
    let rec a = seq {
        yield 0
        yield! b () }
    and b () = seq {
        yield 1
        yield! a }
    do Seq.take 10 a |> Seq.iter (printfn "%d")

Invoking x () will print a 0 then raises NullReferenceException. Putting the function body into a type constructor generates a similar behavior when creating an instance of it:

type A () =
    do  let rec a = seq {
            yield 0
            yield! b () }
        and b () = seq {
            yield 1
            yield! a }
        do Seq.take 10 a |> Seq.iter (printfn "%d")

One of the workarounds would be inlining the do-binding in the above type definition, like below:

type A () =
    let rec a = seq {
        yield 0
        yield! b () }
    and b () = seq {
        yield 1
        yield! a }
    do Seq.take 10 a |> Seq.iter (printfn "%d")

Another workaround is to modify a so that it becomes a function that takes in a parameter:

type A () =
    do  let rec a () = seq {
// ...

Environment:

  • VS2017
  • .NET Framework 4.5 or upper
  • FSharp.Core 4.4.0 or upper

This doesn't happen in VS2015 or on www.ideone.com.

Metadata

Metadata

Assignees

Labels

Area-Compiler-StateMachinesSequence, list, task and other state machine compilationBugImpact-Medium(Internal MS Team use only) Describes an issue with moderate impact on existing code.

Type

Projects

Status

In Progress

Relationships

None yet

Development

No branches or pull requests

Issue actions