@@ -3591,6 +3591,55 @@ filterProtocolRequirements(
35913591 return Filtered;
35923592}
35933593
3594+ // / Sometimes a witness isn't really diagnosed as missing if we have two
3595+ // / complementary Objective-C protocol requirements, only one of which must
3596+ // / be witnessed.
3597+ static bool shouldRecordMissingWitness (
3598+ ProtocolDecl *proto,
3599+ NormalProtocolConformance *conformance,
3600+ ValueDecl *requirement) {
3601+ assert (proto == requirement->getDeclContext ());
3602+ assert (proto == conformance->getProtocol ());
3603+
3604+ // We only care about functions.
3605+ auto fnRequirement = dyn_cast<AbstractFunctionDecl>(requirement);
3606+ if (fnRequirement == nullptr )
3607+ return true ;
3608+
3609+ if (!proto->isObjC ())
3610+ return true ;
3611+
3612+ auto map = getObjCRequirementMap (proto);
3613+
3614+ if (getObjCRequirementSibling (
3615+ proto, fnRequirement, map,
3616+ [proto, conformance](AbstractFunctionDecl *candidate) {
3617+ // FIXME: This performs a recursive lookup in the lazy case, so
3618+ // we have to dodge the cycle.
3619+ auto &ctx = proto->getASTContext ();
3620+
3621+ // If we've already resolved the sibling candidate to a valid
3622+ // witness, don't record a missing witness.
3623+ if (conformance->getWitnessUncached (candidate))
3624+ return true ;
3625+
3626+ // If we're currently resolving the sibling candidate, it may
3627+ // be that the sibling is missing also, so we must record a
3628+ // missing witness.
3629+ if (ctx.evaluator .hasActiveRequest (
3630+ ValueWitnessRequest{conformance, candidate}))
3631+ return false ;
3632+
3633+ // Otherwise, resolve the sibling cadidate; if its valid, don't
3634+ // record a missing witness.
3635+ return static_cast <bool >(conformance->getWitness (candidate));
3636+ })) {
3637+ return false ;
3638+ }
3639+
3640+ return true ;
3641+ }
3642+
35943643// / Prune the set of missing witnesses for the given conformance, eliminating
35953644// / any requirements that do not actually need to satisfied.
35963645static ArrayRef<ASTContext::MissingWitness> pruneMissingWitnesses (
@@ -4393,7 +4442,8 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
43934442
43944443 if (!numViable) {
43954444 // Save the missing requirement for later diagnosis.
4396- GlobalMissingWitnesses.insert ({requirement, matches});
4445+ if (shouldRecordMissingWitness (Proto, Conformance, requirement))
4446+ GlobalMissingWitnesses.insert ({requirement, matches});
43974447 return ResolveWitnessResult::Missing;
43984448 }
43994449
0 commit comments