fsharp
fsharp copied to clipboard
NullReferenceException with Debug build and recursive reference
I'm using dotnet 8.0.101 with Windows 10. The program below, when run in Debug mode, will throw a NullReferenceException. If run in Release mode, it completes successfully. Both versions generate a warning about the reference to parse
in paramParse
(in Type.parse
) needing a runtime check; I believe it is that reference to parse
which is null in the Debug build.
type Ident = string
type Type =
| TPrim of Ident
| TParam of Ident * Type
let tryParam pv x =
match x with
| TParam (name, typ) ->
pv typ |> Result.map (fun t -> [name, t])
| _ -> Error "unexpected"
let tryPrim = function
| TPrim name -> Ok name
| _ -> Error "unused"
module Type =
let parse =
let rec paramParse = tryParam parse
and parse node =
match tryPrim node with
| Ok name -> Ok(TPrim name)
| _ ->
match paramParse node with
| Ok [name, typ] -> Ok(TParam(name,typ))
| _ -> Error "invalid type"
parse
[<EntryPoint>]
let main args =
printfn "%A" (Type.parse (TParam ("ptr", TPrim "float")))
0
The workaround is to reorder parse
and paramParse
; this gets rid of the warning and allows both Debug and Release to succeed. E.g.:
module Type =
let parse =
let rec parse node =
match tryPrim node with
| Ok name -> Ok(TPrim name)
| _ ->
match paramParse node with
| Ok [name, typ] -> Ok(TParam(name,typ))
| _ -> Error "invalid type"
and paramParse = tryParam parse
parse
You can also follow the advice in the error message and make parseParam
a recursive function instead of a recursive object: let rec paramParse n = tryParam parse n
.
The code then runs in both debug and release configuration, and you don't get the warning.