diff --git a/compiler/passes/normalize.cpp b/compiler/passes/normalize.cpp index 1ec12458089f..36df1e9d85e3 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; +static bool isGenericArray(CallExpr* call) { + if (!call->isNamed("chpl__buildArrayRuntimeType")) return false; - // 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); - - 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,29 +2282,109 @@ 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, Expr* retExpr) { BlockStmt* typeExpr = fn->retExprType; + if (toCallExpr(typeExpr->body.tail)->isNamed("chpl__buildArrayRuntimeType")) { + modifyPartiallyGenericArrayReturnSimple(fn, retval, ret, retExpr); + return; + } + 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); + } + } + return 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(); 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) { + 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); + 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)); @@ -3916,6 +4013,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)); +} /************************************* | ************************************** diff --git a/modules/internal/ChapelArray.chpl b/modules/internal/ChapelArray.chpl index e66a53645b77..542338783634 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 ", @@ -669,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 // 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 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.bad b/test/arrays/return/returnArbitraryBadDomain2.bad new file mode 100644 index 000000000000..03919c22eb8e --- /dev/null +++ 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.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.future b/test/arrays/return/returnArbitraryBadDomain2.future new file mode 100644 index 000000000000..687ebdbb6155 --- /dev/null +++ b/test/arrays/return/returnArbitraryBadDomain2.future @@ -0,0 +1,2 @@ +bug: cannot return promoted expression in tuple with explicit domain +#29261 diff --git a/test/arrays/return/returnArbitraryBadDomain2.good b/test/arrays/return/returnArbitraryBadDomain2.good new file mode 100644 index 000000000000..e64b7f031f1a --- /dev/null +++ b/test/arrays/return/returnArbitraryBadDomain2.good @@ -0,0 +1 @@ +returnArbitraryBadDomain2.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/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/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/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)) 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..8babde66d599 --- /dev/null +++ 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.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..687ebdbb6155 --- /dev/null +++ b/test/arrays/return/returnIterable2.future @@ -0,0 +1,2 @@ +bug: cannot return promoted expression in tuple with explicit domain +#29261 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/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..fcb51f189e43 --- /dev/null +++ b/test/arrays/return/returnNonArray.chpl @@ -0,0 +1,5 @@ +proc doit(): ([] int, int) { + 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 new file mode 100644 index 000000000000..364178fa2250 --- /dev/null +++ b/test/arrays/return/returnNonArray.good @@ -0,0 +1,2 @@ +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 new file mode 100644 index 000000000000..961e1b446a87 --- /dev/null +++ b/test/arrays/return/returnNonArray2.chpl @@ -0,0 +1,5 @@ +proc doit(): [] int { + return 2; // error: can't coerce to array, we don't know the domain +} + +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..ba5c2e17956d --- /dev/null +++ b/test/arrays/return/returnNonArray3.chpl @@ -0,0 +1,5 @@ +proc doit(D): [D] { + return 2; // can't coerce to generic array +} + +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-coerce.chpl b/test/arrays/return/returnNonArray4-coerce.chpl new file mode 100644 index 000000000000..a65a9baa6fc7 --- /dev/null +++ b/test/arrays/return/returnNonArray4-coerce.chpl @@ -0,0 +1,5 @@ +proc doit(D): [D] int { + 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 new file mode 100644 index 000000000000..ae7616a6b9f1 --- /dev/null +++ b/test/arrays/return/returnNonArray5.chpl @@ -0,0 +1,5 @@ +proc doit(D): ([D], []) { + 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 new file mode 100644 index 000000000000..9ceba6ba197c --- /dev/null +++ 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)) 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))' 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)' 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)