I'm having trouble adding elements to an object that keeps a collection of generic-typed values. I tried a Minimal Working Example that causes the error:
class OneElementQueue {
type eltType;
var elements : [0..0] eltType;
//initializer
proc init(type eltType) {
this.eltType = eltType;
}
proc add(element : eltType) {
this.elements[0] = element;
}
proc remove() : eltType {
return this.elements[0];
}
} //end of OneElementQueue
class Monkey {
var name: string;
var age: int;
proc init(name : string, age : int) {
this.name = name;
this.age = age;
}
} //end of class Monkey
var q = new owned OneElementQueue(Monkey);
var m = new owned Monkey("Kyle", 6);
q.add(m);
When I try to compile all of this, I get an error:
$ chpl BadQueue.chpl
BadQueue.chpl:12: In function 'add':
BadQueue.chpl:13: error: Scoped variable would outlive the value it is set to
BadQueue.chpl:12: note: consider scope of element
$
What is the correct way to go about adding something to a generic data structure like this? How am I going about this the wrong way?
There are two possible approaches you can take here, depending on what behavior you want:
"I want to have my collection take ownership of the Monkey objects"
In this case, you'll want to instantiate your OneElementQueue
collection to store owned Monkey
objects rather than simply [borrowed] Monkey
objects, which is the default for class types. You can do this with the one line change (Try it Online):
var q = new owned OneElementQueue(owned Monkey);
In this approach, passing an owned Monkey
to your add()
method will pass the ownership to the argument and eventually to the collection, making the original object reference invalid (nil
).
"I want to have my collection borrow the existing Monkey objects without taking ownership of them"
In this case, you'll need to tell the add()
method that the argument passed into it will outlive the argument itself (and then be sure not to lie about it). In Chapel version 1.19, this can be done via lifetime annotations:
proc add(element : eltType) lifetime element > this {
where the annotation lifetime element > this
asserts that the actual argument passed through element
will outlive the this
collection itself, so the compiler should not fear that the borrow will cease to exist once the formal argument has.
Lifetime annotations were not available in Chapel 1.18, so if you're using that version you need to use a slightly bigger hammer and apply pragma "unsafe"
to the method. Note that pragmas are not an officially supported feature and may change in the future, so for this case, served as a stopgap until lifetime annotations had been implemented (Try it Online):
pragma "unsafe"
proc add(element : eltType) {