diff --git a/frontend/lib/resolution/call-init-deinit.cpp b/frontend/lib/resolution/call-init-deinit.cpp index d02ef7194a71..dad02139b0f9 100644 --- a/frontend/lib/resolution/call-init-deinit.cpp +++ b/frontend/lib/resolution/call-init-deinit.cpp @@ -514,6 +514,14 @@ void CallInitDeinit::resolveAssign(const AstNode* ast, return; } + if (auto call = ast->toOpCall()) { + if (call->op() == "=" && call->child(0)->isTuple()) { + // Tuple unpacking assignment, handled directly by Resolver + // (a, b, c) = foo(); + return; + } + } + std::vector actuals; actuals.push_back(CallInfoActual(lhsType, UniqueString())); actuals.push_back(CallInfoActual(rhsType, UniqueString())); diff --git a/frontend/test/resolution/testTuples.cpp b/frontend/test/resolution/testTuples.cpp index 961113c64cf8..5a4511eaa17c 100644 --- a/frontend/test/resolution/testTuples.cpp +++ b/frontend/test/resolution/testTuples.cpp @@ -396,6 +396,39 @@ static void test11() { assert(tt->elementType(0).type()->isRealType()); } +static void test11b() { + printf("test11b\n"); + auto uctx = buildStdContext(); + auto context = uctx.get(); + ErrorGuard guard(context); + + // Exercises a case where the frontend was attempting to resolve an '=' + // operator between "(a, b)" and "foo()", and naturally running into + // constness errors. The Resolver handles this already, so we shouldn't ever + // bother to resolve that assignment. + auto t = resolveTypeOfX(context, + R""""( + record R { var i : int; } + + proc foo() { + return (new R(5), new R(42)); + } + + proc helper() { + var a : R; + var b : R; + + (a, b) = foo(); + + return a; + } + + var x = helper(); + )""""); + + assert(t->isRecordType()); +} + static void test12() { printf("test12\n"); Context ctx; @@ -656,6 +689,7 @@ int main() { test9b(); test10(); test11(); + test11b(); test12(); test13(); test14(); diff --git a/frontend/test/test-common.cpp b/frontend/test/test-common.cpp index 1d77b6b27a84..5e4a0e40ade9 100644 --- a/frontend/test/test-common.cpp +++ b/frontend/test/test-common.cpp @@ -73,3 +73,20 @@ const uast::AstNode* findOnlyNamed(const uast::Module* mod, std::string name) { mod->traverse(col); return col.only(); } + +std::unique_ptr buildStdContext() { + std::string chpl_home; + if (const char* chpl_home_env = getenv("CHPL_HOME")) { + chpl_home = chpl_home_env; + } else { + printf("CHPL_HOME must be set"); + exit(1); + } + Context::Configuration config; + config.chplHome = chpl_home; + Context* context = new Context(config); + chpl::parsing::setupModuleSearchPaths(context, false, false, {}, {}); + + std::unique_ptr ret(context); + return ret; +} diff --git a/frontend/test/test-common.h b/frontend/test/test-common.h index 98002111acbb..ef16e68a4cdc 100644 --- a/frontend/test/test-common.h +++ b/frontend/test/test-common.h @@ -50,4 +50,6 @@ parseStringAndReportErrors(chpl::parsing::Parser* parser, const char* filename, const chpl::uast::AstNode* findOnlyNamed(const chpl::uast::Module* mod, std::string name); +std::unique_ptr buildStdContext(); + #endif