@@ -1966,40 +1966,77 @@ isUnsatisfiedReq(NormalProtocolConformance *conformance, ValueDecl *req,
1966
1966
return false ;
1967
1967
}
1968
1968
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
+
1969
1978
void MultiConformanceChecker::checkAllConformances () {
1970
1979
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) {
1974
1981
checkIndividualConformance (conformance);
1975
1982
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);
1981
1987
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
+ }
1988
1995
}
1989
1996
}
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
+ }
1990
2026
}
1991
- // If all missing witnesses are issued with fixits, we are done.
2027
+
2028
+ // If there were no missing witnesses, we're done.
1992
2029
if (MissingWitnesses.empty ())
1993
2030
return ;
1994
2031
1995
2032
// Otherwise, backtrack to the last checker that has missing witnesses
1996
2033
// 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 ;
2003
2040
}
2004
2041
}
2005
2042
}
@@ -3752,58 +3789,19 @@ static void diagnoseProtocolStubFixit(
3752
3789
}
3753
3790
}
3754
3791
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
+ });
3807
3805
}
3808
3806
3809
3807
// / Whether the given protocol requirement has a "Self ==" constraint.
@@ -5072,10 +5070,6 @@ void ConformanceChecker::checkConformance() {
5072
5070
// Check non-type requirements.
5073
5071
resolveValueWitnesses ();
5074
5072
5075
- // Diagnose any missing witnesses.
5076
- diagnoseMissingWitnesses (MissingWitnessDiagnosisKind::ErrorOnly,
5077
- /* Delayed=*/ false );
5078
-
5079
5073
// Except in specific hardcoded cases for Foundation/Swift
5080
5074
// standard library compatibility, an _ObjectiveCBridgeable
5081
5075
// conformance must appear in the same module as the definition of
@@ -6463,12 +6457,14 @@ Witness
6463
6457
ValueWitnessRequest::evaluate (Evaluator &eval,
6464
6458
NormalProtocolConformance *conformance,
6465
6459
ValueDecl *requirement) const {
6460
+ auto &ctx = requirement->getASTContext ();
6466
6461
llvm::SetVector<ASTContext::MissingWitness> MissingWitnesses;
6467
- ConformanceChecker checker (requirement->getASTContext (), conformance,
6468
- MissingWitnesses);
6462
+ ConformanceChecker checker (ctx, conformance, MissingWitnesses);
6469
6463
checker.resolveSingleWitness (requirement);
6470
- checker.diagnoseMissingWitnesses (MissingWitnessDiagnosisKind::ErrorOnly,
6471
- /* Delayed=*/ true );
6464
+ for (auto missing : MissingWitnesses) {
6465
+ ctx.addDelayedMissingWitness (conformance, missing);
6466
+ }
6467
+
6472
6468
// FIXME: ConformanceChecker and the other associated WitnessCheckers have
6473
6469
// an extremely convoluted caching scheme that doesn't fit nicely into the
6474
6470
// evaluator's model. All of this should be refactored away.
0 commit comments