Skip to content

Commit 25c366d

Browse files
authored
Merge pull request #37170 from hamishknight/take-two
Mark imported @completionHandlerAsync attrs as implicit
2 parents 106002c + fe3dbc2 commit 25c366d

File tree

12 files changed

+83
-34
lines changed

12 files changed

+83
-34
lines changed

include/swift/AST/Attr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ SIMPLE_DECL_ATTR(reasync, AtReasync,
625625
110)
626626

627627
DECL_ATTR(completionHandlerAsync, CompletionHandlerAsync,
628-
OnAbstractFunction | ConcurrencyOnly | LongAttribute | UserInaccessible |
628+
OnAbstractFunction | ConcurrencyOnly | LongAttribute |
629629
ABIStableToAdd | ABIStableToRemove |
630630
APIStableToAdd | APIStableToRemove,
631631
111)

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/AST/Attr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
10971097
} else {
10981098
Printer << attr->AsyncFunctionName;
10991099
}
1100-
Printer << "\", completionHandleIndex: " <<
1100+
Printer << "\", completionHandlerIndex: " <<
11011101
attr->CompletionHandlerIndex << ')';
11021102
break;
11031103
}

lib/ClangImporter/ImportDecl.cpp

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

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
}

test/IDE/print_clang_objc_async.swift

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -print-module -source-filename %s -module-to-print=ObjCConcurrency -function-definitions=false -enable-experimental-concurrency > %t/ObjCConcurrency.printed.txt
3+
// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -print-module -print-implicit-attrs -source-filename %s -module-to-print=ObjCConcurrency -function-definitions=false -enable-experimental-concurrency > %t/ObjCConcurrency.printed.txt
44
// RUN: %FileCheck -input-file %t/ObjCConcurrency.printed.txt %s
55

66
// REQUIRES: objc_interop
@@ -9,64 +9,78 @@ import _Concurrency
99

1010
// CHECK-LABEL: class SlowServer : NSObject, ServiceProvider {
1111

12-
// CHECK: @completionHandlerAsync("doSomethingSlow(_:)", completionHandleIndex: 1)
12+
// CHECK: @completionHandlerAsync("doSomethingSlow(_:)", completionHandlerIndex: 1)
1313
// CHECK-NEXT: func doSomethingSlow(_ operation: String, completionHandler handler: @escaping (Int) -> Void)
14+
// CHECK-NEXT: @discardableResult
1415
// CHECK-NEXT: func doSomethingSlow(_ operation: String) async -> Int
1516

16-
// CHECK: @completionHandlerAsync("doSomethingDangerous(_:)", completionHandleIndex: 1)
17+
// CHECK: @completionHandlerAsync("doSomethingDangerous(_:)", completionHandlerIndex: 1)
1718
// CHECK-NEXT: func doSomethingDangerous(_ operation: String, completionHandler handler: ((String?, Error?) -> Void)? = nil)
19+
// CHECK-NEXT: @discardableResult
1820
// CHECK-NEXT: func doSomethingDangerous(_ operation: String) async throws -> String
1921

20-
// CHECK: @completionHandlerAsync("checkAvailability()", completionHandleIndex: 0)
22+
// CHECK: @completionHandlerAsync("checkAvailability()", completionHandlerIndex: 0)
2123
// CHECK-NEXT: func checkAvailability(completionHandler: @escaping (Bool) -> Void)
24+
// CHECK-NEXT: @discardableResult
2225
// CHECK-NEXT: func checkAvailability() async -> Bool
2326

24-
// CHECK: @completionHandlerAsync("anotherExample()", completionHandleIndex: 0)
27+
// CHECK: @completionHandlerAsync("anotherExample()", completionHandlerIndex: 0)
2528
// CHECK-NEXT: func anotherExample(completionBlock block: @escaping (String) -> Void)
29+
// CHECK-NEXT: @discardableResult
2630
// CHECK-NEXT: func anotherExample() async -> String
2731

28-
// CHECK: @completionHandlerAsync("finalExample()", completionHandleIndex: 0)
32+
// CHECK: @completionHandlerAsync("finalExample()", completionHandlerIndex: 0)
2933
// CHECK-NEXT: func finalExampleWithReply(to block: @escaping (String) -> Void)
34+
// CHECK-NEXT: @discardableResult
3035
// CHECK-NEXT: func finalExample() async -> String
3136

