-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
When I generate a type in a template, everything works fine, but when I use the exact same template to generate another type and use that type, this type will disappear in the generated C code, and the generated C code will use the wrong type instead. Here is an example.
template foobar(arg: typed): untyped =
type
MyType = object
member: type(arg)
var myVar: MyType
myVar.member = arg
echo myVar
foobar("hello world")
foobar(123.456'f64)This is the relevant generated C code:
// there is only one instance of MyType
struct tyObject_MyType_c8zLdw0BfP5QV35I5Dp9cLQ {
NimStringDesc* member;
};
// an instance of MyType with a member of type double does not exist.
/*...*/
// as you can see both myVar instances have the same type
tyObject_MyType_c8zLdw0BfP5QV35I5Dp9cLQ myVar_JAYCzYxe9bQSb28Ss2x9aoxg;
tyObject_MyType_c8zLdw0BfP5QV35I5Dp9cLQ myVar_JAYCzYxe9bQSb28Ss2x9aoxg_2;
/*...*/
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
NimStringDesc* T1_;
tyArray_nHXaesL0DJZHyVS07ARPRA T2_;
tyArray_nHXaesL0DJZHyVS07ARPRA T3_;
nimRegisterGlobalMarker(TM_X9bGGOoNyKehOTF7f2xys3g_2);
T1_ = (NimStringDesc*)0;
T1_ = myVar_JAYCzYxe9bQSb28Ss2x9aoxg.member; myVar_JAYCzYxe9bQSb28Ss2x9aoxg.member = copyStringRC1(((NimStringDesc*) &TM_X9bGGOoNyKehOTF7f2xys3g_3));
if (T1_) nimGCunrefNoCycle(T1_);
memset((void*)T2_, 0, sizeof(tyArray_nHXaesL0DJZHyVS07ARPRA));
T2_[0] = dollar__cL9bBANF2jNLmbCKCDXwjDQ(myVar_JAYCzYxe9bQSb28Ss2x9aoxg);
echoBinSafe(T2_, 1);
// here is the line that won't compile
myVar_JAYCzYxe9bQSb28Ss2x9aoxg_2.member = 1.2345600000000000e+02;
memset((void*)T3_, 0, sizeof(tyArray_nHXaesL0DJZHyVS07ARPRA));
T3_[0] = dollar__cL9bBANF2jNLmbCKCDXwjDQ_2(myVar_JAYCzYxe9bQSb28Ss2x9aoxg_2);
echoBinSafe(T3_, 1);
}The C compiler will refuse to compile with this error message:
/tmp/nimcache/scratch.c:269:42: error: incompatible types when assigning to type 'NimStringDesc * {aka struct NimStringDesc *}' from type 'double'
myVar_JAYCzYxe9bQSb28Ss2x9aoxg_2.member = 1.2345600000000000e+02;
Because of weak type checking in C compiling integers will silently work, so foobar(123) will compile just fine. But when the generated instance of MyType has a member of an integer type, casting pointers to it will actually work, but it will cause a segfault at runtime, when the integer is too small to hold an actual pointer value.
Interesting though, there are two different $ procedures generated for the same type. You can see them in use in the generated code as dollar__cL9bBANF2jNLmbCKCDXwjDQ and dollar__cL9bBANF2jNLmbCKCDXwjDQ_2