Skip to content

Commit f439275

Browse files
committed
Mark imported @completionHandlerAsync attrs as implicit
Mark imported `@completionHandlerAsync` attrs as implicit, which avoids printing them in generated interfaces. And for the sake of completion, serialize the implicit bit in case it's used elsewhere in the future. To make sure we continue to print `@completionHandlerAsync` attributes explicitly written by the user in Swift, add a SourceKit interface test. Resolves rdar://76685011
1 parent 787c1a9 commit f439275

File tree

8 files changed

+41
-8
lines changed

8 files changed

+41
-8
lines changed

include/swift/AST/Attr.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,9 +2077,10 @@ class CompletionHandlerAsyncAttr final : public DeclAttribute {
20772077
CompletionHandlerAsyncAttr(AbstractFunctionDecl &asyncFunctionDecl,
20782078
size_t completionHandlerIndex,
20792079
SourceLoc completionHandlerIndexLoc,
2080-
SourceLoc atLoc, SourceRange range)
2080+
SourceLoc atLoc, SourceRange range,
2081+
bool implicit)
20812082
: DeclAttribute(DAK_CompletionHandlerAsync, atLoc, range,
2082-
/*implicit*/ false),
2083+
implicit),
20832084
AsyncFunctionDecl(&asyncFunctionDecl) ,
20842085
CompletionHandlerIndex(completionHandlerIndex),
20852086
CompletionHandlerIndexLoc(completionHandlerIndexLoc) {}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8104,7 +8104,7 @@ void addCompletionHandlerAttribute(Decl *asyncImport,
81048104
member->getAttrs().add(
81058105
new (SwiftContext) CompletionHandlerAsyncAttr(
81068106
cast<AbstractFunctionDecl>(*asyncImport), completionIndex,
8107-
SourceLoc(), SourceLoc(), SourceRange()));
8107+
SourceLoc(), SourceLoc(), SourceRange(), /*implicit*/ true));
81088108
}
81098109
}
81108110
}

lib/Serialization/Deserialization.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4639,16 +4639,17 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() {
46394639
}
46404640

46414641
case decls_block::CompletionHandlerAsync_DECL_ATTR: {
4642+
bool isImplicit;
46424643
uint64_t handlerIndex;
46434644
uint64_t asyncFunctionDeclID;
46444645
serialization::decls_block::CompletionHandlerAsyncDeclAttrLayout::
4645-
readRecord(scratch, handlerIndex, asyncFunctionDeclID);
4646+
readRecord(scratch, isImplicit, handlerIndex, asyncFunctionDeclID);
46464647

46474648
auto mappedFunctionDecl =
46484649
cast<AbstractFunctionDecl>(MF.getDecl(asyncFunctionDeclID));
46494650
Attr = new (ctx) CompletionHandlerAsyncAttr(
46504651
*mappedFunctionDecl, handlerIndex, /*handlerIndexLoc*/ SourceLoc(),
4651-
/*atLoc*/ SourceLoc(), /*range*/ SourceRange());
4652+
/*atLoc*/ SourceLoc(), /*range*/ SourceRange(), isImplicit);
46524653
break;
46534654
}
46544655

lib/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5656
/// describe what change you made. The content of this comment isn't important;
5757
/// it just ensures a conflict if two people change the module format.
5858
/// Don't worry about adhering to the 80-column limit for this line.
59-
const uint16_t SWIFTMODULE_VERSION_MINOR = 610; // async initializers for nominal types
59+
const uint16_t SWIFTMODULE_VERSION_MINOR = 611; // implicit bit for CompletionHandlerAsyncAttr
6060

6161
/// A standard hash seed used for all string hashes in a serialized module.
6262
///
@@ -1930,6 +1930,7 @@ namespace decls_block {
19301930

19311931
using CompletionHandlerAsyncDeclAttrLayout = BCRecordLayout<
19321932
CompletionHandlerAsync_DECL_ATTR,
1933+
BCFixed<1>, // Implicit flag.
19331934
BCVBR<5>, // Completion handler index
19341935
DeclIDField // Mapped async function decl
19351936
>;

lib/Serialization/Serialization.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,8 +2633,8 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
26332633
auto asyncFuncDeclID = S.addDeclRef(attr->AsyncFunctionDecl);
26342634

26352635
CompletionHandlerAsyncDeclAttrLayout::emitRecord(
2636-
S.Out, S.ScratchRecord, abbrCode, attr->CompletionHandlerIndex,
2637-
asyncFuncDeclID);
2636+
S.Out, S.ScratchRecord, abbrCode, attr->isImplicit(),
2637+
attr->CompletionHandlerIndex, asyncFuncDeclID);
26382638
return;
26392639
}
26402640
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class ClassWithAsyncAndHandler {
2+
@completionHandlerAsync("foo(_:)", completionHandlerIndex: 1)
3+
func foo(_ operation: String, completionHandler handler: @escaping (Int) -> Void) {}
4+
func foo(_ operation: String) async -> Int { 0 }
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import Foundation;
2+
3+
@interface ClassWithHandlerMethod
4+
-(void)methodWithHandler:(NSString *)operation completionHandler:(void (^)(NSInteger))handler;
5+
@end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// REQUIRES: objc_interop
2+
// REQUIRES: concurrency
3+
4+
// RUN: %empty-directory(%t)
5+
6+
// RUN: %sourcekitd-test -req=interface-gen %S/Inputs/gen_concurrency.swift -- %S/Inputs/gen_concurrency.swift -target %target-triple -I %t -Xfrontend -enable-experimental-concurrency | %FileCheck %s --check-prefix=SWIFT-GEN-INTERFACE
7+
8+
// Make sure we print @completionHandlerAsync when it was explicitly written by the user.
9+
// SWIFT-GEN-INTERFACE-LABEL: class ClassWithAsyncAndHandler {
10+
// SWIFT-GEN-INTERFACE: @completionHandlerAsync("foo(_:)", completionHandlerIndex: 1)
11+
// SWIFT-GEN-INTERFACE-NEXT: internal func foo(_ operation: String, completionHandler handler: @escaping (Int) -> Void)
12+
// SWIFT-GEN-INTERFACE: internal func foo(_ operation: String) async -> Int
13+
14+
// RUN: %sourcekitd-test -req=interface-gen -using-swift-args -header %S/Inputs/header_concurrency.h -- %s -Xfrontend -enable-objc-interop -Xfrontend -enable-experimental-concurrency -import-objc-header %S/Inputs/header_concurrency.h -sdk %clang-importer-sdk | %FileCheck %s --check-prefix=OBJC-GEN-INTERFACE
15+
16+
// But don't print @completionHandlerAsync if it was implicitly added to an imported Clang decl (rdar://76685011).
17+
// OBJC-GEN-INTERFACE-LABEL: class ClassWithHandlerMethod {
18+
// OBJC-GEN-INTERFACE-NOT: @completionHandlerAsync
19+
// OBJC-GEN-INTERFACE: func method(withHandler operation: String!, completionHandler handler: ((Int) -> Void)!)
20+
// OBJC-GEN-INTERFACE: func method(withHandler operation: String!) async -> Int

0 commit comments

Comments
 (0)