[ConstraintSystem] Split unviable lookup result storage into candidates & reasons

That makes it easy to process unviable choices the same way as viable
ones and request rejection reasons only when necessary.
This commit is contained in:
Pavel Yaskevich
2019-03-14 22:20:17 -07:00
parent ce2fe021bf
commit 852169a5f5
4 changed files with 31 additions and 31 deletions

View File

@@ -791,15 +791,19 @@ void FailureDiagnosis::diagnoseUnviableLookupResults(
// Otherwise, we have at least one (and potentially many) viable candidates
// sort them out. If all of the candidates have the same problem (commonly
// because there is exactly one candidate!) diagnose this.
bool sameProblem = true;
auto firstProblem = result.UnviableCandidates[0].second;
auto firstProblem = result.UnviableReasons[0];
bool sameProblem = llvm::all_of(
result.UnviableReasons,
[&firstProblem](const MemberLookupResult::UnviableReason &problem) {
return problem == firstProblem;
});
ValueDecl *member = nullptr;
for (auto cand : result.UnviableCandidates) {
if (member == nullptr)
member = cand.first.getDecl();
sameProblem &= cand.second == firstProblem;
member = cand.getDecl();
}
auto instanceTy = baseObjTy;
if (auto *MTT = instanceTy->getAs<AnyMetatypeType>())
instanceTy = MTT->getInstanceType();
@@ -842,7 +846,7 @@ void FailureDiagnosis::diagnoseUnviableLookupResults(
}
case MemberLookupResult::UR_Inaccessible: {
auto decl = result.UnviableCandidates[0].first.getDecl();
auto decl = result.UnviableCandidates[0].getDecl();
// FIXME: What if the unviable candidates have different levels of access?
//
// If we found an inaccessible member of a protocol extension, it might
@@ -853,8 +857,8 @@ void FailureDiagnosis::diagnoseUnviableLookupResults(
diagnose(nameLoc, diag::candidate_inaccessible, decl->getBaseName(),
decl->getFormalAccessScope().accessLevelForDiagnostics());
for (auto cand : result.UnviableCandidates)
diagnose(cand.first.getDecl(), diag::decl_declared_here, memberName);
diagnose(cand.getDecl(), diag::decl_declared_here, memberName);
return;
}
}
@@ -4206,7 +4210,7 @@ bool FailureDiagnosis::diagnoseMethodAttributeFailures(
SmallVector<OverloadChoice, 2> choices;
for (auto &unviable : results.UnviableCandidates)
choices.push_back(OverloadChoice(baseType, unviable.first.getDecl(),
choices.push_back(OverloadChoice(baseType, unviable.getDecl(),
UDE->getFunctionRefKind()));
CalleeCandidateInfo unviableCandidates(baseType, choices, hasTrailingClosure,

View File

@@ -3719,7 +3719,7 @@ swift::resolveValueMember(DeclContext &DC, Type BaseTy, DeclName Name) {
// Keep track of all the unviable members.
for (auto Can : LookupResult.UnviableCandidates)
Result.Impl.AllDecls.push_back(Can.first.getDecl());
Result.Impl.AllDecls.push_back(Can.getDecl());
// Keep track of the start of viable choices.
Result.Impl.ViableStartIdx = Result.Impl.AllDecls.size();

View File

@@ -3933,10 +3933,10 @@ retry_after_fail:
result.addViable(
OverloadChoice::getDynamicMemberLookup(baseTy, decl, name));
}
for (auto candidate : subscripts.UnviableCandidates) {
auto decl = candidate.first.getDecl();
for (auto index : indices(subscripts.UnviableCandidates)) {
auto decl = subscripts.UnviableCandidates[index].getDecl();
auto choice = OverloadChoice::getDynamicMemberLookup(baseTy, decl,name);
result.addUnviable(choice, candidate.second);
result.addUnviable(choice, subscripts.UnviableReasons[index]);
}
}
}
@@ -4232,21 +4232,15 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
}
if (!result.UnviableCandidates.empty()) {
SmallVector<OverloadChoice, 8> choices;
llvm::transform(
result.UnviableCandidates, std::back_inserter(choices),
[](const std::pair<OverloadChoice, MemberLookupResult::UnviableReason>
&candidate) { return candidate.first; });
// Generate constraints for unvailable choices if they have a fix,
// and disable them by default, they'd get picked up in the "salvage" mode.
generateConstraints(candidates, memberTy, choices, useDC, locator,
/*favoredChoice=*/None, /*requiresFix=*/true,
[&](unsigned idx, const OverloadChoice &choice) {
return fixMemberRef(
*this, baseTy, member, choice, locator,
result.UnviableCandidates[idx].second);
});
generateConstraints(
candidates, memberTy, result.UnviableCandidates, useDC, locator,
/*favoredChoice=*/None, /*requiresFix=*/true,
[&](unsigned idx, const OverloadChoice &choice) {
return fixMemberRef(*this, baseTy, member, choice, locator,
result.UnviableReasons[idx]);
});
}
if (!candidates.empty()) {

View File

@@ -873,11 +873,12 @@ struct MemberLookupResult {
/// The member is inaccessible (e.g. a private member in another file).
UR_Inaccessible,
};
/// This is a list of considered (but rejected) candidates, along with a
/// reason for their rejection.
SmallVector<std::pair<OverloadChoice, UnviableReason>, 4> UnviableCandidates;
/// This is a list of considered (but rejected) candidates, along with a
/// reason for their rejection. Split into separate collections to make
/// it easier to use in conjunction with viable candidates.
SmallVector<OverloadChoice, 4> UnviableCandidates;
SmallVector<UnviableReason, 4> UnviableReasons;
/// Mark this as being an already-diagnosed error and return itself.
MemberLookupResult &markErrorAlreadyDiagnosed() {
@@ -890,7 +891,8 @@ struct MemberLookupResult {
}
void addUnviable(OverloadChoice candidate, UnviableReason reason) {
UnviableCandidates.push_back({candidate, reason});
UnviableCandidates.push_back(candidate);
UnviableReasons.push_back(reason);
}
Optional<unsigned> getFavoredIndex() const {