Skip to content

Commit dba2726

Browse files
authored
Merge pull request #35593 from DougGregor/objc-async-conformance-verify
[AST Verifier] Handle ObjC requirements satisfied by alternative requirements
2 parents fb70ab4 + 83e8588 commit dba2726

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

lib/AST/ASTVerifier.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2634,6 +2634,41 @@ class Verifier : public ASTWalker {
26342634
abort();
26352635
}
26362636

2637+
// Tracking for those Objective-C requirements that have witnesses.
2638+
llvm::SmallDenseSet<std::pair<ObjCSelector, char>> hasObjCWitnessMap;
2639+
bool populatedObjCWitnesses = false;
2640+
auto populateObjCWitnesses = [&] {
2641+
if (populatedObjCWitnesses)
2642+
return;
2643+
2644+
populatedObjCWitnesses = true;
2645+
for (auto req : proto->getMembers()) {
2646+
if (auto reqFunc = dyn_cast<AbstractFunctionDecl>(req)) {
2647+
if (normal->hasWitness(reqFunc)) {
2648+
hasObjCWitnessMap.insert(
2649+
{reqFunc->getObjCSelector(), reqFunc->isInstanceMember()});
2650+
}
2651+
}
2652+
}
2653+
};
2654+
2655+
// Check whether there is a witness with the same selector and kind as
2656+
// this requirement.
2657+
auto hasObjCWitness = [&](ValueDecl *req) {
2658+
if (!proto->isObjC())
2659+
return false;
2660+
2661+
auto func = dyn_cast<AbstractFunctionDecl>(req);
2662+
if (!func)
2663+
return false;
2664+
2665+
populateObjCWitnesses();
2666+
2667+
std::pair<ObjCSelector, char> key(
2668+
func->getObjCSelector(), func->isInstanceMember());
2669+
return hasObjCWitnessMap.count(key) > 0;
2670+
};
2671+
26372672
// Check that a normal protocol conformance is complete.
26382673
for (auto member : proto->getMembers()) {
26392674
if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
@@ -2663,7 +2698,6 @@ class Verifier : public ASTWalker {
26632698
if (isa<AccessorDecl>(member))
26642699
continue;
26652700

2666-
26672701
if (auto req = dyn_cast<ValueDecl>(member)) {
26682702
if (!normal->hasWitness(req)) {
26692703
if ((req->getAttrs().isUnavailable(Ctx) ||
@@ -2672,6 +2706,10 @@ class Verifier : public ASTWalker {
26722706
continue;
26732707
}
26742708

2709+
// Check if *any* witness matches the Objective-C selector.
2710+
if (hasObjCWitness(req))
2711+
continue;
2712+
26752713
dumpRef(decl);
26762714
Out << " is missing witness for "
26772715
<< conformance->getProtocol()->getName().str()
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -I %S/Inputs/custom-modules -enable-experimental-concurrency %s -verify
2+
3+
// REQUIRES: objc_interop
4+
// REQUIRES: concurrency
5+
import Foundation
6+
import ObjCConcurrency
7+
8+
// Conform via async method
9+
class C1: ConcurrentProtocol {
10+
func askUser(toSolvePuzzle puzzle: String) async throws -> String { "" }
11+
12+
func askUser(toJumpThroughHoop hoop: String) async -> String { "hello" }
13+
}

0 commit comments

Comments
 (0)