28201, "jabraham17", "[Bug]: list.toArray only works on default initializable types", "2025-12-12T23:56:23Z"
I am finding that list.toArray only works for default initializable types. Other collection.toArray like set.toArray likely have the same problem.
use List;
record R1 {
var x: int;
proc init(x: int) {
this.x = x;
}
}
record R2 {
var x: int;
proc init(x: int) {
this.x = x;
}
proc init() {
this.x = -1;
}
}
record R3 {
var arr: [1..10] int;
proc init(x: int) {
this.arr = x;
}
}
proc testList(type R) {
var l = new list(R);
var empty = l.toArray();
writeln("empty: ", empty);
l.pushBack(new R(1));
l.pushBack(new R(2));
l.pushBack(new R(3));
var arr = l.toArray();
writeln("arr: ", arr);
}
With testList(R1)
$CHPL_HOME/modules/standard/List.chpl:1894: In method 'toArray':
$CHPL_HOME/modules/standard/List.chpl:1903: error: unresolved call 'R1.init()'
test/library/standard/List/toArray/nonDefaultConstruct.chpl:5: note: this candidate did not match: R1.init(x: int)
$CHPL_HOME/modules/internal/ChapelBase.chpl:1547: note: because call does not supply enough arguments
nonDefaultConstruct.chpl:5: note: it is missing a value for formal 'x: int(64)'
nonDefaultConstruct.chpl:28: called as (list(R1,false)).toArray() from function 'testList'
nonDefaultConstruct.chpl:39: called as testList(type R = R1)
note: generic instantiations are underlined in the above callstack
testList(R2) works fine because it is default initializable
The actual body of toArray looks something like this
proc toArray() {
var result: [0..#size] eltType;
on this {
var tmp: [0..#_size] eltType = forall i in 0..#_size do _getRef(i);
result = tmp;
}
return result;
}
Its written this way, since you cannot return from inside an on statement. However, since eltType may not be default initializable, var result cannot be created.
One solution is to use var result: [0..#size] eltType = noinit;. This works great for simple cases like R1, but not R3.
With testList(R3) and adding noinit
$CHPL_HOME/modules/standard/List.chpl:1894: In method 'toArray':
$CHPL_HOME/modules/standard/List.chpl:1903: error: noinit is only supported for arrays of trivially copyable types
nonDefaultConstruct.chpl:28: called as (list(R3,false)).toArray() from function 'testList'
nonDefaultConstruct.chpl:41: called as testList(type R = R3)
note: generic instantiations are underlined in the above callstack
Another solution is to use pragma "no init", which at least compiles. But this is too big of a hammer, and prevents the array metadata from being allocated and crashes at runtime.
The workaround for this issue to use .these() instead of .toArray(), which is not as efficient but at least compiles and works.