I've reduced it to a reproducible snippet of code:
funcdef void Callback();
class Object {
Callback @cb = null;
Object(Callback @cb = null) {
@this.cb = cb;
}
};
class List {
array<Object@> @objects = {
@Object(),
@Object(),
@Object()
};
};
void init() {
message("init()");
auto @list = List();
auto len = list.objects.length();
for (uint i = 0; i < len; i++) {
auto @s = list.objects[i];
if (s is null) {
message("[" + fmtInt(i) + "] = NULL");
continue;
}
message("[" + fmtInt(i) + "] = not null");
}
}
(I have the host define `void message(const string &in)` and `string fmtInt(int)`)
The issue stems from having the last constructor parameter as optional and set to a default value of `null` combined with eliding the last parameter in the constructor invocations in the initializer list.
This case causes the last instance to be null (aka incorrect unexpected buggy behavior):
array<Object@> @objects = {
@Object(null),
@Object(),
@Object()
};
However, this case causes the last instance to NOT be null (aka correct expected behavior):
array<Object@> @objects = {
@Object(null),
@Object(null),
@Object()
};
This case also causes the last instance to NOT be null (aka correct expected behavior):
array<Object@> @objects = {
@Object(null),
@Object(null),
@Object(null)
};
While reducing the test case, my Object constructor had 3 parameters before the optional 4th parameter and the buggy behavior was still present. Only the last constructor parameter being declared optional affects the outcome.