Skip to content

Commit d7709a1

Browse files
authored
Merge pull request swiftlang#63471 from DougGregor/dispatch-queue-fix-sync-inference
2 parents a8bea1e + f72d721 commit d7709a1

File tree

3 files changed

+34
-10
lines changed

3 files changed

+34
-10
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4767,14 +4767,15 @@ static Type applyUnsafeConcurrencyToParameterType(
47674767

47684768
/// Determine whether the given name is that of a DispatchQueue operation that
47694769
/// takes a closure to be executed on the queue.
4770-
bool swift::isDispatchQueueOperationName(StringRef name) {
4771-
return llvm::StringSwitch<bool>(name)
4772-
.Case("sync", true)
4773-
.Case("async", true)
4774-
.Case("asyncAndWait", true)
4775-
.Case("asyncAfter", true)
4776-
.Case("concurrentPerform", true)
4777-
.Default(false);
4770+
Optional<DispatchQueueOperation>
4771+
swift::isDispatchQueueOperationName(StringRef name) {
4772+
return llvm::StringSwitch<Optional<DispatchQueueOperation>>(name)
4773+
.Case("sync", DispatchQueueOperation::Normal)
4774+
.Case("async", DispatchQueueOperation::Sendable)
4775+
.Case("asyncAndWait", DispatchQueueOperation::Normal)
4776+
.Case("asyncAfter", DispatchQueueOperation::Sendable)
4777+
.Case("concurrentPerform", DispatchQueueOperation::Sendable)
4778+
.Default(None);
47784779
}
47794780

47804781
/// Determine whether this function is implicitly known to have its
@@ -4792,7 +4793,17 @@ static bool hasKnownUnsafeSendableFunctionParams(AbstractFunctionDecl *func) {
47924793
auto nominalName = nominal->getName().str();
47934794
if (nominalName == "DispatchQueue") {
47944795
auto name = func->getBaseName().userFacingName();
4795-
return isDispatchQueueOperationName(name);
4796+
auto operation = isDispatchQueueOperationName(name);
4797+
if (!operation)
4798+
return false;
4799+
4800+
switch (*operation) {
4801+
case DispatchQueueOperation::Normal:
4802+
return false;
4803+
4804+
case DispatchQueueOperation::Sendable:
4805+
return true;
4806+
}
47964807
}
47974808

47984809
return false;

lib/Sema/TypeCheckConcurrency.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,17 @@ AnyFunctionType *adjustFunctionTypeForConcurrency(
427427
llvm::function_ref<bool(const ClosureExpr *)> isolatedByPreconcurrency,
428428
llvm::function_ref<Type(Type)> openType);
429429

430+
/// Classifies known dispatch queue operations.
431+
enum class DispatchQueueOperation {
432+
/// This is a dispatch operation we know about.
433+
Normal,
434+
/// The closure passed to this dispatch queue operation should be Sendable.
435+
Sendable,
436+
};
437+
430438
/// Determine whether the given name is that of a DispatchQueue operation that
431439
/// takes a closure to be executed on the queue.
432-
bool isDispatchQueueOperationName(StringRef name);
440+
Optional<DispatchQueueOperation> isDispatchQueueOperationName(StringRef name);
433441

434442
/// Check the correctness of the given Sendable conformance.
435443
///

test/Concurrency/dispatch_inference.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,10 @@ func testUnsafeSendableInAsync(queue: DispatchQueue) async {
2727
queue.async {
2828
x = 17 // expected-error{{mutation of captured var 'x' in concurrently-executing code}}
2929
}
30+
31+
queue.sync {
32+
x = 17 // okay
33+
}
34+
3035
print(x)
3136
}

0 commit comments

Comments
 (0)