20437, "vasslitvinov", "moveFrom, moveInitialize: the compiler needs to be aware", "2022-08-12T07:02:49Z"
These functions are also discussed in #20330 and #20328.
The charter of the Memory.Initialization
module is "[to enable the user] to implement collections in a manner similar to those implemented by the Chapel standard modules (such as List or Map)."
I claim that at present the functions moveFrom
and moveInitialize
do not achieve this purpose.
Example 1: LinkedList.pop_front()
I expect pop_front() to pass to the caller the ownership of the element being popped:
var oldFront = ... the front listNode ...;
var ret = moveFrom(oldFront.data);
delete oldFront;
return ret;
However, it does not -- and cannot do that. Because delete oldFront
deinitializes oldFront.data
among other things - because it does not know that oldFront.data
has been "consumed". So if I called moveFrom(oldFront.data)
, the deinitializer would deinitialize invalid memory contents.
Example 2: chpl__hashtable.clearSlot()
I expect the out val
formal to take over the ownership of tableEntry.val
:
proc chpl__hashtable.clearSlot(ref tableEntry, out key: keyType, out val: valType) {
moveInitialize(key, moveFrom(tableEntry.key));
moveInitialize(val, moveFrom(tableEntry.val));
....
}
However, it does not do that. If it did, the compiler would not know that key
and value
would be initialized and would default-initialize them prior to the moveInitialize() calls. So moveInitialize() would clobber objects without deinitializing them properly. Instead, key
and value
get initialized using =
:
proc chpl__hashtable.clearSlot(ref tableEntry, out key: keyType, out val: valType) {
key = moveFrom(tableEntry.key);
val = moveFrom(tableEntry.val);
....
}
The problem with that is that the compiler inserts calls to chpl__coerceMove(), passing in the results of moveFrom
and using the returned values to initialize key
/value
. chpl__coerceMove() is a Really Big Function and is completely unnecessary here.
In summary, this issue calls for compiler awareness of initialization and deinitialization performed by moveFrom
and moveInitialize
.