Skip to content

Commit f28fbfb

Browse files
committed
Don’t declare async methods with alternatives in headers
If Swift sees this pattern of methods in an @objc protocol: ``` func hello() async -> Int @available(*, renamed: “hello()”) func hello(completion: @escaping (Int) -> Void) ``` Then PrintAsClang will print only the completion-handler-based method, not the async one, into a generated header, on the assumption that the completion-handler method may have greater availability. Fixes rdar://94175167.
1 parent 7a29897 commit f28fbfb

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2026,12 +2026,29 @@ auto DeclAndTypePrinter::getImpl() -> Implementation {
20262026
return Implementation(os, *this, outputLang);
20272027
}
20282028

2029+
static bool isAsyncAlternativeOfOtherDecl(const ValueDecl *VD) {
2030+
auto AFD = dyn_cast<AbstractFunctionDecl>(VD);
2031+
if (!AFD || !AFD->isAsyncContext() || !AFD->getObjCSelector())
2032+
return false;
2033+
2034+
auto type = AFD->getDeclContext()->getSelfNominalTypeDecl();
2035+
auto others = type->lookupDirect(AFD->getObjCSelector(),
2036+
AFD->isInstanceMember());
2037+
2038+
for (auto other : others)
2039+
if (other->getAsyncAlternative() == AFD)
2040+
return true;
2041+
2042+
return false;
2043+
}
2044+
20292045
bool DeclAndTypePrinter::shouldInclude(const ValueDecl *VD) {
20302046
return !VD->isInvalid() &&
20312047
(outputLang == OutputLanguageMode::Cxx
20322048
? cxx_translation::isVisibleToCxx(VD, minRequiredAccess)
20332049
: isVisibleToObjC(VD, minRequiredAccess)) &&
2034-
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>();
2050+
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>() &&
2051+
!isAsyncAlternativeOfOtherDecl(VD);
20352052
}
20362053

20372054
void DeclAndTypePrinter::print(const Decl *D) {

test/PrintAsObjC/protocols.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@ import objc_generics
2727
// CHECK-NEXT: @end
2828
@objc protocol B : A {}
2929

30+
// CHECK-LABEL: @protocol CompletionAndAsync
31+
// CHECK-NEXT: - (void)helloWithCompletion:(void (^ _Nonnull)(BOOL))completion;
32+
// CHECK-NEXT: @end
33+
@objc protocol CompletionAndAsync {
34+
// We don't want this one printed because it has more limited availability.
35+
@available(SwiftStdlib 5.7, *)
36+
@objc(helloWithCompletion:)
37+
func hello() async -> Bool
38+
39+
@available(*, renamed: "hello()")
40+
@objc(helloWithCompletion:)
41+
func hello(completion: @escaping (Bool) -> Void)
42+
}
43+
3044
// CHECK: @protocol CustomName2;
3145
// CHECK-LABEL: SWIFT_PROTOCOL_NAMED("CustomName")
3246
// CHECK-NEXT: @protocol CustomName{{$}}

0 commit comments

Comments
 (0)