Skip to content

Commit 60801bf

Browse files
committed
Sema: Split up ConformanceChecker::diagnoseMissingWitnesses()
1 parent f2c27df commit 60801bf

File tree

3 files changed

+83
-101
lines changed

3 files changed

+83
-101
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3995,12 +3995,14 @@ TypeWitnessAndDecl
39953995
TypeWitnessRequest::evaluate(Evaluator &eval,
39963996
NormalProtocolConformance *conformance,
39973997
AssociatedTypeDecl *requirement) const {
3998+
auto &ctx = requirement->getASTContext();
39983999
llvm::SetVector<ASTContext::MissingWitness> MissingWitnesses;
3999-
ConformanceChecker checker(requirement->getASTContext(), conformance,
4000-
MissingWitnesses);
4000+
ConformanceChecker checker(ctx, conformance, MissingWitnesses);
40014001
checker.resolveSingleTypeWitness(requirement);
4002-
checker.diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::ErrorOnly,
4003-
/*Delayed=*/true);
4002+
for (auto missing : MissingWitnesses) {
4003+
ctx.addDelayedMissingWitness(conformance, missing);
4004+
}
4005+
40044006
// FIXME: ConformanceChecker and the other associated WitnessCheckers have
40054007
// an extremely convoluted caching scheme that doesn't fit nicely into the
40064008
// evaluator's model. All of this should be refactored away.

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 77 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,40 +1966,77 @@ isUnsatisfiedReq(NormalProtocolConformance *conformance, ValueDecl *req,
19661966
return false;
19671967
}
19681968

