Search code examples
object-lifetimechapel

Chapel : Understanding lifetime of managed classes with zip and user-defined iterators


I'm trying to understand the lifetime of an owned class, when being used in a user-defined iterator. Consider the following code :

var a = new owned C();
var b = new owned C();
a.i = 2;

forall (a1,b1) in zip(a,b) {
  b1 = a1;
}

forall (a1,b1) in zip(a,b) {
  writeln(a1, " ",b1);
}

class C {
  var i : int;
  iter these() {
    yield 1;
  }

  iter these(param tag : iterKind) where tag==iterKind.leader {
    yield 1;
  }

  iter these(param tag : iterKind, followThis) ref
  where tag==iterKind.follower {
    yield i;
  }
}

Compiling and running this code gives the following error

(08:54)$ chpl test.chpl --warn-unstable
(08:54)$ ./test
test.chpl:25: error: attempt to dereference nil
(08:54)$ chpl --version
chpl version 1.19.0 pre-release (2c10dbe)

It isn't clear to me when the class is being deinit-ed here. If I replace the owned with a shared, this example works as expected. More interestingly, changing the first loop to

forall (a1,b1) in zip(a.borrow(),b.borrow()) {

allows the code to work as well. In what cases is an argument automatically coerced into a borrowed instance?


Solution

  • I'm pretty sure this is a bug. I'll have a look.

    In what cases is an argument automatically coerced into a borrowed instance?

    Right now, when:

    1. when calling a method on it (the this argument will be a borrow)
    2. when passing to an argument of type C or borrowed C (which mean the same).
    3. when passing to a totally generic function argument.

    I'm not sure if we're going to keep rule 3 or not. But that's not the problem in your case - rather the problem is that some compiler-introduced code implementing the forall statement taking away the owned value. That's a bug.