@@ -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+
19691978void 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
64636457ValueWitnessRequest::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.
0 commit comments