New Issue: Behavior difference between generic and concrete 'in' intents with domain literal actuals

16398, “e-kayrakli”, “Behavior difference between generic and concrete ‘in’ intents with domain literal actuals”, “2020-09-15T23:29:16Z”

Consider the following code:

proc foo(in d) {
  writeln(d);
}

proc bar(in d: domain(1, int, false)) {
  writeln(d);
}

var myDom: domain(1);

foo(myDom);
bar(myDom);

foo({1..10});
bar({1..10});

Should we copy

Currently we copy myDom while calling foo and `bar:

  call_tmp_chpl31 = chpl__buildDomainRuntimeType(&defaultDist_chpl);
  _runtime_type_tmp__chpl2 = (&call_tmp_chpl31)->dist;
  chpl__convertRuntimeTypeToValue(&_runtime_type_tmp__chpl2, UINT8(false), &ret_tmp_chpl);
  myDom_chpl = ret_tmp_chpl;
  _formal_tmp_in_r_chpl = chpl__initCopy(&myDom_chpl, UINT8(false));
  foo_chpl(&_formal_tmp_in_r_chpl);  // we pass the copy here

  _formal_type_tmp_chpl = chpl__buildDomainRuntimeType(&defaultDist_chpl);
  chpl__coerceCopy(&_formal_type_tmp_chpl, &myDom_chpl, UINT8(false), &ret_tmp_chpl2);
  _formal_tmp_in_r_chpl2 = ret_tmp_chpl2;
  bar_chpl(&_formal_tmp_in_r_chpl2);  // we pass the copy here

However the behavior is different while passing a domain literal:

  chpl_build_bounded_range(INT64(1), INT64(10), &ret_tmp_chpl3);
  call_tmp_chpl32 = ret_tmp_chpl3;
  chpl__buildDomainExpr(call_tmp_chpl32, UINT8(false), &ret_tmp_chpl4);
  call_tmp_chpl33 = ret_tmp_chpl4;
  foo_chpl(&call_tmp_chpl33);  // we pass the domain in this scope

  chpl_build_bounded_range(INT64(1), INT64(10), &ret_tmp_chpl5);
  call_tmp_chpl34 = ret_tmp_chpl5;
  chpl__buildDomainExpr(call_tmp_chpl34, UINT8(false), &ret_tmp_chpl6);
  call_tmp_chpl35 = ret_tmp_chpl6;
  _formal_type_tmp_chpl2 = chpl__buildDomainRuntimeType(&defaultDist_chpl);
  chpl__coerceMove(&_formal_type_tmp_chpl2, &call_tmp_chpl35, UINT8(false), &ret_tmp_chpl7);
  _formal_tmp_in_r_chpl3 = ret_tmp_chpl7;
  bar_chpl(&_formal_tmp_in_r_chpl3);  // we pass the copy here

We may be doing some copy elision, because it is a literal in the calling scope,
so there is no need to create its copy. However, the behavior changes if the
argument is generic vs not.

I am not entirely sure whether this causes a problem on master, but it’ll after
https://github.com/chapel-lang/chapel/pull/16397. Because a domain literal
is constant by definition, and an in argument isn’t. So if we are supposed to
elide the copy for the domain literal (1) we have to do that for the generic
case, too, (2) adjust the formal’s definedConst field in the function body.