I am trying to create a ByRefLike struct Context which contains multiple ByRefLike structs. When there is only a single field, the program works. When there are more than 1, the program throws an InvalidProgramException.
Why does it throw an error and is it possible to overcome it?
open System
open System.Runtime.CompilerServices
open FSharp.NativeInterop
#nowarn "9" // Pointers are cool
let inline stackalloc<'a when 'a: unmanaged> (length: int): Span<'a> =
let p = NativePtr.stackalloc<'a> length |> NativePtr.toVoidPtr
Span<'a>(p, length)
[<Struct; IsByRefLike>]
type StackStack<'T>(values: Span<'T>) =
[<DefaultValue>] val mutable private _count : int
member s.Push v =
if s._count < values.Length then
values[s._count] <- v
s._count <- s._count + 1
else
failwith "Exceeded capacity of StackStack"
member s.Pop () =
if s._count > 0 then
s._count <- s._count - 1
values[s._count]
else
failwith "Empty StackStack"
member s.Count = s._count
module StackStack =
let inline create capacity =
let values = stackalloc<_> capacity
StackStack values
[<Struct; IsByRefLike>]
type Context =
{
mutable Stack1 : StackStack<int>
// If you comment out the line below, the program will run just fine
mutable Stack2 : StackStack<int>
// Other fields go here
}
module Context =
let inline create capacity =
{
Stack1 = StackStack.create capacity
// If you comment out the line below, the program will run just fine
Stack2 = StackStack.create capacity
}
let test () =
printfn "State"
let mutable c = Context.create 10
c.Stack1.Push 1
c.Stack1.Push 2
c.Stack1.Push 3
while c.Stack1.Count > 0 do
let next = c.Stack1.Pop()
printfn $"NextValue: {next}"
test ()