Skip to content

[AST Verifier] Handle ObjC requirements satisfied by alternative requirements #35593

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2620,6 +2620,41 @@ class Verifier : public ASTWalker {
abort();
}

// Tracking for those Objective-C requirements that have witnesses.
llvm::SmallDenseSet<std::pair<ObjCSelector, char>> hasObjCWitnessMap;
bool populatedObjCWitnesses = false;
auto populateObjCWitnesses = [&] {
if (populatedObjCWitnesses)
return;

populatedObjCWitnesses = true;
for (auto req : proto->getMembers()) {
if (auto reqFunc = dyn_cast<AbstractFunctionDecl>(req)) {
if (normal->hasWitness(reqFunc)) {
hasObjCWitnessMap.insert(
{reqFunc->getObjCSelector(), reqFunc->isInstanceMember()});
}
}
}
};

// Check whether there is a witness with the same selector and kind as
// this requirement.
auto hasObjCWitness = [&](ValueDecl *req) {
if (!proto->isObjC())
return false;

auto func = dyn_cast<AbstractFunctionDecl>(req);
if (!func)
return false;

populateObjCWitnesses();

std::pair<ObjCSelector, char> key(
func->getObjCSelector(), func->isInstanceMember());
return hasObjCWitnessMap.count(key) > 0;
};

// Check that a normal protocol conformance is complete.
for (auto member : proto->getMembers()) {
if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
Expand Down Expand Up @@ -2649,7 +2684,6 @@ class Verifier : public ASTWalker {
if (isa<AccessorDecl>(member))
continue;


if (auto req = dyn_cast<ValueDecl>(member)) {
if (!normal->hasWitness(req)) {
if ((req->getAttrs().isUnavailable(Ctx) ||
Expand All @@ -2658,6 +2692,10 @@ class Verifier : public ASTWalker {
continue;
}

// Check if *any* witness matches the Objective-C selector.
if (hasObjCWitness(req))
continue;

dumpRef(decl);
Out << " is missing witness for "
<< conformance->getProtocol()->getName().str()
Expand Down
13 changes: 13 additions & 0 deletions test/ClangImporter/objc_async_conformance.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -I %S/Inputs/custom-modules -enable-experimental-concurrency %s -verify

// REQUIRES: objc_interop
// REQUIRES: concurrency
import Foundation
import ObjCConcurrency

// Conform via async method
class C1: ConcurrentProtocol {
func askUser(toSolvePuzzle puzzle: String) async throws -> String { "" }

func askUser(toJumpThroughHoop hoop: String) async -> String { "hello" }
}