chapel-lang/chapel — pull request #1024 by vasslitvinov (2014-12-17 22:58:56+00:00)
Title: Fixed an issue in handleCaptureArgs()

Consider this code:

proc test(ref tArg: int) {
begin {
... tArg ...
}
}

When it is being resolved, the AST looks like this:

proc test(ref tArg: _ref(int)) {
call begin_fn(tArg);
}

proc begin_fn( bArg) {
.... bArg ... // it is still called 'tArg' in AST
// I will call it 'bArg' to disambiguate
}

handleCaptureArgs() is invoked when processing call begin_fn(tArg)
right before resolving begin_fn() - it copies the type of each actual
to the corresponding formal.

To ensure that the value of tArg is "captured" by begin_fn,
rather than passing tArg by reference into begin_fn,
handleCaptureArgs() recognizes that the actual is of a _ref type,
so it removes _ref of the formal, bArg here, and generates
an explicit dereference in the caller - see replaceActualWithDeref()
(added in ade9b83 aka r22008):

proc test(ref tArg: _ref(int)) {
DefExpr derefTmp: int;
derefTmp = deref(tArg);
call begin_fn(derefTmp);
}

proc begin_fn( bArg: int) {
.... bArg ...
}

This gets the job done. However, it will break when:

* the user specifies "ref tArg" in the begin's 'with' clause:

proc test(ref tArg: int) {
begin with (ref tArg) {
...

* I implement the user's 'ref' intent as a 'ref' argument of begin_fn:

proc begin_fn(ref bArg) ...

// This latter is not an issue today, however it is in my way of extending
// task intents. I consider this to be a poor code organization issue
// and would like to fix separately. Read on...

In which case the AST will look like:

proc test(ref tArg: _ref(int)) {
DefExpr derefTmp: int;
derefTmp = deref(tArg);
call begin_fn(derefTmp);
}

proc begin_fn(ref bArg: _ref(int)) {
.... bArg ...
}

which captures the value of tArg, then passes that capture by reference.

// Today there is no bArg at all - the body of begin_fn references
// 'tArg' directly at this point during compilation.

This commit fixes this design as follows, for the case where
the actual is of a _ref type:

* Compute the concrete intent of the corresponding formal of begin_fn
assuming it is of the corresponding value type.

* (a) If the concrete intent is one of reference intents,
revert the formal's type to be the actual's _ref type.

* (b) Otherwise, keep the value type of the formal.

The dereference is not inserted in either case,
allowing me to delete replaceActualWithDeref().
Instead when (b) it will be inserted later, elsewhere in the compiler.