32-
// CHECK: @completionHandlerAsync("replyingOperation(_:)", completionHandleIndex: 1)
37+
// CHECK: @completionHandlerAsync("replyingOperation(_:)", completionHandlerIndex: 1)
3338
// CHECK-NEXT: func replyingOperation(_ operation: String, replyTo block: @escaping (String) -> Void)
39+
// CHECK-NEXT: @discardableResult
3440
// CHECK-NEXT: func replyingOperation(_ operation: String) async -> String
3541

36-
// CHECK: @completionHandlerAsync("findAnswer()", completionHandleIndex: 0)
42+
// CHECK: @completionHandlerAsync("findAnswer()", completionHandlerIndex: 0)
3743
// CHECK-NEXT: func findAnswer(completionHandler handler: @escaping (String?, Error?) -> Void)
44+
// CHECK-NEXT: @discardableResult
3845
// CHECK-NEXT: func findAnswer() async throws -> String
3946

40-
// CHECK: @completionHandlerAsync("findAnswerFailingly()", completionHandleIndex: 0)
47+
// CHECK: @completionHandlerAsync("findAnswerFailingly()", completionHandlerIndex: 0)
4148
// CHECK-NEXT: func findAnswerFailingly(completionHandler handler: @escaping (String?, Error?) -> Void) throws
49+
// CHECK-NEXT: @discardableResult
4250
// CHECK-NEXT: func findAnswerFailingly() async throws -> String
4351

44-
// CHECK: @completionHandlerAsync("findQAndA()", completionHandleIndex: 0)
52+
// CHECK: @completionHandlerAsync("findQAndA()", completionHandlerIndex: 0)
4553
// CHECK-NEXT: func findQAndA(completionHandler handler: @escaping (String?, String?, Error?) -> Void)
54+
// CHECK-NEXT: @discardableResult
4655
// CHECK-NEXT: func findQAndA() async throws -> (String?, String)
4756

48-
// CHECK: @completionHandlerAsync("findQuestionableAnswers()", completionHandleIndex: 0)
57+
// CHECK: @completionHandlerAsync("findQuestionableAnswers()", completionHandlerIndex: 0)
4958
// CHECK-NEXT: func findQuestionableAnswers(completionHandler handler: @escaping CompletionHandler)
59+
// CHECK-NEXT: @discardableResult
5060
// CHECK-NEXT: func findQuestionableAnswers() async throws -> (String, String?)
5161

52-
// CHECK: @completionHandlerAsync("doSomethingFun(_:)", completionHandleIndex: 1)
62+
// CHECK: @completionHandlerAsync("doSomethingFun(_:)", completionHandlerIndex: 1)
5363
// CHECK-NEXT: func doSomethingFun(_ operation: String, then completionHandler: @escaping () -> Void)
5464
// CHECK-NEXT: func doSomethingFun(_ operation: String) async
5565

56-
// CHECK: @completionHandlerAsync("doSomethingConflicted(_:)", completionHandleIndex: 1)
66+
// CHECK: @completionHandlerAsync("doSomethingConflicted(_:)", completionHandlerIndex: 1)
5767
// CHECK-NEXT: func doSomethingConflicted(_ operation: String, completionHandler handler: @escaping (Int) -> Void)
68+
// CHECK-NEXT: @discardableResult
5869
// CHECK-NEXT: func doSomethingConflicted(_ operation: String) async -> Int
70+
// CHECK-NEXT: @discardableResult
5971
// CHECK-NEXT: func doSomethingConflicted(_ operation: String) -> Int
6072

6173
// CHECK: func dance(_ step: String) async -> String
6274
// CHECK: func __leap(_ height: Int) async -> String
6375

64-
// CHECK: @completionHandlerAsync("runOnMainThread()", completionHandleIndex: 0)
76+
// CHECK: @completionHandlerAsync("runOnMainThread()", completionHandlerIndex: 0)
6577
// CHECK-NEXT: func runOnMainThread(completionHandler completion: (@MainActor (String) -> Void)? = nil)
78+
// CHECK-NEXT: @discardableResult
6679
// CHECK-NEXT: func runOnMainThread() async -> String
6780

