Skip to content

Commit

Permalink
small refactor to extract helper, condition updates
Browse files Browse the repository at this point in the history
Signed-off-by: Ahmad Rezaii <[email protected]>
  • Loading branch information
arezaii committed Jan 9, 2025
1 parent 1c8e599 commit 7ab602b
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 40 deletions.
86 changes: 48 additions & 38 deletions frontend/lib/resolution/Resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ApplicabilityResult>& 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<resolution::FormalActual> badPasses;
std::vector<const uast::VarLikeDecl*> 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) {
Expand Down Expand Up @@ -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<resolution::FormalActual> badPasses;
std::vector<const uast::VarLikeDecl*> 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;
}
}
Expand Down
7 changes: 5 additions & 2 deletions frontend/lib/resolution/resolution-error-classes-list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 7ab602b

Please sign in to comment.