Skip to content

Commit e0f0a41

Browse files
committed
[QoI] Switch to diagnoseMemberFailures for subscripts
1 parent 573f20e commit e0f0a41

File tree

1 file changed

+106
-129
lines changed

1 file changed

+106
-129
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 106 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,10 +2153,11 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
21532153
CalleeCandidateInfo &candidates,
21542154
ArrayRef<Identifier> argLabels);
21552155

2156-
bool diagnoseMemberFailures(Expr *baseEpxr, ConstraintKind lookupKind,
2157-
DeclName memberName, FunctionRefKind funcRefKind,
2158-
ConstraintLocator *locator,
2159-
bool includeInaccessibleMembers = true);
2156+
bool diagnoseMemberFailures(
2157+
Expr *baseEpxr, ConstraintKind lookupKind, DeclName memberName,
2158+
FunctionRefKind funcRefKind, ConstraintLocator *locator,
2159+
Optional<std::function<bool(ArrayRef<OverloadChoice>)>> callback = None,
2160+
bool includeInaccessibleMembers = true);
21602161

21612162
bool visitExpr(Expr *E);
21622163
bool visitIdentityExpr(IdentityExpr *E);
@@ -5395,147 +5396,125 @@ bool FailureDiagnosis::visitSubscriptExpr(SubscriptExpr *SE) {
53955396
auto baseExpr = typeCheckChildIndependently(SE->getBase());
53965397
if (!baseExpr) return true;
53975398
auto baseType = baseExpr->getType();
5398-
5399+
53995400
if (isa<NilLiteralExpr>(baseExpr)) {
54005401
diagnose(baseExpr->getLoc(), diag::cannot_subscript_nil_literal)
54015402
.highlight(baseExpr->getSourceRange());
54025403
return true;
54035404
}
54045405

5405-
auto locator =
5406-
CS->getConstraintLocator(SE, ConstraintLocator::SubscriptMember);
5406+
std::function<bool(ArrayRef<OverloadChoice>)> callback =
5407+
[&](ArrayRef<OverloadChoice> candidates) -> bool {
5408+
CalleeCandidateInfo calleeInfo(Type(), candidates, SE->hasTrailingClosure(),
5409+
CS,
5410+
/*selfAlreadyApplied*/ false);
54075411

5408-
auto subscriptName = CS->getASTContext().Id_subscript;
5409-
if (diagnoseMemberFailures(baseExpr, ConstraintKind::ValueMember,
5410-
subscriptName, FunctionRefKind::DoubleApply,
5411-
locator))
5412-
return true;
5412+
// We're about to typecheck the index list, which needs to be processed with
5413+
// self already applied.
5414+
for (unsigned i = 0, e = calleeInfo.size(); i != e; ++i)
5415+
++calleeInfo.candidates[i].level;
54135416

5414-
MemberLookupResult result =
5415-
CS->performMemberLookup(ConstraintKind::ValueMember, subscriptName,
5416-
baseType, FunctionRefKind::DoubleApply, locator,
5417-
/*includeInaccessibleMembers*/true);
5417+
auto indexExpr =
5418+
typeCheckArgumentChildIndependently(SE->getIndex(), Type(), calleeInfo);
5419+
if (!indexExpr)
5420+
return true;
54185421

5419-
5420-
switch (result.OverallResult) {
5421-
case MemberLookupResult::Unsolved:
5422-
return false;
5423-
case MemberLookupResult::ErrorAlreadyDiagnosed:
5424-
// If an error was already emitted, then we're done, don't emit anything
5425-
// redundant.
5426-
return true;
5427-
case MemberLookupResult::HasResults:
5428-
break; // Interesting case. :-)
5429-
}
5430-
5431-
// Don't noise up diagnostics with key path application candidates, since they
5432-
// appear on every type.
5433-
SmallVector<OverloadChoice, 4> viableCandidatesToReport;
5434-
for (auto candidate : result.ViableCandidates)
5435-
if (candidate.getKind() != OverloadChoiceKind::KeyPathApplication)
5436-
viableCandidatesToReport.push_back(candidate);
5422+
// Back to analyzing the candidate list with self applied.
5423+
for (unsigned i = 0, e = calleeInfo.size(); i != e; ++i)
5424+
--calleeInfo.candidates[i].level;
54375425

5438-
CalleeCandidateInfo calleeInfo(Type(), viableCandidatesToReport,
5439-
SE->hasTrailingClosure(), CS,
5440-
/*selfAlreadyApplied*/false);
5426+
ArrayRef<Identifier> argLabels = SE->getArgumentLabels();
5427+
if (diagnoseParameterErrors(calleeInfo, SE, indexExpr, argLabels))
5428+
return true;
54415429

5442-
// We're about to typecheck the index list, which needs to be processed with
5443-
// self already applied.
5444-
for (unsigned i = 0, e = calleeInfo.size(); i != e; ++i)
5445-
++calleeInfo.candidates[i].level;
5446-
5447-
auto indexExpr = typeCheckArgumentChildIndependently(SE->getIndex(),
5448-
Type(), calleeInfo);
5449-
if (!indexExpr) return true;
5430+
auto indexType = indexExpr->getType();
5431+
5432+
auto decomposedBaseType = decomposeArgType(baseType, {Identifier()});
5433+
auto decomposedIndexType = decomposeArgType(indexType, argLabels);
5434+
calleeInfo.filterList(
5435+
[&](UncurriedCandidate cand) -> CalleeCandidateInfo::ClosenessResultTy {
5436+
// Classify how close this match is. Non-subscript decls don't match.
5437+
if (!dyn_cast_or_null<SubscriptDecl>(cand.getDecl()))
5438+
return {CC_GeneralMismatch, {}};
5439+
5440+
// Check whether the self type matches.
5441+
auto selfConstraint = CC_ExactMatch;
5442+
if (calleeInfo.evaluateCloseness(cand, decomposedBaseType).first !=
5443+
CC_ExactMatch)
5444+
selfConstraint = CC_SelfMismatch;
5445+
5446+
// Increase the uncurry level to look past the self argument to the
5447+
// indices.
5448+
cand.level++;
5449+
5450+
// Explode out multi-index subscripts to find the best match.
5451+
auto indexResult =
5452+
calleeInfo.evaluateCloseness(cand, decomposedIndexType);
5453+
if (selfConstraint > indexResult.first)
5454+
return {selfConstraint, {}};
5455+
return indexResult;
5456+
});
54505457

5451-
// Back to analyzing the candidate list with self applied.
5452-
for (unsigned i = 0, e = calleeInfo.size(); i != e; ++i)
5453-
--calleeInfo.candidates[i].level;
5458+
// If the closest matches all mismatch on self, we either have something
5459+
// that
5460+
// cannot be subscripted, or an ambiguity.
5461+
if (calleeInfo.closeness == CC_SelfMismatch) {
5462+
diagnose(SE->getLoc(), diag::cannot_subscript_base, baseType)
5463+
.highlight(SE->getBase()->getSourceRange());
5464+
// FIXME: Should suggest overload set, but we're not ready for that until
5465+
// it points to candidates and identifies the self type in the diagnostic.
5466+
// calleeInfo.suggestPotentialOverloads(SE->getLoc());
5467+
return true;
5468+
}
54545469

5455-
ArrayRef<Identifier> argLabels = SE->getArgumentLabels();
5456-
if (diagnoseParameterErrors(calleeInfo, SE, indexExpr, argLabels))
5457-
return true;
5470+
// Any other failures relate to the index list.
5471+
for (unsigned i = 0, e = calleeInfo.size(); i != e; ++i)
5472+
++calleeInfo.candidates[i].level;
54585473

5459-
auto indexType = indexExpr->getType();
5474+
// TODO: Is there any reason to check for CC_NonLValueInOut here?
54605475

5461-
auto decomposedBaseType = decomposeArgType(baseType, { Identifier() });
5462-
auto decomposedIndexType = decomposeArgType(indexType, argLabels);
5463-
calleeInfo.filterList([&](UncurriedCandidate cand) ->
5464-
CalleeCandidateInfo::ClosenessResultTy
5465-
{
5466-
// Classify how close this match is. Non-subscript decls don't match.
5467-
if (!dyn_cast_or_null<SubscriptDecl>(cand.getDecl()))
5468-
return { CC_GeneralMismatch, {}};
5469-
5470-
// Check whether the self type matches.
5471-
auto selfConstraint = CC_ExactMatch;
5472-
if (calleeInfo.evaluateCloseness(cand, decomposedBaseType)
5473-
.first != CC_ExactMatch)
5474-
selfConstraint = CC_SelfMismatch;
5475-
5476-
// Increase the uncurry level to look past the self argument to the indices.
5477-
cand.level++;
5478-
5479-
// Explode out multi-index subscripts to find the best match.
5480-
auto indexResult =
5481-
calleeInfo.evaluateCloseness(cand, decomposedIndexType);
5482-
if (selfConstraint > indexResult.first)
5483-
return {selfConstraint, {}};
5484-
return indexResult;
5485-
});
5476+
if (calleeInfo.closeness == CC_ExactMatch) {
5477+
// Otherwise, whatever the result type of the call happened to be must not
5478+
// have been what we were looking for. Lets diagnose it as a conversion
5479+
// or ambiguity failure.
5480+
if (calleeInfo.size() == 1)
5481+
return false;
54865482

5487-
// If the closest matches all mismatch on self, we either have something that
5488-
// cannot be subscripted, or an ambiguity.
5489-
if (calleeInfo.closeness == CC_SelfMismatch) {
5490-
diagnose(SE->getLoc(), diag::cannot_subscript_base, baseType)
5491-
.highlight(SE->getBase()->getSourceRange());
5492-
// FIXME: Should suggest overload set, but we're not ready for that until
5493-
// it points to candidates and identifies the self type in the diagnostic.
5494-
//calleeInfo.suggestPotentialOverloads(SE->getLoc());
5495-
return true;
5496-
}
5483+
diagnose(SE->getLoc(), diag::ambiguous_subscript, baseType, indexType)
5484+
.highlight(indexExpr->getSourceRange())
5485+
.highlight(baseExpr->getSourceRange());
54975486

5498-
// Any other failures relate to the index list.
5499-
for (unsigned i = 0, e = calleeInfo.size(); i != e; ++i)
5500-
++calleeInfo.candidates[i].level;
5501-
5502-
// TODO: Is there any reason to check for CC_NonLValueInOut here?
5503-
5504-
if (calleeInfo.closeness == CC_ExactMatch) {
5505-
// Otherwise, whatever the result type of the call happened to be must not
5506-
// have been what we were looking for. Lets diagnose it as a conversion
5507-
// or ambiguity failure.
5508-
if (calleeInfo.size() == 1)
5509-
return false;
5487+
// FIXME: suggestPotentialOverloads should do this.
5488+
// calleeInfo.suggestPotentialOverloads(SE->getLoc());
5489+
for (auto candidate : calleeInfo.candidates)
5490+
if (auto decl = candidate.getDecl())
5491+
diagnose(decl, diag::found_candidate);
5492+
else
5493+
diagnose(candidate.getExpr()->getLoc(), diag::found_candidate);
55105494

5511-
diagnose(SE->getLoc(), diag::ambiguous_subscript, baseType, indexType)
5512-
.highlight(indexExpr->getSourceRange())
5513-
.highlight(baseExpr->getSourceRange());
5514-
5515-
// FIXME: suggestPotentialOverloads should do this.
5516-
//calleeInfo.suggestPotentialOverloads(SE->getLoc());
5517-
for (auto candidate : calleeInfo.candidates)
5518-
if (auto decl = candidate.getDecl())
5519-
diagnose(decl, diag::found_candidate);
5520-
else
5521-
diagnose(candidate.getExpr()->getLoc(), diag::found_candidate);
5495+
return true;
5496+
}
55225497

5523-
return true;
5524-
}
5498+
if (diagnoseParameterErrors(calleeInfo, SE, indexExpr, argLabels))
5499+
return true;
55255500

5526-
if (diagnoseParameterErrors(calleeInfo, SE, indexExpr, argLabels))
5527-
return true;
5501+
// Diagnose some simple and common errors.
5502+
if (calleeInfo.diagnoseSimpleErrors(SE))
5503+
return true;
55285504

5529-
// Diagnose some simple and common errors.
5530-
if (calleeInfo.diagnoseSimpleErrors(SE))
5531-
return true;
5505+
diagnose(SE->getLoc(), diag::cannot_subscript_with_index, baseType,
5506+
indexType);
55325507

5508+
calleeInfo.suggestPotentialOverloads(SE->getLoc());
5509+
return true;
5510+
};
55335511

5534-
diagnose(SE->getLoc(), diag::cannot_subscript_with_index,
5535-
baseType, indexType);
5512+
auto locator =
5513+
CS->getConstraintLocator(SE, ConstraintLocator::SubscriptMember);
55365514

5537-
calleeInfo.suggestPotentialOverloads(SE->getLoc());
5538-
return true;
5515+
return diagnoseMemberFailures(
5516+
baseExpr, ConstraintKind::ValueMember, CS->getASTContext().Id_subscript,
5517+
FunctionRefKind::DoubleApply, locator, callback);
55395518
}
55405519