68-
// CHECK: @completionHandlerAsync("asyncImportSame(_:)", completionHandleIndex: 1)
81+
// CHECK: @completionHandlerAsync("asyncImportSame(_:)", completionHandlerIndex: 1)
6982
// CHECK-NEXT: func asyncImportSame(_ operation: String, completionHandler handler: @escaping (Int) -> Void)
83+
// CHECK-NEXT: @discardableResult
7084
// CHECK-NEXT: func asyncImportSame(_ operation: String) async -> Int
7185
// CHECK-NEXT: func asyncImportSame(_ operation: String, replyTo handler: @escaping (Int) -> Void)
7286
// CHECK-NOT: func asyncImportSame(_ operation: String) async -> Int
@@ -76,20 +90,21 @@ import _Concurrency
7690
// CHECK-LABEL: protocol RefrigeratorDelegate
7791
// CHECK-NEXT: func someoneDidOpenRefrigerator(_ fridge: Any)
7892
// CHECK-NEXT: func refrigerator(_ fridge: Any, didGetFilledWithItems items: [Any])
79-
// CHECK-NEXT: {{^}} func refrigerator(_ fridge: Any, didGetFilledWithIntegers items: UnsafeMutablePointer<Int>, count: Int)
80-
// CHECK-NEXT: {{^}} func refrigerator(_ fridge: Any, willAddItem item: Any)
81-
// CHECK-NEXT: {{^}} func refrigerator(_ fridge: Any, didRemoveItem item: Any) -> Bool
93+
// CHECK-NEXT: {{^}} @objc func refrigerator(_ fridge: Any, didGetFilledWithIntegers items: UnsafeMutablePointer<Int>, count: Int)
94+
// CHECK-NEXT: {{^}} @objc func refrigerator(_ fridge: Any, willAddItem item: Any)
95+
// CHECK-NEXT: @discardableResult
96+
// CHECK-NEXT: {{^}} @objc func refrigerator(_ fridge: Any, didRemoveItem item: Any) -> Bool
8297
// CHECK-NEXT: {{^[}]$}}
8398

8499
// CHECK-LABEL: protocol ProtocolWithSwiftAttributes {
85100
// CHECK-NEXT: @actorIndependent func independentMethod()
86101
// CHECK-NEXT: func asyncHandlerMethod()
87-
// CHECK-NEXT: {{^}} @MainActor func mainActorMethod()
88-
// CHECK-NEXT: {{^}} @MainActor func uiActorMethod()
89-
// CHECK-NEXT: {{^}} optional func missingAtAttributeMethod()
102+
// CHECK-NEXT: {{^}} @objc @MainActor func mainActorMethod()
103+
// CHECK-NEXT: {{^}} @objc @MainActor func uiActorMethod()
104+
// CHECK-NEXT: {{^}} @objc optional func missingAtAttributeMethod()
90105
// CHECK-NEXT: {{^[}]$}}
91106

92-
// CHECK: {{^}}var MAGIC_NUMBER: Int32 { get }
107+
// CHECK: {{^}}@actorIndependent(unsafe) var MAGIC_NUMBER: Int32 { get }
93108

94109
// CHECK: func doSomethingConcurrently(_ block: @Sendable () -> Void)
95110

test/IDE/print_clang_objc_effectful_properties.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -print-module -source-filename %s -module-to-print=EffectfulProperties -function-definitions=false -enable-experimental-concurrency > %t/EffectfulProperties.printed.txt
3+
// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -print-module -print-implicit-attrs -source-filename %s -module-to-print=EffectfulProperties -function-definitions=false -enable-experimental-concurrency > %t/EffectfulProperties.printed.txt
44
// RUN: %FileCheck -input-file %t/EffectfulProperties.printed.txt %s
55

66
// REQUIRES: objc_interop
@@ -29,8 +29,9 @@
2929
// CHECK: func getMainDog(_ completion: @escaping @MainActor (String) -> Void)
3030
// CHECK-NEXT: var mainDogProp: String { get async }
3131

32-
// CHECK: @completionHandlerAsync("regularMainDog()", completionHandleIndex: 0)
32+
// CHECK: @completionHandlerAsync("regularMainDog()", completionHandlerIndex: 0)
3333
// CHECK-NEXT: func regularMainDog(_ completion: @escaping @MainActor (String) -> Void)
34+
// CHECK-NEXT: @discardableResult
3435
// CHECK-NEXT: func regularMainDog() async -> String
3536
// CHECK: }
3637

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)