1969+
static void
1970+
diagnoseMatch(ModuleDecl *module, NormalProtocolConformance *conformance,
1971+
ValueDecl *req, const RequirementMatch &match);
1972+
1973+
static void diagnoseProtocolStubFixit(
1974+
ASTContext &ctx,
1975+
NormalProtocolConformance *conformance,
1976+
ArrayRef<ASTContext::MissingWitness> missingWitnesses);
1977+
19691978
void MultiConformanceChecker::checkAllConformances() {
19701979
bool anyInvalid = false;
1971-
for (unsigned I = 0, N = AllConformances.size(); I < N; ++I) {
1972-
auto *conformance = AllConformances[I];
1973-
// Check this conformance and emit fixits if this is the last one in the pool.
1980+
for (auto *conformance : AllConformances) {
19741981
checkIndividualConformance(conformance);
19751982
anyInvalid |= conformance->isInvalid();
1976-
if (anyInvalid)
1977-
continue;
1978-
// Check whether there are any unsatisfied requirements.
1979-
auto proto = conformance->getProtocol();
1980-
ObjCRequirementMap map = getObjCRequirementMap(proto);
1983+
if (!anyInvalid) {
1984+
// Check whether there are any unsatisfied requirements.
1985+
auto proto = conformance->getProtocol();
1986+
ObjCRequirementMap map = getObjCRequirementMap(proto);
19811987

1982-
for (auto *req : proto->getProtocolRequirements()) {
1983-
// If the requirement is unsatisfied, we might want to warn
1984-
// about near misses; record it.
1985-
if (isUnsatisfiedReq(conformance, req, map)) {
1986-
UnsatisfiedReqs.push_back(req);
1987-
continue;
1988+
for (auto *req : proto->getProtocolRequirements()) {
1989+
// If the requirement is unsatisfied, we might want to warn
1990+
// about near misses; record it.
1991+
if (isUnsatisfiedReq(conformance, req, map)) {
1992+
UnsatisfiedReqs.push_back(req);
1993+
continue;
1994+
}
19881995
}
19891996
}
1997+
1998+
if (AllUsedCheckers.empty() ||
1999+
AllUsedCheckers.back().Conformance != conformance) {
2000+
continue;
2001+
}
2002+
2003+
auto &checker = AllUsedCheckers.back();
2004+
auto LocalMissing = checker.getLocalMissingWitness();
2005+
if (LocalMissing.empty())
2006+
continue;
2007+
2008+
// Diagnose the missing witnesses.
2009+
for (auto &Missing : LocalMissing) {
2010+
auto requirement = Missing.requirement;
2011+
auto matches = Missing.matches;
2012+
2013+
Context.addDelayedConformanceDiag(conformance, true,
2014+
[requirement, matches](NormalProtocolConformance *conformance) {
2015+
auto dc = conformance->getDeclContext();
2016+
auto *protocol = conformance->getProtocol();
2017+
auto *nominal = dc->getSelfNominalTypeDecl();
2018+
// Possibly diagnose reason for automatic derivation failure
2019+
DerivedConformance::tryDiagnoseFailedDerivation(dc, nominal, protocol);
2020+
// Diagnose each of the matches.
2021+
for (const auto &match : matches) {
2022+
diagnoseMatch(dc->getParentModule(), conformance, requirement, match);
2023+
}
2024+
});
2025+
}
19902026
}
1991-
// If all missing witnesses are issued with fixits, we are done.
2027+
2028+
// If there were no missing witnesses, we're done.
19922029
if (MissingWitnesses.empty())
19932030
return;
19942031

19952032
// Otherwise, backtrack to the last checker that has missing witnesses
19962033
// and diagnose missing witnesses from there.
1997-
for (auto It = AllUsedCheckers.rbegin(); It != AllUsedCheckers.rend();
1998-
++It) {
1999-
if (!It->getLocalMissingWitness().empty()) {
2000-
if (It->diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::FixItOnly,
2001-
/*Delayed=*/false))
2002-
break;
2034+
for (auto &checker : llvm::reverse(AllUsedCheckers)) {
2035+
if (!checker.getLocalMissingWitness().empty()) {
2036+
diagnoseProtocolStubFixit(Context,
2037+
checker.Conformance,
2038+
MissingWitnesses.getArrayRef());
2039+
break;
20032040
}
20042041
}
20052042
}
@@ -3752,58 +3789,19 @@ static void diagnoseProtocolStubFixit(
37523789
}
37533790
}
37543791

3755-
bool ConformanceChecker::
3756-
diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind, bool Delayed) {
3757-
auto LocalMissing = getLocalMissingWitness();
3758-
3759-
// If this conformance has nothing to complain, return.
3760-
if (LocalMissing.empty())
3761-
return false;
3762-
3763-
if (Delayed) {
3764-
// If the diagnostics are suppressed, we register these missing witnesses
3765-
// for later revisiting.
3766-
for (auto Missing : LocalMissing) {
3767-
getASTContext().addDelayedMissingWitness(Conformance, Missing);
3768-
}
3769-
3770-
return true;
3771-
}
3772-
3773-
switch (Kind) {
3774-
case MissingWitnessDiagnosisKind::FixItOnly: {
3775-
const auto MissingWitnesses = filterProtocolRequirements(
3776-
GlobalMissingWitnesses.getArrayRef(), Adoptee);
3777-
getASTContext().addDelayedConformanceDiag(Conformance, true,
3778-
[MissingWitnesses](NormalProtocolConformance *Conf) {
3779-
diagnoseProtocolStubFixit(Conf, MissingWitnesses);
3780-
});
3781-
clearGlobalMissingWitnesses();
3782-
return true;
3783-
}
3784-
3785-
case MissingWitnessDiagnosisKind::ErrorOnly: {
3786-
// Diagnose the missing witnesses.
3787-
for (auto &Missing : LocalMissing) {
3788-
auto requirement = Missing.requirement;
3789-
auto matches = Missing.matches;
3790-
auto nominal = DC->getSelfNominalTypeDecl();
3791-
3792-
getASTContext().addDelayedConformanceDiag(Conformance, true,
3793-
[requirement, matches, nominal](NormalProtocolConformance *conformance) {
3794-
auto dc = conformance->getDeclContext();
3795-
auto *protocol = conformance->getProtocol();
3796-
// Possibly diagnose reason for automatic derivation failure
3797-
DerivedConformance::tryDiagnoseFailedDerivation(dc, nominal, protocol);
3798-
// Diagnose each of the matches.
3799-
for (const auto &match : matches) {
3800-
diagnoseMatch(dc->getParentModule(), conformance, requirement, match);
3801-
}
3802-
});
3803-
}
3804-
}
3805-
return true;
3806-
}
3792+
static void diagnoseProtocolStubFixit(
3793+
ASTContext &ctx,
3794+
NormalProtocolConformance *conformance,
3795+
ArrayRef<ASTContext::MissingWitness> missingWitnesses) {
3796+
auto selfInterfaceType = conformance->getDeclContext()->getSelfInterfaceType();
3797+
const auto filteredWitnesses = filterProtocolRequirements(
3798+
missingWitnesses, selfInterfaceType);
3799+
assert(!filteredWitnesses.empty());
3800+
3801+
ctx.addDelayedConformanceDiag(conformance, true,
3802+
[filteredWitnesses](NormalProtocolConformance *conf) {
3803+
diagnoseProtocolStubFixit(conf, filteredWitnesses);
3804+
});
38073805
}
38083806

38093807
/// Whether the given protocol requirement has a "Self ==" constraint.
@@ -5072,10 +5070,6 @@ void ConformanceChecker::checkConformance() {
50725070
// Check non-type requirements.
50735071
resolveValueWitnesses();
50745072

5075-
// Diagnose any missing witnesses.
5076-
diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::ErrorOnly,
5077-
/*Delayed=*/false);
5078-
50795073
// Except in specific hardcoded cases for Foundation/Swift
50805074
// standard library compatibility, an _ObjectiveCBridgeable
50815075
// conformance must appear in the same module as the definition of
@@ -6463,12 +6457,14 @@ Witness
64636457
ValueWitnessRequest::evaluate(Evaluator &eval,
64646458
NormalProtocolConformance *conformance,
64656459
ValueDecl *requirement) const {
6460+
auto &ctx = requirement->getASTContext();
64666461
llvm::SetVector<ASTContext::MissingWitness> MissingWitnesses;
6467-
ConformanceChecker checker(requirement->getASTContext(), conformance,
6468-
MissingWitnesses);
6462+
ConformanceChecker checker(ctx, conformance, MissingWitnesses);
64696463
checker.resolveSingleWitness(requirement);
6470-
checker.diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::ErrorOnly,
6471-
/*Delayed=*/true);
6464+
for (auto missing : MissingWitnesses) {
6465+
ctx.addDelayedMissingWitness(conformance, missing);
6466+
}
6467+
64726468
// FIXME: ConformanceChecker and the other associated WitnessCheckers have
64736469
// an extremely convoluted caching scheme that doesn't fit nicely into the
64746470
// evaluator's model. All of this should be refactored away.

lib/Sema/TypeCheckProtocol.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,6 @@ enum class ResolveWitnessResult {
117117
Missing
118118
};
119119

120-
enum class MissingWitnessDiagnosisKind {
121-
FixItOnly,
122-
ErrorOnly,
123-
};
124-
125120
/// The protocol conformance checker.
126121
///
127122
/// This helper class handles most of the details of checking whether a
@@ -195,17 +190,6 @@ class ConformanceChecker : public WitnessChecker {
195190
GlobalMissingWitnesses.size() - LocalMissingWitnessesStartIndex);
196191
}
197192

198-
void clearGlobalMissingWitnesses() {
199-
GlobalMissingWitnesses.clear();
200-
LocalMissingWitnessesStartIndex = GlobalMissingWitnesses.size();
201-
}
202-
203-
/// Call this to diagnose currently known missing witnesses.
204-
///
205-
/// \returns true if any witnesses were diagnosed.
206-
bool diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind,
207-
bool Delayed);
208-
209193
ConformanceChecker(ASTContext &ctx, NormalProtocolConformance *conformance,
210194
llvm::SetVector<ASTContext::MissingWitness> &GlobalMissingWitnesses);
211195

0 commit comments

Comments
 (0)