Skip to content

Commit d4ee34c

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 dcb1d66 commit d4ee34c

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2017,12 +2017,31 @@ auto DeclAndTypePrinter::getImpl() -> Implementation {
20172017
return Implementation(os, *this, outputLang);
20182018
}
20192019

2020+
static bool isAsyncAlternativeOfOtherDecl(const ValueDecl *VD) {
2021+
auto AFD = dyn_cast<AbstractFunctionDecl>(VD);
2022+
if (!AFD || !AFD->isAsyncContext() || !AFD->getObjCSelector())
2023+
return false;
2024+
2025+
auto type = AFD->getDeclContext()->getSelfNominalTypeDecl();
2026+
if (!type)
2027+
return false;
2028+
auto others = type->lookupDirect(AFD->getObjCSelector(),
2029+
AFD->isInstanceMember());
2030+
2031+
for (auto other : others)
2032+
if (other->getAsyncAlternative() == AFD)
2033+
return true;
2034+
2035+
return false;
2036+
}
2037+
20202038
bool DeclAndTypePrinter::shouldInclude(const ValueDecl *VD) {
20212039
return !VD->isInvalid() &&
20222040
(outputLang == OutputLanguageMode::Cxx
20232041
? cxx_translation::isVisibleToCxx(VD, minRequiredAccess)
20242042
: isVisibleToObjC(VD, minRequiredAccess)) &&
2025-
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>();
2043+
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>() &&
2044+
!isAsyncAlternativeOfOtherDecl(VD);
20262045
}
20272046

20282047
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)