From 7ab602b7eba92930b28fad0a62153550aae65b90 Mon Sep 17 00:00:00 2001 From: Ahmad Rezaii Date: Wed, 8 Jan 2025 19:46:44 -0700 Subject: [PATCH] small refactor to extract helper, condition updates Signed-off-by: Ahmad Rezaii --- frontend/lib/resolution/Resolver.cpp | 86 +++++++++++-------- .../resolution-error-classes-list.cpp | 7 +- 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/frontend/lib/resolution/Resolver.cpp b/frontend/lib/resolution/Resolver.cpp index 4ce4e30da067..928039b16311 100644 --- a/frontend/lib/resolution/Resolver.cpp +++ b/frontend/lib/resolution/Resolver.cpp @@ -944,6 +944,53 @@ static bool isCallToPtr(const AstNode* formalTypeExpr) { return false; } +// helper to gather bad actuals and report NoMatchingCandidates error +static void +handleRejectedCandidates(Context* context, + ResolutionResultByPostorderID& byPostorder, + std::vector& rejected, + const resolution::CallInfo& ci, + const uast::Call*& call) { + // There were candidates but we threw them out. We can issue a nicer + // error explaining why each candidate was rejected. + std::vector badPasses; + std::vector actualDecls; + badPasses.resize(rejected.size()); + actualDecls.resize(rejected.size()); + // check each rejected candidate for uninitialized actuals + for (size_t i = 0; i < rejected.size(); i++) { + auto &candidate = rejected[i]; + if (candidate.reason() == resolution::FAIL_CANNOT_PASS && + /* skip printing detailed info_ here because computing the formal-actual + map will go poorly with an unknown formal. */ + candidate.formalReason() != resolution::FAIL_UNKNOWN_FORMAL_TYPE) { + auto fn = candidate.initialForErr(); + resolution::FormalActualMap fa(fn, ci); + auto& badPass = fa.byFormalIdx(candidate.formalIdx()); + badPasses[i] = badPass; + const uast::AstNode *actualExpr = nullptr; + const uast::VarLikeDecl *actualDecl = nullptr; + if (call && 0 <= badPass.actualIdx() && + badPass.actualIdx() < call->numActuals()) { + actualExpr = call->actual(badPass.actualIdx()); + } + // look for a definition point of the actual for error reporting of + // uninitialized vars typically in the case of bad split-initialization + if (actualExpr && actualExpr->isIdentifier()) { + auto &resolvedExpr = byPostorder.byAst(actualExpr->toIdentifier()); + if (auto id = resolvedExpr.toId()) { + auto var = parsing::idToAst(context, id); + // should put a nullptr if not a VarLikeDecl + actualDecl = var->toVarLikeDecl(); + } + } + actualDecls[i] = actualDecl; + } + } + CHPL_ASSERT(badPasses.size() == rejected.size() && rejected.size() == actualDecls.size()); + CHPL_REPORT(context, NoMatchingCandidates, call, ci, rejected, badPasses, actualDecls); +} + static void varArgTypeQueryError(Context* context, const AstNode* node, ResolvedExpression& result) { @@ -1949,44 +1996,7 @@ void Resolver::handleResolvedCallPrintCandidates(ResolvedExpression& r, } if (!rejected.empty()) { - // There were candidates but we threw them out. We can issue a nicer - // error explaining why each candidate was rejected. - std::vector badPasses; - std::vector actualDecls; - badPasses.resize(rejected.size()); - actualDecls.resize(rejected.size()); - // check each rejected candidate for uninitialized actuals - for (size_t i = 0; i < rejected.size(); i++) { - auto& candidate = rejected[i]; - if (candidate.reason() == resolution::FAIL_CANNOT_PASS && - /* skip printing detailed info_ here because computing the formal-actual - map will go poorly with an unknown formal. */ - candidate.formalReason() != resolution::FAIL_UNKNOWN_FORMAL_TYPE) { - auto fn = candidate.initialForErr(); - resolution::FormalActualMap fa(fn, ci); - auto badPass = fa.byFormalIdx(candidate.formalIdx()); - badPasses[i] = badPass; - const uast::AstNode* actualExpr = nullptr; - const uast::VarLikeDecl* actualDecl = nullptr; - if (call && 0 <= badPass.actualIdx() && - badPass.actualIdx() < call->numActuals()) { - actualExpr = call->actual(badPass.actualIdx()); - } - // look for a definition point of the actual for error reporting of - // uninitialized vars typically in the case of bad split-initialization - if (actualExpr && actualExpr->isIdentifier()) { - auto& resolvedExpr = byPostorder.byAst(actualExpr->toIdentifier()); - if (auto id = resolvedExpr.toId()) { - auto var = parsing::idToAst(context, id); - // should put a nullptr if not a VarLikeDecl - actualDecl = var->toVarLikeDecl(); - } - } - actualDecls[i] = actualDecl; - } - } - CHPL_ASSERT((badPasses.size() == rejected.size()) && (rejected.size() == actualDecls.size())); - CHPL_REPORT(context, NoMatchingCandidates, call, ci, rejected, badPasses, actualDecls); + handleRejectedCandidates(context, byPostorder, rejected, ci, call); return; } } diff --git a/frontend/lib/resolution/resolution-error-classes-list.cpp b/frontend/lib/resolution/resolution-error-classes-list.cpp index bd8cc61a76a2..5bc5c4a1512c 100644 --- a/frontend/lib/resolution/resolution-error-classes-list.cpp +++ b/frontend/lib/resolution/resolution-error-classes-list.cpp @@ -1044,14 +1044,17 @@ void ErrorNoMatchingCandidates::write(ErrorWriterBase& wr) const { formalName = "'" + buildTupleDeclName(formalDecl->toTupleDecl()) + "'"; } bool actualPrinted = false; + auto offendingActual = actualDecls[iterCount]; if (badPass.formalType().isUnknown()) { // The formal type can be unknown in an initial instantiation if it // depends on the previous formals' types. In that case, don't print it // and say something nicer. wr.message("The instantiated type of formal ", formalName, " does not allow actuals of type '", badPass.actualType().type(), "'."); - } else if (badPass.actualType().isUnknown() && actualExpr && actualExpr->isIdentifier()) { - auto offendingActual = actualDecls[iterCount]; + } else if (badPass.actualType().isUnknown() && + offendingActual && + !offendingActual->initExpression() && + !offendingActual->typeExpression()) { auto formalKind = badPass.formalType().kind(); auto actualName = "'" + actualExpr->toIdentifier()->name().str() + "'"; wr.note(actualExpr->id(), "The actual ", actualName,