Why does Nim need to call =destroy on an enum field kind, when I set a.kind to SomeEnumValue ? Is there a way to tell the compiler to not call =destroy in this case?
result.kind = kind
{
if (!!(((*result).kind == colontmpD_))) goto LA4_;
eqdestroy___OOZgeneZtypes_u16418((&(*result).kind));
if (NIM_UNLIKELY(*nimErr_)) goto BeforeRet_;
}
I think there is no bug here. eqdestroy___enum95destroy_u88((&(*t__enum95destroy_u12).kind)); doesn't destroy the enum field. It's a hacky way the destroy the old object variant (It uses the address of the start of the object variant)
N_LIB_PRIVATE N_NIMCALL(void, eqdestroy___test5053_u78)(tyEnum_TestKind__64TS1K9bhOpdtj62mFh9au2g *dest_p0)
{
tyObject_TestcolonObjectType___Q7ioB54z2AzFX9c67jm5Yhg *dest_2;
dest_2 = ((tyObject_TestcolonObjectType___Q7ioB54z2AzFX9c67jm5Yhg *)((NI)(((NI)(ptrdiff_t)(dest_p0)) - ((NI)0))));
switch ((*dest_2).kind)
{
case ((tyEnum_TestKind__64TS1K9bhOpdtj62mFh9au2g)0):
{
if ((*dest_2)._kind_1.a.p && !((*dest_2)._kind_1.a.p->cap & NIM_STRLIT_FLAG))
{
deallocShared((*dest_2)._kind_1.a.p);
}
(*dest_2)._kind_1.a.len = 0;
(*dest_2)._kind_1.a.p = NIM_NIL;
}
break;
case ((tyEnum_TestKind__64TS1K9bhOpdtj62mFh9au2g)1):
{
(*dest_2)._kind_2.b = 0;
}
break;
default:
__builtin_unreachable();
}
(*dest_2).kind = 0;
}
It's necessary to destroy the old one for correctness.Thank you! That makes sense.
A related question is how do I initialize the kind field in a newly-allocated memory, without triggering the destroy? I couldn't find a way to set memory directly. Here is code from my project. Please correct me if I am doing something wrong.
type
TestKind* = enum
tkA
tkB
Test* = object
case kind*: TestKind
of tkA:
a*: int
of tkB:
b*: string
var t = cast[ptr Test](alloc0(sizeof(Test)))
{.cast(uncheckedAssign).}:
t.kind = tkA # Is there another way of doing this?
You should be able to do
var myVariant = Object(kind: ...)
let newKind = YourNewKind
copyMem(myVariant.kind.addr, newKind.addr, sizeof(YourKindType))