[Chapel Merge] Dyno: const ref field access, aliasing arrays

Branch: refs/heads/main
Revision: b861ebb6e93f47e2c54e16ea5756651ef913cb18
Author: DanilaFe
Link: Dyno: const ref field access, aliasing arrays by DanilaFe · Pull Request #27228 · chapel-lang/chapel · GitHub
Log Message:
Dyno: const ref field access, aliasing arrays (#27228)

Closes https://github.com/Cray/chapel-private/issues/7333. There's no
issue for const field accessors, but this would close that too.

The original program I set out to make work was this:

proc helper(ref data) {
  data[5] = 10;
}

proc test() {
  var A : [1..10] int;
  helper(A[1..5]);
}
test();

The curiosity here is that ref data accepts a mutable reference, and
we are passing it a slice. Normally, a value produced by an expression
cannot be passed to a mutable reference, since it's a temporary.
However, slices produce values that alias other arrays. Although they
are values, they can be used for non-const references.

The fact that the result of slicing A is const for const A and
non-const for non-const A seemed similar to how field access works
(fields are refs if the receiver is mutable, const refs if it's not). In
looking for how we handle the latter in Dyno, I noticed that we don't.
Thus, prior to this PR, the following program causes no problems.

record R { var x: int; }
const r: R;
ref myX = r.x;

Thus, I set out to handle both things (field access and slicing). In
production, the latter is implemented via pragma "reference to const when const this". However, such adjustments -- which depend on the
constness of the receiver actual type -- happen separately from
computing the return type a function (which, once it's been
instantiated, does not depend on the actuals at all). This, in turn,
meant that they would need to be done separately from returnType,
returnTypes, and yieldType queries. I was concerned about this,
because we call returnType a lot, and having to adjust each call site
was difficult in some cases, and impossible in others.

Thus, I made the following changes:

  • Switched PromotionIteratorType to contain its yield type, determined
    at the time where a promoted call is detected. This is needed anyway
    since one could promote a "reference to const when const this"
    function, and thus, a typed signature alone does not uniquely determine
    the yielded type of a PromotionIteratorType.
  • For the same reason, changes FnIteratorType to contain its yield
    type.
  • Avoids re-running returnType when handling return intent
    overloading. As a comment there points out, the only thing that needs to
    change is the intent of the result type; we can infer that from the
    chosen overload.

This leaves very few places where returnType and friends are used. The
only place that then requires changes for handling constness is in
"mainline" call resolution code. This PR adjusts that, including checks
for field constnesss and "reference to const when const this".

This, however, was not sufficient to get the slices primer to resolve.
It seems like we have special const checking exceptions for when the
type being returned is an aliasing array. This PR adjusts the return
intent inference logic to detect aliasing arrays -- and aliasing arrays
only -- and mark them as non-const.

Reviewed by @benharsh -- thanks!

Testing

  • dyno tests
  • release/examples/spec (no change)
  • release/examples/primers (-1 failure, slices is now passing)
  • paratest

Compare: Comparing a45af4e5eb4dd23fc23839d3598fa85ac985a919...7f7453f64448ed3a871ebf474a613d8d503543e8 · chapel-lang/chapel · GitHub

Diff:
M frontend/include/chpl/resolution/resolution-queries.h
M frontend/include/chpl/types/ArrayType.h
M frontend/include/chpl/types/FnIteratorType.h
M frontend/include/chpl/types/PromotionIteratorType.h
M frontend/lib/resolution/Resolver.cpp
M frontend/lib/resolution/disambiguation.cpp
M frontend/lib/resolution/maybe-const.cpp
M frontend/lib/resolution/resolution-queries.cpp
M frontend/lib/resolution/return-type-inference.cpp
M frontend/lib/types/ArrayType.cpp
M frontend/lib/types/FnIteratorType.cpp
M frontend/lib/types/PromotionIteratorType.cpp
https://github.com/chapel-lang/chapel/pull/27228.diff