Skip to content

Commit

Permalink
Dyno: Fix constness error for unpacked tuple assignment (chapel-lang#…
Browse files Browse the repository at this point in the history
…24761)

This PR resolves a bug where the frontend was issuing a constness error
for statements like ``(a, b, c) = foo();``. The error originated from an
attempt to resolve an assignment operator between the tuple literal
``(a, b, c)`` and the returned tuple from ``foo()``. The LHS naturally
accepts a ``ref``, which is not compatible with a tuple literal. The
Resolver has already taken responsibility for implementing this case, so
resolving the assignment would be incorrect. This PR avoids resolving
the assignment altogether.

A new helper function, ``buildStdContext()``, is added to the
``test-common.h`` header. This function returns a ``unique_ptr`` to a
Context that has been configured to load the standard modules. Use of
the standard modules in this instance was necessary to expose the issue
when trying to resolve the assignment operator defined in
``ChapelTuple``.

[reviewed-by @DanilaFe]
  • Loading branch information
benharsh authored Apr 8, 2024
2 parents 6da6595 + 17c5e38 commit b563da4
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 0 deletions.
8 changes: 8 additions & 0 deletions frontend/lib/resolution/call-init-deinit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<CallInfoActual> actuals;
actuals.push_back(CallInfoActual(lhsType, UniqueString()));
actuals.push_back(CallInfoActual(rhsType, UniqueString()));
Expand Down
34 changes: 34 additions & 0 deletions frontend/test/resolution/testTuples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -656,6 +689,7 @@ int main() {
test9b();
test10();
test11();
test11b();
test12();
test13();
test14();
Expand Down
17 changes: 17 additions & 0 deletions frontend/test/test-common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,20 @@ const uast::AstNode* findOnlyNamed(const uast::Module* mod, std::string name) {
mod->traverse(col);
return col.only();
}

std::unique_ptr<chpl::Context> 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<chpl::Context> ret(context);
return ret;
}
2 changes: 2 additions & 0 deletions frontend/test/test-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<chpl::Context> buildStdContext();

#endif

0 comments on commit b563da4

Please sign in to comment.