@@ -3591,6 +3591,55 @@ filterProtocolRequirements(
3591
3591
return Filtered;
3592
3592
}
3593
3593
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
+
3594
3643
// / Prune the set of missing witnesses for the given conformance, eliminating
3595
3644
// / any requirements that do not actually need to satisfied.
3596
3645
static ArrayRef<ASTContext::MissingWitness> pruneMissingWitnesses (
@@ -4393,7 +4442,8 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
4393
4442
4394
4443
if (!numViable) {
4395
4444
// Save the missing requirement for later diagnosis.
4396
- GlobalMissingWitnesses.insert ({requirement, matches});
4445
+ if (shouldRecordMissingWitness (Proto, Conformance, requirement))
4446
+ GlobalMissingWitnesses.insert ({requirement, matches});
4397
4447
return ResolveWitnessResult::Missing;
4398
4448
}
4399
4449
0 commit comments