Chapel: Array views and in intent

Created on 31 Jul 2020  路  4Comments  路  Source: chapel-lang/chapel

What should the following program do?

proc run() {
  var A:[1..10] int;

  foo(A[1..3]); // accepts argument with `in` and sets element 1
  writeln("after foo, A[1] is ", A[1]); // is A[1] still 0?
}

proc foo(in A) {
  writeln("in foo, chpl__isArrayView(A) is ", chpl__isArrayView(A));
  writeln("in foo, A[1] is ", A[1]);
  writeln("in foo, setting A[1] = 1");
  A[1] = 1;
}

run();

In 1.16, it had the probably desired behavior described later (at the end A[1] is 0).
In 1.17 / 1.18 / 1.19 / 1.20, it gives C code compilation errors
In 1.21 / 1.22, this program core dumps

After that, as of 2ef4ab70de397a162ec68dbb50398bab608f45f3, it prints out

in foo, chpl__isArrayView(A) is true
in foo, A[1] is 0
in foo, setting A[1] = 1
after foo, A[1] is 1

Since in intent passing is similar to variable initialization, I would expect the in intent to copy the array view into a non-view array and as a result to print this:

in foo, chpl__isArrayView(A) is false
in foo, A[1] is 0
in foo, setting A[1] = 1
after foo, A[1] is 0
Language Bug Design

Most helpful comment

My understanding of the in intent is that it makes "copy-in" of the actual argument (according to the docs page). If so, I think the code would behave equally as first making var Asub = A[1..3]; on the caller side and then passing Asub with the ref intent to foo(). Because var Asub = A[1..3]; makes a copy of the array value (rather than making a reference or making a copy of the "array descriptor"), I would also expect that foo( in A ) does not affect the original A on the caller side...

On the other hand, if foo() has the ref intent and is given an actual argument A[1..3], then I would expect foo() will receive an array view and the original A (on the caller side) to be modified.

All 4 comments

Here is a related example with tuples that appears to work the way I would expect:

var A:[1..10] int;

proc run() {
  var A:[1..10] int;

  foo( (A,A) );
  writeln("after foo, A[1] is ", A[1]);
}

proc foo(in tup) {
  writeln("in foo, tup(0)[1] is ", tup(0)[1]);
  writeln("in foo, tup(1)[1] is ", tup(1)[1]);
  writeln("in foo, setting A[1] = 1");
  tup(0)[1] = 1;
  writeln("in foo, tup(1)[1] is ", tup(1)[1]);
}

run();

My understanding of the in intent is that it makes "copy-in" of the actual argument (according to the docs page). If so, I think the code would behave equally as first making var Asub = A[1..3]; on the caller side and then passing Asub with the ref intent to foo(). Because var Asub = A[1..3]; makes a copy of the array value (rather than making a reference or making a copy of the "array descriptor"), I would also expect that foo( in A ) does not affect the original A on the caller side...

On the other hand, if foo() has the ref intent and is given an actual argument A[1..3], then I would expect foo() will receive an array view and the original A (on the caller side) to be modified.

@ty1027 beat me to it, but the final output in the OP is what I would expect as the output as well.

16195 asks a related question about A.domain

Was this page helpful?
0 / 5 - 0 ratings