55415520

@@ -7652,12 +7631,11 @@ bool FailureDiagnosis::visitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
76527631
llvm_unreachable("all cases should be handled");
76537632
}
76547633

7655-
bool FailureDiagnosis::diagnoseMemberFailures(Expr *baseExpr,
7656-
ConstraintKind lookupKind,
7657-
DeclName memberName,
7658-
FunctionRefKind funcRefKind,
7659-
ConstraintLocator *locator,
7660-
bool includeInaccessibleMembers) {
7634+
bool FailureDiagnosis::diagnoseMemberFailures(
7635+
Expr *baseExpr, ConstraintKind lookupKind, DeclName memberName,
7636+
FunctionRefKind funcRefKind, ConstraintLocator *locator,
7637+
Optional<std::function<bool(ArrayRef<OverloadChoice>)>> callback,
7638+
bool includeInaccessibleMembers) {
76617639
auto isInitializer = memberName.isSimpleName(CS->TC.Context.Id_init);
76627640

76637641
// Get the referenced base expression from the failed constraint, along with
@@ -7881,8 +7859,7 @@ bool FailureDiagnosis::diagnoseMemberFailures(Expr *baseExpr,
78817859
return true;
78827860
}
78837861

7884-
// Otherwise, we don't know why this failed.
7885-
return false;
7862+
return callback.hasValue() ? (*callback)(viableCandidatesToReport) : false;
78867863
}
78877864

78887865
bool FailureDiagnosis::visitUnresolvedDotExpr(UnresolvedDotExpr *UDE) {

0 commit comments

Comments
 (0)