question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Codegen Regression - `function` within recursive function results in null reference exception

See original GitHub issue

Using function within a recursive function iterating over a list results in a null reference exception when matching against the empty list [].

Repro steps

A sample repo has been made: https://github.com/StachuDotNet/function-rec-fsharp-dotnet7-bug-demo/blob/main/Program.fs

let list = [1; 2; 3]
let condition n = n < 3

let dropWhileWithMatch condition list =
  let rec f (l : List<int>) : List<int> =
    match l with
    | [] -> []
    | head :: tail ->
      match condition head with
      | true -> f tail
      | false -> head :: tail

  f list

let dropWhileWithFunction condition list =
  let rec f : List<int> -> List<int> =
    function
    | [] -> []
    | head :: tail ->
      match condition head with
      | true -> f tail
      | false -> head :: tail

  f list


// this runs fine:
let matchResult = dropWhileWithMatch condition list
printfn "Match: %A" matchResult


// and this results in a null reference exception
let functionResult = dropWhileWithFunction condition list
printfn "Function: %A" functionResult
(*
  Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
   at Program.f@14-1.Invoke(FSharpList`1 _arg1) in /workspaces/function-rec-fsharp-dotnet7-bug-demo/Program.fs:line 18
   at Program.dropWhileWithFunction(FSharpFunc`2 condition, FSharpList`1 list) in /workspaces/function-rec-fsharp-dotnet7-bug-demo/Program.fs:line 21
   at <StartupCode$function-rec-fsharp-dotnet7-bug-demo>.$Program.main@() in /workspaces/function-rec-fsharp-dotnet7-bug-demo/Program.fs:line 29
*)

The sample repo includes a devcontainer set up for simple testing - just dotnet run.

Related information

Provide any related information (optional):

  • Ubuntu 21.10
  • .NET SDK 7.0.100-preview.3.22179.4

I suspect this issue will be eventually closed in favor of a runtime issue, but know too little to report there appropriately.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:9 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
KevinRansomcommented, Apr 28, 2022

@vzarytovskii , we probably need to evaluate the debugging experience more deeply, before we do that. This change, makes no difference in the debugging as far as I can tell.

1reaction
En3Thocommented, Apr 27, 2022

I’m able to reproduce it on 6.0.300-preview.22154.4 too. There is an IL diff between stable and preview versions: stable (6.0.104) : both functions have effectively identical il https://www.diffchecker.com/Av9sdqwx

preview: IL of “function” is very different. It is on the left.

It seems that compiler is now trying to make “f” an object instead of function.

So it tries to get “f” from field which is somehow null and fails on “f tail” call. You can check that by printfn ReferenceEquals(f, null) before the call. Funnily, removing type annotation from “let rec f : List<int> -> List<int>” to just “let rec f” fixes an issue.

Side note: I wonder why compiler doesn’t emit a warning when rec function results in closure instead of a while loop. I would really like to see a warning. Some things are really better expressed as rec’s but it’s always a manual check that assures, not compiler.

https://www.diffchecker.com/eAcGUo5B

Oh, @vzarytovskii was faster than me 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Null Reference Exception in Recursive Function
Use a function expression that references values that are defined recursively. Before we jump to examples, I suggest changing the definition ...
Read more >
Changelog | Burst | 1.2.3 - Unity User Manual 2021.3 (LTS)
Fix possible NullReferenceException when an entry point function is calling another empty function. Fix an exception occurring while ...
Read more >
Changelog | Burst | 1.3.9
Fixed a subtle codegen bug that could occur when the target is an Arm or AArch64 CPU ... Fix possible NullReferenceException when an...
Read more >
Code Generation for Recursive Functions - MATLAB & ...
Use recursive functions in MATLAB code that is intended for code generation.
Read more >
Recursion in Java
We'll explain the characteristics of a recursive function and show how to use recursion for solving various problems in Java.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found