3636#include " swift/Basic/Statistic.h"
3737#include " swift/ClangImporter/ClangImporterRequests.h"
3838#include " swift/Parse/Lexer.h"
39+ #include " swift/Strings.h"
3940#include " clang/AST/DeclObjC.h"
4041#include " clang/Basic/Specifiers.h"
4142#include " llvm/ADT/DenseMap.h"
@@ -1716,14 +1717,34 @@ NominalTypeDecl::lookupDirect(ObjCSelector selector, bool isInstance) {
17161717 return stored.Methods ;
17171718}
17181719
1719- // / Is the new method an async alternative of any existing method, or vice
1720- // / versa?
1721- static bool isAnAsyncAlternative (AbstractFunctionDecl *newDecl,
1722- llvm::TinyPtrVector<AbstractFunctionDecl *> &vec) {
1723- return llvm::any_of (vec, [&](AbstractFunctionDecl *oldDecl) {
1720+ // / If there is an apparent conflict between \p newDecl and one of the methods
1721+ // / in \p vec, should we diagnose it?
1722+ static bool
1723+ shouldDiagnoseConflict (NominalTypeDecl *ty, AbstractFunctionDecl *newDecl,
1724+ llvm::TinyPtrVector<AbstractFunctionDecl *> &vec) {
1725+ // Are all conflicting methods imported from ObjC and in our ObjC half or a
1726+ // bridging header? Some code bases implement ObjC methods in Swift even
1727+ // though it's not exactly supported.
1728+ auto newDeclModuleName = newDecl->getModuleContext ()->getName ();
1729+ if (llvm::all_of (vec, [&](AbstractFunctionDecl *oldDecl) {
1730+ if (!oldDecl->hasClangNode ())
1731+ return false ;
1732+ auto oldDeclModuleName = oldDecl->getModuleContext ()->getName ();
1733+ return oldDeclModuleName == newDeclModuleName
1734+ || oldDeclModuleName.str () == CLANG_HEADER_MODULE_NAME;
1735+ }))
1736+ return false ;
1737+
1738+ // If we're looking at protocol requirements, is the new method an async
1739+ // alternative of any existing method, or vice versa?
1740+ if (isa<ProtocolDecl>(ty) &&
1741+ llvm::any_of (vec, [&](AbstractFunctionDecl *oldDecl) {
17241742 return newDecl->getAsyncAlternative (/* isKnownObjC=*/ true ) == oldDecl
17251743 || oldDecl->getAsyncAlternative (/* isKnownObjC=*/ true ) == newDecl;
1726- });
1744+ }))
1745+ return false ;
1746+
1747+ return true ;
17271748}
17281749
17291750void NominalTypeDecl::recordObjCMethod (AbstractFunctionDecl *method,
@@ -1743,7 +1764,7 @@ void NominalTypeDecl::recordObjCMethod(AbstractFunctionDecl *method,
17431764 if (auto *sf = method->getParentSourceFile ()) {
17441765 if (vec.empty ()) {
17451766 sf->ObjCMethodList .push_back (method);
1746- } else if (!isa<ProtocolDecl> (this ) || ! isAnAsyncAlternative ( method, vec)) {
1767+ } else if (shouldDiagnoseConflict (this , method, vec)) {
17471768 // We have a conflict.
17481769 sf->ObjCMethodConflicts .insert ({ this , selector, isInstanceMethod });
17491770 }
0 commit comments