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 aPromotionIteratorType
. - 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
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