Skip to content

Commit aa1c79d

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 a58ab77 commit aa1c79d

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

lib/AST/NameLookup.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,15 @@ 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+
if (decl->hasClangNode() || decl->getAttrs().hasAttribute<ObjCAttr>()) {
833+
type =
834+
type->stripConcurrency(/*recursive=*/true, /*dropGlobalActor=*/false)
835+
->getCanonicalType();
836+
}
837+
829838
// Record this declaration based on its signature.
830839
auto &known = collisions[type];
831840
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
@@ -68,6 +68,11 @@ void doSomethingConcurrently(__attribute__((noescape)) void SWIFT_SENDABLE (^blo
6868
-(void)computeWithCompletionHandler: (void (^)(void)) handler;
6969
@end
7070

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

7378
//--- main.swift
@@ -154,3 +159,16 @@ class TestConformanceWithoutStripping : InnerSendableTypes {
154159
@objc func compute(completionHandler: @escaping () -> Void) {}
155160
// 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}}
156161
}
162+
163+
// Methods deliberately has no `@Sendable` to make sure that
164+
// shadowing rules are preserved when SendableCompletionHandlers feature is enabled.
165+
@objc extension Shadowing {
166+
@objc func compute(completion: @escaping () -> Void) {}
167+
168+
@objc func update(completionHandler: (() -> Void)? = nil) {}
169+
170+
func testCompute() {
171+
self.compute { } // Ok - no ambiguity
172+
self.update { } // Ok - no ambiguity
173+
}
174+
}

test/Concurrency/sendable_objc_attr_in_type_context_swift6.swift

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

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

7378
//--- main.swift
@@ -161,3 +166,16 @@ class TestConformanceWithoutStripping : InnerSendableTypes {
161166
@objc func compute(completionHandler: @escaping () -> Void) {}
162167
// 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}}
163168
}
169+
170+
// Methods deliberately has no `@Sendable` to make sure that
171+
// shadowing rules are preserved when SendableCompletionHandlers feature is enabled.
172+
@objc extension Shadowing {
173+
@objc func compute(completion: @escaping () -> Void) {}
174+
175+
@objc func update(completionHandler: (() -> Void)? = nil) {}
176+
177+
func testCompute() {
178+
self.compute { } // Ok - no ambiguity
179+
self.update { } // Ok - no ambiguity
180+
}
181+
}

0 commit comments

Comments
 (0)