I have a question on StackOverflow that hasn't been answered so I decided to post here.
The example below is actually further simplified from the one in the question. When re-assigning a value of an algebraic data type to a generic field, if the type of the variant that was assigned changes, it crashes.
So in the example below, the variant goes from an object with a single float32 field to a string.
type
RefPar*[U] = ref object of RootObj
curr*: U
type
BasicNumber = object of RootObj
value: float32
RefChild* = ref object of RefPar[TokenObject]
Token* {.pure.} = enum
foo,
bar,
TokenObject = object
case kind*: Token
of Token.foo:
foo*: string
of Token.bar:
bar*: BasicNumber
var t = RefChild()
t.curr = TokenObject(kind: Token.bar, bar: BasicNumber(value: 12.34))
t.curr = TokenObject(kind: Token.foo, foo: "foo")
echo "SUCCESS"
Here's the error message. Slightly different from the one in the SO question, but overall the same.
Traceback (most recent call last) test_nim.nim(23) test_nim assign.nim(99) genericShallowAssign assign.nim(85) genericAssignAux assign.nim(35) genericAssignAux assign.nim(21) genericAssignAux assign.nim(52) genericAssignAux gc.nim(269) unsureAsgnRef gc.nim(208) decRef gc.nim(121) canbeCycleRoot SIGSEGV: Illegal storage access. (Attempt to read from nil?)
I assume this is a bug, but would like for someone to let me know if I'm simply doing something wrong or in a way that isn't intended to be done.
The issue exists in both the current version 10.2 as well as the branch for the 10.3 build.
Thank you!
EDIT: Here are two notes that I added to the bottom of the SO question:
Note that if I change the bar field to use a float32 directly instead of the BasicNumber type, it succeeds. But the code above is a simplification, and I do need an object.
Another note: If I make BasicNumber a ref, the problem goes away. That'll be an acceptable workaround for me, but I'm still curious about the issue.
Shouldn't t be initialised with new proc?
var t : RefChild
t.new()
@yglukhov:
Thanks for the reply. I'm new to Nim, but RefChild is already a ref object type, so I think that would make a ref to a ref.
In any case, this is a simplification of a larger application and the initialization works in the rest of the app. It's just this issue.
Araq:
Ah that's good to know. I figured it must be but needed a confirmation. Now I feel more confident in continuing with my workaround until there's a fix.
Thank you!