Skip to content

Commit 0004a4b

Browse files
committed
[NameLookup] Shadowing: strip @Sendable annotations for declarations ObjC/@objc declarations
When `SendableCompletionHandlers` feature is enabled, ClangImporter is going to inject `@Sendable` attribute into the completion handler parameter's function type. We need to make sure that his new behavior doesn't break shadowing rules and allow APIs to annotate their ObjC declarations with `@Sendable` without breaking clients.
1 parent d14635b commit 0004a4b

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

lib/AST/NameLookup.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,20 @@ static void recordShadowedDeclsAfterSignatureMatch(
826826
else
827827
type = removeThrownError(decl->getInterfaceType()->getCanonicalType());
828828

829+
// Strip `@Sendable` annotations for declarations that come from
830+
// or are exposed to Objective-C to make it possible to introduce
831+
// new annotations without breaking shadowing rules.
832+
//
833+
// This is a narrow fix for specific backwards-incompatible cases
834+
// we know about, it could be extended to use `isObjC()` in the
835+
// future if we find problematic cases were a more general change
836+
// is required.
837+
if (decl->hasClangNode() || decl->getAttrs().hasAttribute<ObjCAttr>()) {
838+
type =
839+
type->stripConcurrency(/*recursive=*/true, /*dropGlobalActor=*/false)
840+
->getCanonicalType();
841+
}
842+
829843
// Record this declaration based on its signature.
830844
auto &known = collisions[type];
831845
if (known.size() == 1) {

test/Concurrency/sendable_objc_attr_in_type_context_swift5.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ void doSomethingConcurrently(__attribute__((noescape)) void SWIFT_SENDABLE (^blo
6969
-(void)computeWithCompletionHandler: (void (^)(void)) handler;
7070
@end
7171

72+
@interface Shadowing : NSObject
73+
-(void)computeWithCompletion: (void (^)(void)) completion;
74+
-(void)updateWithCompletionHandler: (void (^_Nullable)(void)) handler;
75+
@end
76+
7277
#pragma clang assume_nonnull end
7378

7479
//--- main.swift
@@ -158,3 +163,16 @@ class TestConformanceWithoutStripping : InnerSendableTypes {
158163
@objc func compute(completionHandler: @escaping () -> Void) {}
159164
// expected-warning@-1 {{sendability of function types in instance method 'compute(completionHandler:)' of type '(@escaping () -> Void) -> ()' does not match type '(@escaping @Sendable () -> Void) -> Void' declared by the header}}
160165
}
166+
167+
// Methods deliberately has no `@Sendable` to make sure that
168+
// shadowing rules are preserved when SendableCompletionHandlers feature is enabled.
169+
@objc extension Shadowing {
170+
@objc func compute(completion: @escaping () -> Void) {}
171+
172+
@objc func update(completionHandler: (() -> Void)? = nil) {}
173+
174+
func testCompute() {
175+
self.compute { } // Ok - no ambiguity
176+
self.update { } // Ok - no ambiguity
177+
}
178+
}

test/Concurrency/sendable_objc_attr_in_type_context_swift6.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ void doSomethingConcurrently(__attribute__((noescape)) void SWIFT_SENDABLE (^blo
6969
-(void)computeWithCompletionHandler: (void (^)(void)) handler;
7070
@end
7171

72+
@interface Shadowing : NSObject
73+
-(void)computeWithCompletion: (void (^)(void)) completion;
74+
-(void)updateWithCompletionHandler: (void (^_Nullable)(void)) handler;
75+
@end
76+
7277
#pragma clang assume_nonnull end
7378

7479
//--- main.swift
@@ -165,3 +170,16 @@ class TestConformanceWithoutStripping : InnerSendableTypes {
165170
@objc func compute(completionHandler: @escaping () -> Void) {}
166171
// expected-warning@-1 {{sendability of function types in instance method 'compute(completionHandler:)' of type '(@escaping () -> Void) -> ()' does not match type '(@escaping @Sendable () -> Void) -> Void' declared by the header}}
167172
}
173+
174+
// Methods deliberately has no `@Sendable` to make sure that
175+
// shadowing rules are preserved when SendableCompletionHandlers feature is enabled.
176+
@objc extension Shadowing {
177+
@objc func compute(completion: @escaping () -> Void) {}
178+
179+
@objc func update(completionHandler: (() -> Void)? = nil) {}
180+
181+
func testCompute() {
182+
self.compute { } // Ok - no ambiguity
183+
self.update { } // Ok - no ambiguity
184+
}
185+
}

0 commit comments

Comments
 (0)