Skip to content

Commit 3032add

Browse files
committed
[Sema] Allow associated type inference to skip @Sendable on ObjC witnesses
Witness checking itself is allowed to skip `@Sendable` mismatch in this situation. This is a narrow fix for `SendableCompletionHandlers` feature to make sure that the behavior doesn't change for non-ObjC witnesses
1 parent ffbbfb7 commit 3032add

4 files changed

+51
-1
lines changed

include/swift/AST/TypeMatcher.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,8 @@ class TypeMatcher {
375375
if (firstFunc->isNoEscape() != secondFunc->isNoEscape())
376376
return mismatch(firstFunc.getPointer(), secondFunc, sugaredFirstType);
377377

378-
if (firstFunc->isSendable() != secondFunc->isSendable())
378+
if (!Matcher.asDerived().allowSendableFunctionMismatch() &&
379+
firstFunc->isSendable() != secondFunc->isSendable())
379380
return mismatch(firstFunc.getPointer(), secondFunc, sugaredFirstType);
380381

381382
auto sugaredFirstFunc = sugaredFirstType->castTo<AnyFunctionType>();
@@ -554,6 +555,8 @@ class TypeMatcher {
554555

555556
bool alwaysMismatchTypeParameters() const { return false; }
556557

558+
bool allowSendableFunctionMismatch() const { return false; }
559+
557560
void pushPosition(Position pos) {}
558561
void popPosition(Position pos) {}
559562

lib/Sema/AssociatedTypeInference.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -2269,6 +2269,25 @@ AssociatedTypeInference::getPotentialTypeWitnessesByMatchingTypes(ValueDecl *req
22692269
return true;
22702270
}
22712271

2272+
bool allowSendableFunctionMismatch() const {
2273+
// Allow mismatches on `@Sendable` only if the witness comes
2274+
// from ObjC as a very narrow fix to avoid introducing new
2275+
// ambiguities like this:
2276+
//
2277+
// protocol P {
2278+
// associatedtype T
2279+
// func test(_: (T) -> Void)
2280+
// }
2281+
//
2282+
// struct S : P {
2283+
// func test(_: @Sendable (Int) -> Void) {}
2284+
// func test(_: (Int) -> Void) {}
2285+
// }
2286+
//
2287+
// Currently, there is only one binding for `T` - `Int`.
2288+
return Inferred.Witness && Inferred.Witness->hasClangNode();
2289+
}
2290+
22722291
bool mismatch(GenericTypeParamType *selfParamType,
22732292
TypeBase *secondType, Type sugaredFirstType) {
22742293
if (selfParamType->isEqual(Conformance->getProtocol()->getSelfInterfaceType())) {

test/Concurrency/sendable_objc_attr_in_type_context_swift5.swift

+14
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ void doSomethingConcurrently(__attribute__((noescape)) void SWIFT_SENDABLE (^blo
7878
-(void)willSendDataWithCompletion: (void (^)(void)) completion;
7979
@end
8080

81+
@interface DataHandler : NSObject
82+
+(void)sendDataWithCompletion: (void (^)(MyValue *)) completion;
83+
@end
84+
8185
#pragma clang assume_nonnull end
8286

8387
//--- main.swift
@@ -189,3 +193,13 @@ class ImplicitShadowing : NSObject, TestWitnesses {
189193
(self as AnyObject).willSendData { } // Ok
190194
}
191195
}
196+
197+
protocol CompletionWithoutSendable {
198+
associatedtype T
199+
static func sendData(completion: @escaping (T) -> Void) // expected-note {{expected sendability to match requirement here}}
200+
}
201+
202+
extension DataHandler : CompletionWithoutSendable {
203+
// expected-warning@-1 {{sendability of function types in class method 'sendData(completion:)' does not match requirement in protocol 'CompletionWithoutSendable'}}
204+
// It should be possible to infer `T` from method that mismatches on @Sendable in Swift 5 mode
205+
}

test/Concurrency/sendable_objc_attr_in_type_context_swift6.swift

+14
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ void doSomethingConcurrently(__attribute__((noescape)) void SWIFT_SENDABLE (^blo
7878
-(void)willSendDataWithCompletion: (void (^)(void)) completion;
7979
@end
8080

81+
@interface DataHandler : NSObject
82+
+(void)sendDataWithCompletion: (void (^)(MyValue *)) completion;
83+
@end
84+
8185
#pragma clang assume_nonnull end
8286

8387
//--- main.swift
@@ -196,3 +200,13 @@ class ImplicitShadowing : NSObject, TestWitnesses {
196200
(self as AnyObject).willSendData { } // Ok
197201
}
198202
}
203+
204+
protocol CompletionWithoutSendable {
205+
associatedtype T
206+
static func sendData(completion: @escaping (T) -> Void) // expected-note {{expected sendability to match requirement here}}
207+
}
208+
209+
extension DataHandler : CompletionWithoutSendable {
210+
// expected-error@-1 {{sendability of function types in class method 'sendData(completion:)' does not match requirement in protocol 'CompletionWithoutSendable'}}
211+
// It should be possible to infer `T` from method that mismatches on @Sendable in Swift 5 mode
212+
}

0 commit comments

Comments
 (0)