From ed26b1bd5e69d5391713ada3431a07e7b0f9e836 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Mon, 10 Aug 2026 14:43:06 -0700 Subject: [PATCH 01/11] add more tests for array return types Signed-off-by: Jade Abraham --- test/arrays/return/returnArbitraryArray.chpl | 12 ++++++++++ test/arrays/return/returnArbitraryArray.good | 3 +++ .../return/returnArbitraryBadDomain2.chpl | 8 +++++++ .../return/returnArbitraryBadDomain2.good | 1 + .../return/returnArbitraryBadDomain2.skipif | 1 + .../return/returnArbitraryBadEltType2.chpl | 8 +++++++ .../return/returnArbitraryBadEltType2.good | 3 +++ .../return/returnArbitraryBadEltType3.chpl | 8 +++++++ .../return/returnArbitraryBadEltType3.good | 3 +++ .../returnArbitraryMultipleReturns.chpl | 12 ++++++++++ .../returnArbitraryMultipleReturns.good | 2 ++ .../return/returnArbitraryMultipleTypes.chpl | 18 +++++++++++++++ .../return/returnArbitraryMultipleTypes.good | 2 ++ test/arrays/return/returnWithEffects.chpl | 23 +++++++++++++++++++ test/arrays/return/returnWithEffects.good | 14 +++++++++++ 15 files changed, 118 insertions(+) create mode 100644 test/arrays/return/returnArbitraryBadDomain2.chpl create mode 100644 test/arrays/return/returnArbitraryBadDomain2.good create mode 100644 test/arrays/return/returnArbitraryBadDomain2.skipif create mode 100644 test/arrays/return/returnArbitraryBadEltType2.chpl create mode 100644 test/arrays/return/returnArbitraryBadEltType2.good create mode 100644 test/arrays/return/returnArbitraryBadEltType3.chpl create mode 100644 test/arrays/return/returnArbitraryBadEltType3.good create mode 100644 test/arrays/return/returnWithEffects.chpl create mode 100644 test/arrays/return/returnWithEffects.good diff --git a/test/arrays/return/returnArbitraryArray.chpl b/test/arrays/return/returnArbitraryArray.chpl index 14a6f0b7e679..254149356548 100644 --- a/test/arrays/return/returnArbitraryArray.chpl +++ b/test/arrays/return/returnArbitraryArray.chpl @@ -1,8 +1,20 @@ proc inc(X: [] real): [] real { return X + 1; } +proc incByTuple(X: [] real): (real, [] real) { + return (X[1], X + 1); +} +proc incByTuple2(X: [] real): ([] real, ([] real, [] real)) { + return (X + 1, (X + 2, X + 3)); +} +proc incByTuple3(X: [] real): (real, ([] real, [] real), [] real) { + return (X[1], (X + 2, X + 3), X + 4); +} var A = [1.0, 2.0, 3.0]; writeln(inc(A)); +writeln(incByTuple(A)); +writeln(incByTuple2(A)); +writeln(incByTuple3(A)); writeln(A); diff --git a/test/arrays/return/returnArbitraryArray.good b/test/arrays/return/returnArbitraryArray.good index 60f11a193df3..2837f5ebc1b4 100644 --- a/test/arrays/return/returnArbitraryArray.good +++ b/test/arrays/return/returnArbitraryArray.good @@ -1,2 +1,5 @@ 2.0 3.0 4.0 +(2.0, 2.0 3.0 4.0) +(2.0 3.0 4.0, (3.0 4.0 5.0, 4.0 5.0 6.0)) +(2.0, (3.0 4.0 5.0, 4.0 5.0 6.0), 5.0 6.0 7.0) 1.0 2.0 3.0 diff --git a/test/arrays/return/returnArbitraryBadDomain2.chpl b/test/arrays/return/returnArbitraryBadDomain2.chpl new file mode 100644 index 000000000000..b1c5cffbdd47 --- /dev/null +++ b/test/arrays/return/returnArbitraryBadDomain2.chpl @@ -0,0 +1,8 @@ +proc inc(X: [0..4] int): (int, (int, [1..6] int)) { + return (X[0], (X[0], X + 3)); +} + +var A = [1, 2, 3, 4, 5]; + +writeln(inc(A)); +writeln(A); diff --git a/test/arrays/return/returnArbitraryBadDomain2.good b/test/arrays/return/returnArbitraryBadDomain2.good new file mode 100644 index 000000000000..e4f19080cf74 --- /dev/null +++ b/test/arrays/return/returnArbitraryBadDomain2.good @@ -0,0 +1 @@ +returnArbitraryBadDomain.chpl:2: error: halt reached - domain mismatch on return diff --git a/test/arrays/return/returnArbitraryBadDomain2.skipif b/test/arrays/return/returnArbitraryBadDomain2.skipif new file mode 100644 index 000000000000..7d0abe186052 --- /dev/null +++ b/test/arrays/return/returnArbitraryBadDomain2.skipif @@ -0,0 +1 @@ +COMPOPTS <= --fast diff --git a/test/arrays/return/returnArbitraryBadEltType2.chpl b/test/arrays/return/returnArbitraryBadEltType2.chpl new file mode 100644 index 000000000000..d98e646b3edb --- /dev/null +++ b/test/arrays/return/returnArbitraryBadEltType2.chpl @@ -0,0 +1,8 @@ +proc inc(X: [] real): ([] int, [] int) { + return (X + 1, X + 2); +} + +var A = [1.0, 2.0, 3.0]; + +writeln(inc(A)); +writeln(A); diff --git a/test/arrays/return/returnArbitraryBadEltType2.good b/test/arrays/return/returnArbitraryBadEltType2.good new file mode 100644 index 000000000000..fbc36a8537b3 --- /dev/null +++ b/test/arrays/return/returnArbitraryBadEltType2.good @@ -0,0 +1,3 @@ +returnArbitraryBadEltType2.chpl:1: In function 'inc': +returnArbitraryBadEltType2.chpl:2: error: array element type mismatch in return from real(64) to int(64) + returnArbitraryBadEltType2.chpl:7: called as inc(X: [domain(1,int(64),one)] real(64)) diff --git a/test/arrays/return/returnArbitraryBadEltType3.chpl b/test/arrays/return/returnArbitraryBadEltType3.chpl new file mode 100644 index 000000000000..d87a1bdf7ab4 --- /dev/null +++ b/test/arrays/return/returnArbitraryBadEltType3.chpl @@ -0,0 +1,8 @@ +proc inc(X: [] real): ([] real, ([] int, int)) { + return (X + 1, (X + 2, 3)); +} + +var A = [1.0, 2.0, 3.0]; + +writeln(inc(A)); +writeln(A); diff --git a/test/arrays/return/returnArbitraryBadEltType3.good b/test/arrays/return/returnArbitraryBadEltType3.good new file mode 100644 index 000000000000..bc8ba07e79b6 --- /dev/null +++ b/test/arrays/return/returnArbitraryBadEltType3.good @@ -0,0 +1,3 @@ +returnArbitraryBadEltType3.chpl:1: In function 'inc': +returnArbitraryBadEltType3.chpl:2: error: array element type mismatch in return from real(64) to int(64) + returnArbitraryBadEltType3.chpl:7: called as inc(X: [domain(1,int(64),one)] real(64)) diff --git a/test/arrays/return/returnArbitraryMultipleReturns.chpl b/test/arrays/return/returnArbitraryMultipleReturns.chpl index 9fcb27fab178..cb5e78ac6cfb 100644 --- a/test/arrays/return/returnArbitraryMultipleReturns.chpl +++ b/test/arrays/return/returnArbitraryMultipleReturns.chpl @@ -8,9 +8,21 @@ proc inc(X: [] real, two: bool): [] real { } } +proc incByTuple(X: [] real, two: bool): ([] real, ([] real, [] real)) { + if (two) { + var ret = X + 2; + return (ret, (ret + 3, X + 4)); + } else { + var ret = X + 1; + return (ret, (X + 2, ret + 3)); + } +} + var A = [1.0, 2.0, 3.0]; writeln(inc(A, false)); +writeln(incByTuple(A, false)); writeln(A); writeln(inc(A, true)); +writeln(incByTuple(A, true)); writeln(A); diff --git a/test/arrays/return/returnArbitraryMultipleReturns.good b/test/arrays/return/returnArbitraryMultipleReturns.good index e95552c94fa0..012a6f523bed 100644 --- a/test/arrays/return/returnArbitraryMultipleReturns.good +++ b/test/arrays/return/returnArbitraryMultipleReturns.good @@ -1,4 +1,6 @@ 2.0 3.0 4.0 +(2.0 3.0 4.0, (3.0 4.0 5.0, 5.0 6.0 7.0)) 1.0 2.0 3.0 3.0 4.0 5.0 +(3.0 4.0 5.0, (6.0 7.0 8.0, 5.0 6.0 7.0)) 1.0 2.0 3.0 diff --git a/test/arrays/return/returnArbitraryMultipleTypes.chpl b/test/arrays/return/returnArbitraryMultipleTypes.chpl index e4082848edf8..6215e86e5143 100644 --- a/test/arrays/return/returnArbitraryMultipleTypes.chpl +++ b/test/arrays/return/returnArbitraryMultipleTypes.chpl @@ -2,8 +2,26 @@ proc gimme(type t): [] { var x: [1..5] t; return x; } +proc gimme2(type t, type t2): ([], []) { + var x: [1..5] t; + var y: [1..5] t2; + return (x, y); +} +proc gimme3(type t, type t2, type t3, type t4): ([], [], ([], [])) { + var x: [1..5] t; + var y: [1..5] t2; + var z: [1..5] t3; + var w: [1..5] t4; + return (x, y, (z, w)); +} + var myReals = gimme(real); var myInts = gimme(int); writeln(myReals); writeln(myInts); + +var myRealsAndInts = gimme2(real, int); +writeln(myRealsAndInts); +var manyRealsAndInts = gimme3(real, int, real, int); +writeln(manyRealsAndInts); diff --git a/test/arrays/return/returnArbitraryMultipleTypes.good b/test/arrays/return/returnArbitraryMultipleTypes.good index b0ddc59a9a24..27e4ed02e6a7 100644 --- a/test/arrays/return/returnArbitraryMultipleTypes.good +++ b/test/arrays/return/returnArbitraryMultipleTypes.good @@ -1,2 +1,4 @@ 0.0 0.0 0.0 0.0 0.0 0 0 0 0 0 +(0.0 0.0 0.0 0.0 0.0, 0 0 0 0 0) +(0.0 0.0 0.0 0.0 0.0, 0 0 0 0 0, (0.0 0.0 0.0 0.0 0.0, 0 0 0 0 0)) diff --git a/test/arrays/return/returnWithEffects.chpl b/test/arrays/return/returnWithEffects.chpl new file mode 100644 index 000000000000..029d57185a66 --- /dev/null +++ b/test/arrays/return/returnWithEffects.chpl @@ -0,0 +1,23 @@ +proc sideeffect(type t, n) { + writeln("side effect ", n, " for ", t:string); + return [i in 1..10] i:t; +} + +proc basic(type t): [] t { + return sideeffect(t, 1); +} +proc nested(type t): ([] t, [] t) { + return (sideeffect(t, 1), sideeffect(t, 2)); +} +proc superNested(type t): (([] t, [] t), [] t) { + return ((sideeffect(t, 1), sideeffect(t, 2)), sideeffect(t, 3)); +} +proc superNested2(type t): ([] t, ([] t, [] t), [] t) { + return (sideeffect(t, 1), (sideeffect(t, 2), sideeffect(t, 3)), sideeffect(t, 4)); +} + + +writeln(basic(int)); +writeln(nested(int)); +writeln(superNested(real)); +writeln(superNested2(int(32))); diff --git a/test/arrays/return/returnWithEffects.good b/test/arrays/return/returnWithEffects.good new file mode 100644 index 000000000000..4c8b615199a7 --- /dev/null +++ b/test/arrays/return/returnWithEffects.good @@ -0,0 +1,14 @@ +side effect 1 for int(64) +1 2 3 4 5 6 7 8 9 10 +side effect 1 for int(64) +side effect 2 for int(64) +(1 2 3 4 5 6 7 8 9 10, 1 2 3 4 5 6 7 8 9 10) +side effect 1 for real(64) +side effect 2 for real(64) +side effect 3 for real(64) +((1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0, 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0), 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0) +side effect 1 for int(32) +side effect 2 for int(32) +side effect 3 for int(32) +side effect 4 for int(32) +(1 2 3 4 5 6 7 8 9 10, (1 2 3 4 5 6 7 8 9 10, 1 2 3 4 5 6 7 8 9 10), 1 2 3 4 5 6 7 8 9 10) From ff2e6431d4f96a5df648692cd4322f9cb273c0f2 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Mon, 10 Aug 2026 14:43:34 -0700 Subject: [PATCH 02/11] initial fix for an explicit array return type within a tuple Signed-off-by: Jade Abraham --- compiler/passes/normalize.cpp | 126 ++++++++++++++++++++++++++++++---- 1 file changed, 111 insertions(+), 15 deletions(-) diff --git a/compiler/passes/normalize.cpp b/compiler/passes/normalize.cpp index 1ec12458089f..3cf941f50f83 100644 --- a/compiler/passes/normalize.cpp +++ b/compiler/passes/normalize.cpp @@ -71,6 +71,7 @@ static bool isArrayFormal(ArgSymbol* arg); static Expr* arrayTypeEltTypeExprOrNull(Expr* expr); static bool returnsArray(FnSymbol* fn); +static bool returnsArrayOrTupleOfArrays(FnSymbol* fn); static void makeExportWrapper(FnSymbol* fn); static void fixupArrayFormals(FnSymbol* fn); @@ -2202,26 +2203,42 @@ static bool isVoidReturn(CallExpr* call) { return retval; } -static bool hasGenericArrayReturn(FnSymbol* fn) { - if (returnsArray(fn)) { - BlockStmt* typeExpr = fn->retExprType; - - // returnsArray ensured this was a call to "chpl__buildArrayRuntimeType" - CallExpr* call = toCallExpr(typeExpr->body.tail); - int nArgs = call->numActuals(); - Expr* domExpr = call->get(1); - Expr* eltExpr = nArgs == 2 ? call->get(2) : NULL; - bool noDom = (isSymExpr(domExpr) && toSymExpr(domExpr)->symbol() == gNil); +static bool isGenericArray(CallExpr* call) { + if (!call->isNamed("chpl__buildArrayRuntimeType")) return false; - if (noDom || eltExpr == NULL) { - // Either the domain is not provided explicitly as part of the return - // type, or the element type is not provided, or both + int nArgs = call->numActuals(); + Expr* domExpr = call->get(1); + Expr* eltExpr = nArgs == 2 ? call->get(2) : nullptr; + bool noDom = (isSymExpr(domExpr) && toSymExpr(domExpr)->symbol() == gNil); - return true; + // Either the domain is not provided explicitly as part of the return + // type, or the element type is not provided, or both + return noDom || eltExpr == nullptr; +} +static bool containsGenericArray(CallExpr* call) { + if (call->isNamed("_build_tuple")) { + for_actuals(arg, call) { + if (CallExpr* argCall = toCallExpr(arg)) { + if (containsGenericArray(argCall)) + return true; + } } + return false; + } else { + return isGenericArray(call); } +} + +static bool hasGenericArrayReturn(FnSymbol* fn) { + if (!returnsArrayOrTupleOfArrays(fn)) return false; + BlockStmt* typeExpr = fn->retExprType; + + // returnsArrayOrTupleOfArrays ensured this was a call to + // "chpl__buildArrayRuntimeType" or a call to "_build_tuple" with + // "chpl__buildArrayRuntimeType" as an argument + CallExpr* call = toCallExpr(typeExpr->body.tail); + return containsGenericArray(call); - return false; } // @@ -2265,11 +2282,75 @@ static void insertElementTypeCheck(Expr* declaredRet, Expr* actualRet, retVar->insertBefore(checkEltType); } +static void modifyPartiallyGenericArrayReturnSimple(FnSymbol* fn, + VarSymbol* retval, + CallExpr* ret, + Expr* retExpr); static void modifyPartiallyGenericArrayReturn(FnSymbol* fn, VarSymbol* retval, CallExpr* ret, Expr* retExpr) { BlockStmt* typeExpr = fn->retExprType; + if (toCallExpr(typeExpr->body.tail)->isNamed("chpl__buildArrayRuntimeType")) { + modifyPartiallyGenericArrayReturnSimple(fn, retval, ret, retExpr); + return; + } + + // pair(typeExpr, retExpr) + std::stack> calls; + calls.push(std::make_pair(toCallExpr(typeExpr->body.tail), toCallExpr(retExpr))); + while(calls.size() > 0) { + auto call = calls.top(); + calls.pop(); + auto typeCall = toCallExpr(call.first); + auto myRetExpr = call.second; + auto retCall = toCallExpr(myRetExpr); + if (typeCall && typeCall->isNamed("_build_tuple")) { + if (!(retCall && retCall->isNamed("_build_tuple"))) { + USR_FATAL(fn, "return type is a tuple, but return value is not"); + } + int nTypeArgs = typeCall->numActuals(); + int nRetArgs = retCall->numActuals(); + if (nTypeArgs != nRetArgs) { + USR_FATAL(fn, "return type is a tuple of size %d, but return value is a tuple of size %d", nTypeArgs, nRetArgs); + } + for (int i = 1; i <= nTypeArgs; i++) { + Expr* typeArg = typeCall->get(i); + Expr* retArg = retCall->get(i); + calls.push(std::make_pair(typeArg, retArg)); + } + } else if (typeCall && isGenericArray(typeCall)) { + int nArgs = typeCall->numActuals(); + Expr* domExpr = typeCall->get(1); + Expr* retEltExpr = nArgs == 2 ? typeCall->get(2) : nullptr; + bool noDom = (isSymExpr(domExpr) && toSymExpr(domExpr)->symbol() == gNil); + + if (!noDom) { + // TODO: prepareRetExpr + // prepareRetExpr(retExpr, ret); + // Add checks against the declared domain + insertDomainCheck(myRetExpr, ret, domExpr); + } + + if (retEltExpr != nullptr) { + // TODO: prepareRetExpr + // prepareRetExpr(retExpr, ret); + insertElementTypeCheck(retEltExpr, myRetExpr, ret); + } + } + } + // TODO: Do something about coercion + ret->insertBefore(new CallExpr(PRIM_MOVE, retval, retExpr)); +} + + + + +static void modifyPartiallyGenericArrayReturnSimple(FnSymbol* fn, + VarSymbol* retval, + CallExpr* ret, + Expr* retExpr) { + BlockStmt* typeExpr = fn->retExprType; CallExpr* call = toCallExpr(typeExpr->body.tail); int nArgs = call->numActuals(); @@ -3916,6 +3997,21 @@ static bool returnsArray(FnSymbol* fn) { // If we don't have a declared return type, assume we don't return an array return false; } +static bool isTupleOrArray(CallExpr* call) { + if (!call) return false; + if (call->isNamed("chpl__buildArrayRuntimeType")) + return true; + else if (call->isNamed("_build_tuple")) + for_actuals(actual, call) { + if (isTupleOrArray(toCallExpr(actual))) + return true; + } + return false; +} +static bool returnsArrayOrTupleOfArrays(FnSymbol* fn) { + return fn->retExprType != NULL && + isTupleOrArray(toCallExpr(fn->retExprType->body.tail)); +} /************************************* | ************************************** From 18d313fcbdf12f611056ffb2719564c60d0c0920 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Mon, 10 Aug 2026 14:57:47 -0700 Subject: [PATCH 03/11] more test cases Signed-off-by: Jade Abraham --- .../return/returnArbitraryMultiDiffRank.chpl | 13 +++++++++++++ .../return/returnArbitraryMultiDiffRank.good | 10 ++++++++++ .../return/returnArbitraryMultiDiffType.chpl | 13 +++++++++++++ .../return/returnArbitraryMultiDiffType.good | 2 ++ .../return/returnArbitraryMultiplePromotion.chpl | 11 +++++++++++ .../return/returnArbitraryMultiplePromotion.good | 4 ++++ test/arrays/return/returnFullyAnon.chpl | 16 ++++++++++++++++ test/arrays/return/returnFullyAnon.good | 3 +++ 8 files changed, 72 insertions(+) create mode 100644 test/arrays/return/returnFullyAnon.chpl create mode 100644 test/arrays/return/returnFullyAnon.good diff --git a/test/arrays/return/returnArbitraryMultiDiffRank.chpl b/test/arrays/return/returnArbitraryMultiDiffRank.chpl index 28c3da061d13..39166cbfc11c 100644 --- a/test/arrays/return/returnArbitraryMultiDiffRank.chpl +++ b/test/arrays/return/returnArbitraryMultiDiffRank.chpl @@ -7,8 +7,21 @@ proc foo(type t, param fiveInts: bool): [] { return x; } } +proc bar(type t, param fiveInts: bool): ([], [], ([], [])) { + if (fiveInts) { + var x: [1..5] int; + return (x, x, (x, x)); + } else { + var x: [1..3, 1..4] t; + return (x, x, (x, x)); + } +} var a = foo(real, true); var b = foo(real, false); writeln(a); writeln(b); +var c = bar(real, true); +var d = bar(real, false); +writeln(c); +writeln(d); diff --git a/test/arrays/return/returnArbitraryMultiDiffRank.good b/test/arrays/return/returnArbitraryMultiDiffRank.good index 9cc0f5088718..41a6d50dd0b7 100644 --- a/test/arrays/return/returnArbitraryMultiDiffRank.good +++ b/test/arrays/return/returnArbitraryMultiDiffRank.good @@ -2,3 +2,13 @@ 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +(0 0 0 0 0, 0 0 0 0 0, (0 0 0 0 0, 0 0 0 0 0)) +(0.0 0.0 0.0 0.0 +0.0 0.0 0.0 0.0 +0.0 0.0 0.0 0.0, 0.0 0.0 0.0 0.0 +0.0 0.0 0.0 0.0 +0.0 0.0 0.0 0.0, (0.0 0.0 0.0 0.0 +0.0 0.0 0.0 0.0 +0.0 0.0 0.0 0.0, 0.0 0.0 0.0 0.0 +0.0 0.0 0.0 0.0 +0.0 0.0 0.0 0.0)) diff --git a/test/arrays/return/returnArbitraryMultiDiffType.chpl b/test/arrays/return/returnArbitraryMultiDiffType.chpl index fe4aa3db9bb7..ab408da4cca0 100644 --- a/test/arrays/return/returnArbitraryMultiDiffType.chpl +++ b/test/arrays/return/returnArbitraryMultiDiffType.chpl @@ -7,8 +7,21 @@ proc foo(type t, param fiveInts: bool): [] { return x; } } +proc bar(type t, param fiveInts: bool): ([], ([], []), []) { + if (fiveInts) { + var x: [1..5] int; + return (x, (x, x), x); + } else { + var x: [1..3] t; + return (x, (x, x), x); + } +} var a = foo(real, true); var b = foo(real, false); writeln(a); writeln(b); +var c = bar(real, true); +var d = bar(real, false); +writeln(c); +writeln(d); diff --git a/test/arrays/return/returnArbitraryMultiDiffType.good b/test/arrays/return/returnArbitraryMultiDiffType.good index 810ac43accc4..1fd0b808df33 100644 --- a/test/arrays/return/returnArbitraryMultiDiffType.good +++ b/test/arrays/return/returnArbitraryMultiDiffType.good @@ -1,2 +1,4 @@ 0 0 0 0 0 0.0 0.0 0.0 +(0 0 0 0 0, (0 0 0 0 0, 0 0 0 0 0), 0 0 0 0 0) +(0.0 0.0 0.0, (0.0 0.0 0.0, 0.0 0.0 0.0), 0.0 0.0 0.0) diff --git a/test/arrays/return/returnArbitraryMultiplePromotion.chpl b/test/arrays/return/returnArbitraryMultiplePromotion.chpl index 3db6f7745ddb..356b885168a1 100644 --- a/test/arrays/return/returnArbitraryMultiplePromotion.chpl +++ b/test/arrays/return/returnArbitraryMultiplePromotion.chpl @@ -5,6 +5,13 @@ proc inc(X: [] real, two: bool): [] real { return X + 1; } } +proc inc2(X: [] real, two: bool): ([] real, ([] real, [] real)) { + if (two) { + return (X + 2, (X + 3, X + 4)); + } else { + return (X + 1, (X + 2, X + 3)); + } +} var A = [1.0, 2.0, 3.0]; @@ -12,3 +19,7 @@ writeln(inc(A, false)); writeln(A); writeln(inc(A, true)); writeln(A); +writeln(inc2(A, false)); +writeln(A); +writeln(inc2(A, true)); +writeln(A); diff --git a/test/arrays/return/returnArbitraryMultiplePromotion.good b/test/arrays/return/returnArbitraryMultiplePromotion.good index e95552c94fa0..35ffc7ac5974 100644 --- a/test/arrays/return/returnArbitraryMultiplePromotion.good +++ b/test/arrays/return/returnArbitraryMultiplePromotion.good @@ -2,3 +2,7 @@ 1.0 2.0 3.0 3.0 4.0 5.0 1.0 2.0 3.0 +(2.0 3.0 4.0, (3.0 4.0 5.0, 4.0 5.0 6.0)) +1.0 2.0 3.0 +(3.0 4.0 5.0, (4.0 5.0 6.0, 5.0 6.0 7.0)) +1.0 2.0 3.0 diff --git a/test/arrays/return/returnFullyAnon.chpl b/test/arrays/return/returnFullyAnon.chpl new file mode 100644 index 000000000000..7e5913f0e403 --- /dev/null +++ b/test/arrays/return/returnFullyAnon.chpl @@ -0,0 +1,16 @@ +proc foo(a): [] { + return a; +} +proc bar(a, b): ([], []) { + return (a, b); +} +proc baz(const a, const b, const c): ([], ([], [])) { + return (a, (b, c)); +} + +var A = [1, 2, 3]; +writeln(foo(A)); +var B = [4, 5, 6]; +writeln(bar(A, B)); +var C = [7.0, 8.0, 9.0, 10.0]; +writeln(baz(A, B, C)); diff --git a/test/arrays/return/returnFullyAnon.good b/test/arrays/return/returnFullyAnon.good new file mode 100644 index 000000000000..d56e77919017 --- /dev/null +++ b/test/arrays/return/returnFullyAnon.good @@ -0,0 +1,3 @@ +1 2 3 +(1 2 3, 4 5 6) +(1 2 3, (4 5 6, 7.0 8.0 9.0 10.0)) From 6a740e2c8752ca8119932453b4508a1f0e75dc0c Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Mon, 10 Aug 2026 16:20:49 -0700 Subject: [PATCH 04/11] fix errors Signed-off-by: Jade Abraham --- modules/internal/ChapelArray.chpl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/internal/ChapelArray.chpl b/modules/internal/ChapelArray.chpl index e66a53645b77..7a9044b210c1 100644 --- a/modules/internal/ChapelArray.chpl +++ b/modules/internal/ChapelArray.chpl @@ -648,6 +648,11 @@ module ChapelArray { b: string); } } + pragma "last resort" + proc chpl__checkRetEltTypeMatch(a, type b) { + compilerError("expected an array or iterator but got a value of type ", + a.type:string); + } proc chpl__checkOutEltTypeMatch(a: [], type b) { if (a.eltType != b) { compilerError("array element type mismatch in initializing out formal ", From b98f1de60978417a9ec21e84cc363af5d2cdf411 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Mon, 10 Aug 2026 16:21:03 -0700 Subject: [PATCH 05/11] more test cases Signed-off-by: Jade Abraham --- test/arrays/return/returnMismatchedArrayTuple.chpl | 5 +++++ test/arrays/return/returnMismatchedArrayTuple.good | 1 + test/arrays/return/returnMismatchedArrayTuple2.chpl | 6 ++++++ test/arrays/return/returnMismatchedArrayTuple2.good | 1 + test/arrays/return/returnNonArray.chpl | 5 +++++ test/arrays/return/returnNonArray.good | 1 + test/arrays/return/returnUnexpectedArray.chpl | 5 +++++ test/arrays/return/returnUnexpectedArray.good | 2 ++ 8 files changed, 26 insertions(+) create mode 100644 test/arrays/return/returnMismatchedArrayTuple.chpl create mode 100644 test/arrays/return/returnMismatchedArrayTuple.good create mode 100644 test/arrays/return/returnMismatchedArrayTuple2.chpl create mode 100644 test/arrays/return/returnMismatchedArrayTuple2.good create mode 100644 test/arrays/return/returnNonArray.chpl create mode 100644 test/arrays/return/returnNonArray.good create mode 100644 test/arrays/return/returnUnexpectedArray.chpl create mode 100644 test/arrays/return/returnUnexpectedArray.good diff --git a/test/arrays/return/returnMismatchedArrayTuple.chpl b/test/arrays/return/returnMismatchedArrayTuple.chpl new file mode 100644 index 000000000000..eb97f8a86d9d --- /dev/null +++ b/test/arrays/return/returnMismatchedArrayTuple.chpl @@ -0,0 +1,5 @@ +proc doit(): ([] int, int, [] int) { + var A = [1, 2, 3]; + return (A, 3); +} +writeln(doit()); diff --git a/test/arrays/return/returnMismatchedArrayTuple.good b/test/arrays/return/returnMismatchedArrayTuple.good new file mode 100644 index 000000000000..741f7a1ceb14 --- /dev/null +++ b/test/arrays/return/returnMismatchedArrayTuple.good @@ -0,0 +1 @@ +returnMismatchedArrayTuple.chpl:1: error: return type is a tuple of size 3, but return value is a tuple of size 2 diff --git a/test/arrays/return/returnMismatchedArrayTuple2.chpl b/test/arrays/return/returnMismatchedArrayTuple2.chpl new file mode 100644 index 000000000000..94d7fdbe4941 --- /dev/null +++ b/test/arrays/return/returnMismatchedArrayTuple2.chpl @@ -0,0 +1,6 @@ +proc doit(): ([] int, int) { + var A = [1, 2, 3]; + return (A, 3, A); +} + +writeln(doit()); diff --git a/test/arrays/return/returnMismatchedArrayTuple2.good b/test/arrays/return/returnMismatchedArrayTuple2.good new file mode 100644 index 000000000000..0c86bdcd8569 --- /dev/null +++ b/test/arrays/return/returnMismatchedArrayTuple2.good @@ -0,0 +1 @@ +returnMismatchedArrayTuple2.chpl:1: error: return type is a tuple of size 2, but return value is a tuple of size 3 diff --git a/test/arrays/return/returnNonArray.chpl b/test/arrays/return/returnNonArray.chpl new file mode 100644 index 000000000000..adcca5f0541e --- /dev/null +++ b/test/arrays/return/returnNonArray.chpl @@ -0,0 +1,5 @@ +proc doit(): ([] int, int) { + return (2, 3); +} + +writeln(doit()); diff --git a/test/arrays/return/returnNonArray.good b/test/arrays/return/returnNonArray.good new file mode 100644 index 000000000000..7232c875214b --- /dev/null +++ b/test/arrays/return/returnNonArray.good @@ -0,0 +1 @@ +returnNonArray.chpl:1: error: return type is a tuple, but return value is not diff --git a/test/arrays/return/returnUnexpectedArray.chpl b/test/arrays/return/returnUnexpectedArray.chpl new file mode 100644 index 000000000000..2badfbcf9c96 --- /dev/null +++ b/test/arrays/return/returnUnexpectedArray.chpl @@ -0,0 +1,5 @@ +proc doit(): (int, int) { + var A = [1, 2, 3]; + return (A, 3); +} +writeln(doit()); diff --git a/test/arrays/return/returnUnexpectedArray.good b/test/arrays/return/returnUnexpectedArray.good new file mode 100644 index 000000000000..7f88db2c8494 --- /dev/null +++ b/test/arrays/return/returnUnexpectedArray.good @@ -0,0 +1,2 @@ +returnUnexpectedArray.chpl:1: In function 'doit': +returnUnexpectedArray.chpl:3: error: cannot initialize return value of type '2*int(64)' from a '([domain(1,int(64),one)] int(64),int(64))' From 6d3db1df5aec22611fd46c56ed8cfdd6e2bfed38 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Mon, 10 Aug 2026 16:24:13 -0700 Subject: [PATCH 06/11] attempt to fix side effect issue Signed-off-by: Jade Abraham --- compiler/passes/normalize.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/compiler/passes/normalize.cpp b/compiler/passes/normalize.cpp index 3cf941f50f83..919334d544fe 100644 --- a/compiler/passes/normalize.cpp +++ b/compiler/passes/normalize.cpp @@ -2296,6 +2296,14 @@ static void modifyPartiallyGenericArrayReturn(FnSymbol* fn, return; } + // // at this point, its a pretty good assumption that the return type is a + // // tuple that contains one or more generic arrays + // // to prevent side-effects, we need to insert call temps for the return + // // expression before we start + // // we do this for the entire call expression up front, and then insert checks + // // for each of the generic arrays in the tuple + // prepareRetExpr(retExpr, ret); + // pair(typeExpr, retExpr) std::stack> calls; calls.push(std::make_pair(toCallExpr(typeExpr->body.tail), toCallExpr(retExpr))); @@ -2324,17 +2332,14 @@ static void modifyPartiallyGenericArrayReturn(FnSymbol* fn, Expr* domExpr = typeCall->get(1); Expr* retEltExpr = nArgs == 2 ? typeCall->get(2) : nullptr; bool noDom = (isSymExpr(domExpr) && toSymExpr(domExpr)->symbol() == gNil); - + if (!noDom || retEltExpr != nullptr) { + prepareRetExpr(myRetExpr, ret); + } if (!noDom) { - // TODO: prepareRetExpr - // prepareRetExpr(retExpr, ret); // Add checks against the declared domain insertDomainCheck(myRetExpr, ret, domExpr); } - if (retEltExpr != nullptr) { - // TODO: prepareRetExpr - // prepareRetExpr(retExpr, ret); insertElementTypeCheck(retEltExpr, myRetExpr, ret); } } @@ -2358,14 +2363,14 @@ static void modifyPartiallyGenericArrayReturnSimple(FnSymbol* fn, Expr* retEltExpr = nArgs == 2 ? call->get(2) : NULL; bool noDom = (isSymExpr(domExpr) && toSymExpr(domExpr)->symbol() == gNil); - if (!noDom) { + if (!noDom || retEltExpr != nullptr) { prepareRetExpr(retExpr, ret); + } + if (!noDom) { // Add checks against the declared domain insertDomainCheck(retExpr, ret, domExpr); } - if (retEltExpr != NULL) { - prepareRetExpr(retExpr, ret); insertElementTypeCheck(retEltExpr, retExpr, ret); } From 352a99a0a512df0f30fd9546f447672abf054e10 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Mon, 10 Aug 2026 16:32:01 -0700 Subject: [PATCH 07/11] more test cases Signed-off-by: Jade Abraham --- test/arrays/return/returnNonArray2.chpl | 5 +++++ test/arrays/return/returnNonArray2.good | 2 ++ test/arrays/return/returnNonArray3.chpl | 5 +++++ test/arrays/return/returnNonArray3.good | 3 +++ test/arrays/return/returnNonArray4.chpl | 5 +++++ test/arrays/return/returnNonArray4.good | 0 test/arrays/return/returnNonArray5.chpl | 5 +++++ test/arrays/return/returnNonArray5.good | 0 test/arrays/return/returnUnexpectedArray2.chpl | 5 +++++ test/arrays/return/returnUnexpectedArray2.good | 2 ++ 10 files changed, 32 insertions(+) create mode 100644 test/arrays/return/returnNonArray2.chpl create mode 100644 test/arrays/return/returnNonArray2.good create mode 100644 test/arrays/return/returnNonArray3.chpl create mode 100644 test/arrays/return/returnNonArray3.good create mode 100644 test/arrays/return/returnNonArray4.chpl create mode 100644 test/arrays/return/returnNonArray4.good create mode 100644 test/arrays/return/returnNonArray5.chpl create mode 100644 test/arrays/return/returnNonArray5.good create mode 100644 test/arrays/return/returnUnexpectedArray2.chpl create mode 100644 test/arrays/return/returnUnexpectedArray2.good diff --git a/test/arrays/return/returnNonArray2.chpl b/test/arrays/return/returnNonArray2.chpl new file mode 100644 index 000000000000..a6f6aa5e012f --- /dev/null +++ b/test/arrays/return/returnNonArray2.chpl @@ -0,0 +1,5 @@ +proc doit(): [] int { + return 2; +} + +writeln(doit()); diff --git a/test/arrays/return/returnNonArray2.good b/test/arrays/return/returnNonArray2.good new file mode 100644 index 000000000000..ec1e0119704a --- /dev/null +++ b/test/arrays/return/returnNonArray2.good @@ -0,0 +1,2 @@ +returnNonArray2.chpl:1: In function 'doit': +returnNonArray2.chpl:2: error: expected an array or iterator but got a value of type int(64) diff --git a/test/arrays/return/returnNonArray3.chpl b/test/arrays/return/returnNonArray3.chpl new file mode 100644 index 000000000000..b92d4c20b6e4 --- /dev/null +++ b/test/arrays/return/returnNonArray3.chpl @@ -0,0 +1,5 @@ +proc doit(D): [D] { + return 2; +} + +writeln(doit({1..10})); diff --git a/test/arrays/return/returnNonArray3.good b/test/arrays/return/returnNonArray3.good new file mode 100644 index 000000000000..6007f7b9eaef --- /dev/null +++ b/test/arrays/return/returnNonArray3.good @@ -0,0 +1,3 @@ +returnNonArray3.chpl:1: In function 'doit': +returnNonArray3.chpl:2: error: expected an array or iterator but got a value of type int(64) + returnNonArray3.chpl:5: called as doit(D: domain(1,int(64),one)) diff --git a/test/arrays/return/returnNonArray4.chpl b/test/arrays/return/returnNonArray4.chpl new file mode 100644 index 000000000000..983147301af3 --- /dev/null +++ b/test/arrays/return/returnNonArray4.chpl @@ -0,0 +1,5 @@ +proc doit(D): [D] int { + return 2; +} + +writeln(doit({1..10})); diff --git a/test/arrays/return/returnNonArray4.good b/test/arrays/return/returnNonArray4.good new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/arrays/return/returnNonArray5.chpl b/test/arrays/return/returnNonArray5.chpl new file mode 100644 index 000000000000..bdff25a47e35 --- /dev/null +++ b/test/arrays/return/returnNonArray5.chpl @@ -0,0 +1,5 @@ +proc doit(D): ([D], []) { + return (2, 3); +} + +writeln(doit({1..10})); diff --git a/test/arrays/return/returnNonArray5.good b/test/arrays/return/returnNonArray5.good new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/arrays/return/returnUnexpectedArray2.chpl b/test/arrays/return/returnUnexpectedArray2.chpl new file mode 100644 index 000000000000..f7795355000d --- /dev/null +++ b/test/arrays/return/returnUnexpectedArray2.chpl @@ -0,0 +1,5 @@ +proc doit(): int { + var A = [1, 2, 3]; + return A; +} +writeln(doit()); diff --git a/test/arrays/return/returnUnexpectedArray2.good b/test/arrays/return/returnUnexpectedArray2.good new file mode 100644 index 000000000000..0783da66f300 --- /dev/null +++ b/test/arrays/return/returnUnexpectedArray2.good @@ -0,0 +1,2 @@ +returnUnexpectedArray2.chpl:1: In function 'doit': +returnUnexpectedArray2.chpl:3: error: cannot initialize return value of type 'int(64)' from an '[domain(1,int(64),one)] int(64)' From 7c25d410e3b079b7067ac94620a3d1ed8b6e2ac6 Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Mon, 10 Aug 2026 16:32:11 -0700 Subject: [PATCH 08/11] add another error case Signed-off-by: Jade Abraham --- modules/internal/ChapelDomain.chpl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/internal/ChapelDomain.chpl b/modules/internal/ChapelDomain.chpl index 4d0f5582eb95..e4d0eb98f36a 100644 --- a/modules/internal/ChapelDomain.chpl +++ b/modules/internal/ChapelDomain.chpl @@ -351,6 +351,12 @@ module ChapelDomain { } } + pragma "last resort" + proc chpl__checkDomainsMatch(a, b) { + compilerError("expected an array or iterator but got a value of type ", + a.type:string); + } + proc chpl_countDomHelp(dom, counts) { var ranges = dom.dims(); for param i in 0..dom.rank-1 do From 200553764ed32a1febad475e1ec0bdd61e0f16aa Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Fri, 14 Aug 2026 09:31:15 -0700 Subject: [PATCH 09/11] fix nested checks with side effects and check fully generic array Signed-off-by: Jade Abraham --- compiler/passes/normalize.cpp | 113 ++++++++++++++++-------------- modules/internal/ChapelArray.chpl | 8 +++ 2 files changed, 70 insertions(+), 51 deletions(-) diff --git a/compiler/passes/normalize.cpp b/compiler/passes/normalize.cpp index 919334d544fe..36df1e9d85e3 100644 --- a/compiler/passes/normalize.cpp +++ b/compiler/passes/normalize.cpp @@ -2282,10 +2282,21 @@ static void insertElementTypeCheck(Expr* declaredRet, Expr* actualRet, retVar->insertBefore(checkEltType); } +// Validates the actual return type is an array of some kind +static void insertGenericArrayCheck(Expr* actualRet, CallExpr* retVar) { + CallExpr* checkGenericArray = new CallExpr("chpl__checkGenericArrayReturn", + actualRet->copy()); + retVar->insertBefore(checkGenericArray); +} + static void modifyPartiallyGenericArrayReturnSimple(FnSymbol* fn, VarSymbol* retval, CallExpr* ret, Expr* retExpr); +static Expr* modifyPartiallyGenericArrayReturnRecurse(FnSymbol* fn, + CallExpr* ret, + Expr* typeExpr, + Expr* retExpr); static void modifyPartiallyGenericArrayReturn(FnSymbol* fn, VarSymbol* retval, CallExpr* ret, @@ -2295,57 +2306,53 @@ static void modifyPartiallyGenericArrayReturn(FnSymbol* fn, modifyPartiallyGenericArrayReturnSimple(fn, retval, ret, retExpr); return; } - - // // at this point, its a pretty good assumption that the return type is a - // // tuple that contains one or more generic arrays - // // to prevent side-effects, we need to insert call temps for the return - // // expression before we start - // // we do this for the entire call expression up front, and then insert checks - // // for each of the generic arrays in the tuple - // prepareRetExpr(retExpr, ret); - - // pair(typeExpr, retExpr) - std::stack> calls; - calls.push(std::make_pair(toCallExpr(typeExpr->body.tail), toCallExpr(retExpr))); - while(calls.size() > 0) { - auto call = calls.top(); - calls.pop(); - auto typeCall = toCallExpr(call.first); - auto myRetExpr = call.second; - auto retCall = toCallExpr(myRetExpr); - if (typeCall && typeCall->isNamed("_build_tuple")) { - if (!(retCall && retCall->isNamed("_build_tuple"))) { - USR_FATAL(fn, "return type is a tuple, but return value is not"); - } - int nTypeArgs = typeCall->numActuals(); - int nRetArgs = retCall->numActuals(); - if (nTypeArgs != nRetArgs) { - USR_FATAL(fn, "return type is a tuple of size %d, but return value is a tuple of size %d", nTypeArgs, nRetArgs); - } - for (int i = 1; i <= nTypeArgs; i++) { - Expr* typeArg = typeCall->get(i); - Expr* retArg = retCall->get(i); - calls.push(std::make_pair(typeArg, retArg)); - } - } else if (typeCall && isGenericArray(typeCall)) { - int nArgs = typeCall->numActuals(); - Expr* domExpr = typeCall->get(1); - Expr* retEltExpr = nArgs == 2 ? typeCall->get(2) : nullptr; - bool noDom = (isSymExpr(domExpr) && toSymExpr(domExpr)->symbol() == gNil); - if (!noDom || retEltExpr != nullptr) { - prepareRetExpr(myRetExpr, ret); - } - if (!noDom) { - // Add checks against the declared domain - insertDomainCheck(myRetExpr, ret, domExpr); - } - if (retEltExpr != nullptr) { - insertElementTypeCheck(retEltExpr, myRetExpr, ret); - } + auto newRetExpr = + modifyPartiallyGenericArrayReturnRecurse(fn, ret, typeExpr->body.tail, retExpr); + ret->insertBefore(new CallExpr(PRIM_MOVE, retval, newRetExpr)); +} +static Expr* modifyPartiallyGenericArrayReturnRecurse(FnSymbol* fn, + CallExpr* ret, + Expr* typeExpr, + Expr* retExpr) { + auto typeCall = toCallExpr(typeExpr); + auto retCall = toCallExpr(retExpr); + if (typeCall && typeCall->isNamed("_build_tuple")) { + if (!(retCall && retCall->isNamed("_build_tuple"))) { + USR_FATAL(fn, "return type is a tuple, but return value is not"); } + int nTypeArgs = typeCall->numActuals(); + int nRetArgs = retCall->numActuals(); + if (nTypeArgs != nRetArgs) { + USR_FATAL(fn, "return type is a tuple of size %d, but return value is a tuple of size %d", nTypeArgs, nRetArgs); + } + for (int i = 1; i <= nTypeArgs; i++) { + Expr* typeArg = typeCall->get(i); + Expr* retArg = retCall->get(i); + retCall->get(i)->replace(new SymExpr(gNil)); // dummy replacement + auto newRetArg = + modifyPartiallyGenericArrayReturnRecurse(fn, ret, typeArg, retArg); + retCall->get(i)->replace(newRetArg); + } + } else if (typeCall && isGenericArray(typeCall)) { + int nArgs = typeCall->numActuals(); + Expr* domExpr = typeCall->get(1); + Expr* retEltExpr = nArgs == 2 ? typeCall->get(2) : nullptr; + bool noDom = (isSymExpr(domExpr) && toSymExpr(domExpr)->symbol() == gNil); + if (!noDom || retEltExpr != nullptr) { + prepareRetExpr(retExpr, ret); + } + if (!noDom) { + // Add checks against the declared domain + insertDomainCheck(retExpr, ret, domExpr); + } + if (retEltExpr != nullptr) { + insertElementTypeCheck(retEltExpr, retExpr, ret); + } + if (noDom && retEltExpr == nullptr) { + insertGenericArrayCheck(retExpr, ret); } - // TODO: Do something about coercion - ret->insertBefore(new CallExpr(PRIM_MOVE, retval, retExpr)); + } + return retExpr; } @@ -2360,7 +2367,7 @@ static void modifyPartiallyGenericArrayReturnSimple(FnSymbol* fn, CallExpr* call = toCallExpr(typeExpr->body.tail); int nArgs = call->numActuals(); Expr* domExpr = call->get(1); - Expr* retEltExpr = nArgs == 2 ? call->get(2) : NULL; + Expr* retEltExpr = nArgs == 2 ? call->get(2) : nullptr; bool noDom = (isSymExpr(domExpr) && toSymExpr(domExpr)->symbol() == gNil); if (!noDom || retEltExpr != nullptr) { @@ -2370,10 +2377,14 @@ static void modifyPartiallyGenericArrayReturnSimple(FnSymbol* fn, // Add checks against the declared domain insertDomainCheck(retExpr, ret, domExpr); } - if (retEltExpr != NULL) { + if (retEltExpr != nullptr) { insertElementTypeCheck(retEltExpr, retExpr, ret); } + if (noDom && retEltExpr == nullptr) { + insertGenericArrayCheck(retExpr, ret); + } + // TODO: Do something about coercion ret->insertBefore(new CallExpr(PRIM_MOVE, retval, retExpr)); diff --git a/modules/internal/ChapelArray.chpl b/modules/internal/ChapelArray.chpl index 7a9044b210c1..542338783634 100644 --- a/modules/internal/ChapelArray.chpl +++ b/modules/internal/ChapelArray.chpl @@ -674,6 +674,14 @@ module ChapelArray { } } + proc chpl__checkGenericArrayReturn(a: []) { } + proc chpl__checkGenericArrayReturn(a: _iteratorRecord) { } + pragma "last resort" + proc chpl__checkGenericArrayReturn(a) { + compilerError("expected an array or iterator but got a value of type ", + a.type:string); + } + // // Support for distributions // From 79ca2df4453850fb079aab4fdb01f096fe92449e Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Fri, 14 Aug 2026 09:31:52 -0700 Subject: [PATCH 10/11] add many tests Signed-off-by: Jade Abraham --- ...returnNonArray4.good => returnArbitraryBadDomain2.bad} | 0 test/arrays/return/returnArbitraryBadDomain2.future | 1 + test/arrays/return/returnArbitraryBadDomain2.good | 2 +- test/arrays/return/returnIterable.chpl | 8 ++++++++ test/arrays/return/returnIterable.good | 2 ++ test/arrays/return/returnIterable2.bad | 0 test/arrays/return/returnIterable2.chpl | 8 ++++++++ test/arrays/return/returnIterable2.future | 1 + test/arrays/return/returnIterable2.good | 2 ++ test/arrays/return/returnNonArray.chpl | 2 +- test/arrays/return/returnNonArray.good | 3 ++- test/arrays/return/returnNonArray2.chpl | 2 +- test/arrays/return/returnNonArray3.chpl | 2 +- .../{returnNonArray4.chpl => returnNonArray4-coerce.chpl} | 2 +- test/arrays/return/returnNonArray4-coerce.good | 1 + test/arrays/return/returnNonArray4-error.chpl | 5 +++++ test/arrays/return/returnNonArray4-error.good | 3 +++ test/arrays/return/returnNonArray5.chpl | 2 +- test/arrays/return/returnNonArray5.good | 3 +++ test/arrays/return/returnNonArray6.chpl | 5 +++++ test/arrays/return/returnNonArray6.good | 8 ++++++++ test/arrays/return/returnNonArray7.chpl | 6 ++++++ test/arrays/return/returnNonArray7.good | 3 +++ test/arrays/return/returnNonArray8.chpl | 5 +++++ test/arrays/return/returnNonArray8.good | 3 +++ 25 files changed, 72 insertions(+), 7 deletions(-) rename test/arrays/return/{returnNonArray4.good => returnArbitraryBadDomain2.bad} (100%) create mode 100644 test/arrays/return/returnArbitraryBadDomain2.future create mode 100644 test/arrays/return/returnIterable.chpl create mode 100644 test/arrays/return/returnIterable.good create mode 100644 test/arrays/return/returnIterable2.bad create mode 100644 test/arrays/return/returnIterable2.chpl create mode 100644 test/arrays/return/returnIterable2.future create mode 100644 test/arrays/return/returnIterable2.good rename test/arrays/return/{returnNonArray4.chpl => returnNonArray4-coerce.chpl} (62%) create mode 100644 test/arrays/return/returnNonArray4-coerce.good create mode 100644 test/arrays/return/returnNonArray4-error.chpl create mode 100644 test/arrays/return/returnNonArray4-error.good create mode 100644 test/arrays/return/returnNonArray6.chpl create mode 100644 test/arrays/return/returnNonArray6.good create mode 100644 test/arrays/return/returnNonArray7.chpl create mode 100644 test/arrays/return/returnNonArray7.good create mode 100644 test/arrays/return/returnNonArray8.chpl create mode 100644 test/arrays/return/returnNonArray8.good diff --git a/test/arrays/return/returnNonArray4.good b/test/arrays/return/returnArbitraryBadDomain2.bad similarity index 100% rename from test/arrays/return/returnNonArray4.good rename to test/arrays/return/returnArbitraryBadDomain2.bad diff --git a/test/arrays/return/returnArbitraryBadDomain2.future b/test/arrays/return/returnArbitraryBadDomain2.future new file mode 100644 index 000000000000..c425be233be1 --- /dev/null +++ b/test/arrays/return/returnArbitraryBadDomain2.future @@ -0,0 +1 @@ +bug: cannot return promoted expression in tuple with explicit domain diff --git a/test/arrays/return/returnArbitraryBadDomain2.good b/test/arrays/return/returnArbitraryBadDomain2.good index e4f19080cf74..e64b7f031f1a 100644 --- a/test/arrays/return/returnArbitraryBadDomain2.good +++ b/test/arrays/return/returnArbitraryBadDomain2.good @@ -1 +1 @@ -returnArbitraryBadDomain.chpl:2: error: halt reached - domain mismatch on return +returnArbitraryBadDomain2.chpl:2: error: halt reached - domain mismatch on return diff --git a/test/arrays/return/returnIterable.chpl b/test/arrays/return/returnIterable.chpl new file mode 100644 index 000000000000..b9a78d519653 --- /dev/null +++ b/test/arrays/return/returnIterable.chpl @@ -0,0 +1,8 @@ +proc inc(X: [] int): (int, (int, [] int)) { + return (X[0], (X[0], X + 3)); +} + +var A = [1, 2, 3, 4, 5]; + +writeln(inc(A)); +writeln(A); diff --git a/test/arrays/return/returnIterable.good b/test/arrays/return/returnIterable.good new file mode 100644 index 000000000000..3686632f594b --- /dev/null +++ b/test/arrays/return/returnIterable.good @@ -0,0 +1,2 @@ +(1, (1, 4 5 6 7 8)) +1 2 3 4 5 diff --git a/test/arrays/return/returnIterable2.bad b/test/arrays/return/returnIterable2.bad new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/arrays/return/returnIterable2.chpl b/test/arrays/return/returnIterable2.chpl new file mode 100644 index 000000000000..c536130d9cce --- /dev/null +++ b/test/arrays/return/returnIterable2.chpl @@ -0,0 +1,8 @@ +proc inc(X: [?D] int): (int, (int, [D] int)) { + return (X[0], (X[0], X + 3)); +} + +var A = [1, 2, 3, 4, 5]; + +writeln(inc(A)); +writeln(A); diff --git a/test/arrays/return/returnIterable2.future b/test/arrays/return/returnIterable2.future new file mode 100644 index 000000000000..c425be233be1 --- /dev/null +++ b/test/arrays/return/returnIterable2.future @@ -0,0 +1 @@ +bug: cannot return promoted expression in tuple with explicit domain diff --git a/test/arrays/return/returnIterable2.good b/test/arrays/return/returnIterable2.good new file mode 100644 index 000000000000..3686632f594b --- /dev/null +++ b/test/arrays/return/returnIterable2.good @@ -0,0 +1,2 @@ +(1, (1, 4 5 6 7 8)) +1 2 3 4 5 diff --git a/test/arrays/return/returnNonArray.chpl b/test/arrays/return/returnNonArray.chpl index adcca5f0541e..fcb51f189e43 100644 --- a/test/arrays/return/returnNonArray.chpl +++ b/test/arrays/return/returnNonArray.chpl @@ -1,5 +1,5 @@ proc doit(): ([] int, int) { - return (2, 3); + return (2, 3); // error: can't coerce individual tuple elements } writeln(doit()); diff --git a/test/arrays/return/returnNonArray.good b/test/arrays/return/returnNonArray.good index 7232c875214b..364178fa2250 100644 --- a/test/arrays/return/returnNonArray.good +++ b/test/arrays/return/returnNonArray.good @@ -1 +1,2 @@ -returnNonArray.chpl:1: error: return type is a tuple, but return value is not +returnNonArray.chpl:1: In function 'doit': +returnNonArray.chpl:2: error: expected an array or iterator but got a value of type int(64) diff --git a/test/arrays/return/returnNonArray2.chpl b/test/arrays/return/returnNonArray2.chpl index a6f6aa5e012f..961e1b446a87 100644 --- a/test/arrays/return/returnNonArray2.chpl +++ b/test/arrays/return/returnNonArray2.chpl @@ -1,5 +1,5 @@ proc doit(): [] int { - return 2; + return 2; // error: can't coerce to array, we don't know the domain } writeln(doit()); diff --git a/test/arrays/return/returnNonArray3.chpl b/test/arrays/return/returnNonArray3.chpl index b92d4c20b6e4..ba5c2e17956d 100644 --- a/test/arrays/return/returnNonArray3.chpl +++ b/test/arrays/return/returnNonArray3.chpl @@ -1,5 +1,5 @@ proc doit(D): [D] { - return 2; + return 2; // can't coerce to generic array } writeln(doit({1..10})); diff --git a/test/arrays/return/returnNonArray4.chpl b/test/arrays/return/returnNonArray4-coerce.chpl similarity index 62% rename from test/arrays/return/returnNonArray4.chpl rename to test/arrays/return/returnNonArray4-coerce.chpl index 983147301af3..a65a9baa6fc7 100644 --- a/test/arrays/return/returnNonArray4.chpl +++ b/test/arrays/return/returnNonArray4-coerce.chpl @@ -1,5 +1,5 @@ proc doit(D): [D] int { - return 2; + return 2; // coerce to array } writeln(doit({1..10})); diff --git a/test/arrays/return/returnNonArray4-coerce.good b/test/arrays/return/returnNonArray4-coerce.good new file mode 100644 index 000000000000..35ba99cb515e --- /dev/null +++ b/test/arrays/return/returnNonArray4-coerce.good @@ -0,0 +1 @@ +2 2 2 2 2 2 2 2 2 2 diff --git a/test/arrays/return/returnNonArray4-error.chpl b/test/arrays/return/returnNonArray4-error.chpl new file mode 100644 index 000000000000..2cad44ea9d98 --- /dev/null +++ b/test/arrays/return/returnNonArray4-error.chpl @@ -0,0 +1,5 @@ +proc doit(D): [D] int { + return "2"; // can't coerce string -> int +} + +writeln(doit({1..10})); diff --git a/test/arrays/return/returnNonArray4-error.good b/test/arrays/return/returnNonArray4-error.good new file mode 100644 index 000000000000..d6f5a138fd60 --- /dev/null +++ b/test/arrays/return/returnNonArray4-error.good @@ -0,0 +1,3 @@ +returnNonArray4-error.chpl:1: In function 'doit': +returnNonArray4-error.chpl:2: error: cannot initialize a value of type 'int(64)' from a 'string' + returnNonArray4-error.chpl:5: called as doit(D: domain(1,int(64),one)) diff --git a/test/arrays/return/returnNonArray5.chpl b/test/arrays/return/returnNonArray5.chpl index bdff25a47e35..ae7616a6b9f1 100644 --- a/test/arrays/return/returnNonArray5.chpl +++ b/test/arrays/return/returnNonArray5.chpl @@ -1,5 +1,5 @@ proc doit(D): ([D], []) { - return (2, 3); + return (2, 3); // error: can't coerce individual tuple elements } writeln(doit({1..10})); diff --git a/test/arrays/return/returnNonArray5.good b/test/arrays/return/returnNonArray5.good index e69de29bb2d1..9ceba6ba197c 100644 --- a/test/arrays/return/returnNonArray5.good +++ b/test/arrays/return/returnNonArray5.good @@ -0,0 +1,3 @@ +returnNonArray5.chpl:1: In function 'doit': +returnNonArray5.chpl:2: error: expected an array or iterator but got a value of type int(64) + returnNonArray5.chpl:5: called as doit(D: domain(1,int(64),one)) diff --git a/test/arrays/return/returnNonArray6.chpl b/test/arrays/return/returnNonArray6.chpl new file mode 100644 index 000000000000..a6398aa1dbdb --- /dev/null +++ b/test/arrays/return/returnNonArray6.chpl @@ -0,0 +1,5 @@ +proc doit(D): ([D], [D] real) { + return (2, 3); // error: can't coerce individual tuple elements +} + +writeln(doit({1..10})); diff --git a/test/arrays/return/returnNonArray6.good b/test/arrays/return/returnNonArray6.good new file mode 100644 index 000000000000..bff6319cef30 --- /dev/null +++ b/test/arrays/return/returnNonArray6.good @@ -0,0 +1,8 @@ +returnNonArray6.chpl:1: In function 'doit': +returnNonArray6.chpl:1: error: unresolved call '_build_tuple([domain(1,int(64),one)] domain(1,int(64),one), type [domain(1,int(64),one)] real(64))' +$CHPL_HOME/modules/internal/ChapelTuple.chpl:42: note: this candidate did not match: _build_tuple(type t ...) +returnNonArray6.chpl:1: note: because non-type actual argument #1 +$CHPL_HOME/modules/internal/ChapelTuple.chpl:42: note: is passed to formal '_e0_t' +returnNonArray6.chpl:1: note: other candidates are: +$CHPL_HOME/modules/internal/ChapelTuple.chpl:48: note: _build_tuple(x ...) + returnNonArray6.chpl:1: called as doit(D: domain(1,int(64),one)) diff --git a/test/arrays/return/returnNonArray7.chpl b/test/arrays/return/returnNonArray7.chpl new file mode 100644 index 000000000000..24fc95868ffc --- /dev/null +++ b/test/arrays/return/returnNonArray7.chpl @@ -0,0 +1,6 @@ +proc doit(D): ([D] real, [] real) { + var A, B: [D] int; + return (A, B); // error: can't coerce individual tuple elements +} + +writeln(doit({1..10})); diff --git a/test/arrays/return/returnNonArray7.good b/test/arrays/return/returnNonArray7.good new file mode 100644 index 000000000000..dc0e36421abc --- /dev/null +++ b/test/arrays/return/returnNonArray7.good @@ -0,0 +1,3 @@ +returnNonArray7.chpl:1: In function 'doit': +returnNonArray7.chpl:3: error: array element type mismatch in return from int(64) to real(64) + returnNonArray7.chpl:6: called as doit(D: domain(1,int(64),one)) diff --git a/test/arrays/return/returnNonArray8.chpl b/test/arrays/return/returnNonArray8.chpl new file mode 100644 index 000000000000..6866fe049598 --- /dev/null +++ b/test/arrays/return/returnNonArray8.chpl @@ -0,0 +1,5 @@ +proc doit(D): [] { + return 2; // can't coerce to generic array +} + +writeln(doit({1..10})); diff --git a/test/arrays/return/returnNonArray8.good b/test/arrays/return/returnNonArray8.good new file mode 100644 index 000000000000..be63b5f4d94f --- /dev/null +++ b/test/arrays/return/returnNonArray8.good @@ -0,0 +1,3 @@ +returnNonArray8.chpl:1: In function 'doit': +returnNonArray8.chpl:2: error: expected an array or iterator but got a value of type int(64) + returnNonArray8.chpl:5: called as doit(D: domain(1,int(64),one)) From 2e1b4fa8a7c1a6a0122dd74e304170794182ae4a Mon Sep 17 00:00:00 2001 From: Jade Abraham Date: Fri, 14 Aug 2026 09:45:49 -0700 Subject: [PATCH 11/11] update future Signed-off-by: Jade Abraham --- test/arrays/return/returnArbitraryBadDomain2.bad | 3 +++ test/arrays/return/returnArbitraryBadDomain2.future | 1 + test/arrays/return/returnIterable2.bad | 3 +++ test/arrays/return/returnIterable2.future | 1 + 4 files changed, 8 insertions(+) diff --git a/test/arrays/return/returnArbitraryBadDomain2.bad b/test/arrays/return/returnArbitraryBadDomain2.bad index e69de29bb2d1..03919c22eb8e 100644 --- a/test/arrays/return/returnArbitraryBadDomain2.bad +++ b/test/arrays/return/returnArbitraryBadDomain2.bad @@ -0,0 +1,3 @@ +returnArbitraryBadDomain2.chpl:1: In function 'inc': +returnArbitraryBadDomain2.chpl:2: error: illegal cast from promoted expression yielding int(64) to [domain(1,int(64),one)] int(64) + returnArbitraryBadDomain2.chpl:7: called as inc(X: [domain(1,int(64),one)] int(64)) diff --git a/test/arrays/return/returnArbitraryBadDomain2.future b/test/arrays/return/returnArbitraryBadDomain2.future index c425be233be1..687ebdbb6155 100644 --- a/test/arrays/return/returnArbitraryBadDomain2.future +++ b/test/arrays/return/returnArbitraryBadDomain2.future @@ -1 +1,2 @@ bug: cannot return promoted expression in tuple with explicit domain +#29261 diff --git a/test/arrays/return/returnIterable2.bad b/test/arrays/return/returnIterable2.bad index e69de29bb2d1..8babde66d599 100644 --- a/test/arrays/return/returnIterable2.bad +++ b/test/arrays/return/returnIterable2.bad @@ -0,0 +1,3 @@ +returnIterable2.chpl:1: In function 'inc': +returnIterable2.chpl:2: error: illegal cast from promoted expression yielding int(64) to [domain(1,int(64),one)] int(64) + returnIterable2.chpl:7: called as inc(X: [domain(1,int(64),one)] int(64)) diff --git a/test/arrays/return/returnIterable2.future b/test/arrays/return/returnIterable2.future index c425be233be1..687ebdbb6155 100644 --- a/test/arrays/return/returnIterable2.future +++ b/test/arrays/return/returnIterable2.future @@ -1 +1,2 @@ bug: cannot return promoted expression in tuple with explicit domain +#29261