Skip to content

Commit 6714f4b

Browse files
committed
Avoid issuing warning when user lib implements only ExecutorJob enqueue
The latter example NIODefaultSerialEventLoopExecutor when the type is more available than the enqueue implementation provided via an extrension would issue a warning that that this enqueue(ExecutorJob) would not be used which is not true. We need to filter out all "default impls" from the stdlib as we issue this warning. We also put a note on the offending declaration that one can remove now, to ease getting rid of warnings when possible Resolves rdar://115166475
1 parent 469a614 commit 6714f4b

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1394,9 +1394,13 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
13941394
// If both old and new enqueue are implemented, but the old one cannot be removed,
13951395
// emit a warning that the new enqueue is unused.
13961396
if (!canRemoveOldDecls && unownedEnqueueWitnessDecl && moveOnlyEnqueueWitnessDecl) {
1397-
if (!isStdlibDefaultImplDecl(moveOnlyEnqueueWitnessDecl)) {
1397+
if (!isStdlibDefaultImplDecl(moveOnlyEnqueueWitnessDecl) &&
1398+
!isStdlibDefaultImplDecl(unownedEnqueueWitnessDecl)) {
13981399
diags.diagnose(moveOnlyEnqueueWitnessDecl->getLoc(),
13991400
diag::executor_enqueue_unused_implementation);
1401+
if (auto decl = unownedEnqueueWitnessDecl) {
1402+
decl->diagnose(diag::decl_declared_here, decl);
1403+
}
14001404
}
14011405
}
14021406

test/Concurrency/custom_executor_enqueue_availability.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ final class OldExecutorOldStdlib: SerialExecutor {
2626
/// availability, since in this case the UnownedJob version needs to exist.
2727
@available(SwiftStdlib 5.1, *)
2828
final class BothExecutorOldStdlib: SerialExecutor {
29-
func enqueue(_ job: UnownedJob) {}
29+
func enqueue(_ job: UnownedJob) {} // expected-note{{'enqueue' declared here}}
3030

3131
@available(SwiftStdlib 5.9, *)
3232
func enqueue(_ job: __owned ExecutorJob) {} // expected-warning{{'Executor.enqueue(ExecutorJob)' will never be used, due to the presence of 'enqueue(UnownedJob)'}}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// RUN: %target-swift-frontend -enable-experimental-move-only %s -emit-sil -o /dev/null -verify
2+
// RUN: %target-swift-frontend -enable-experimental-move-only %s -emit-sil -o /dev/null -verify -strict-concurrency=targeted
3+
// RUN: %target-swift-frontend -enable-experimental-move-only %s -emit-sil -o /dev/null -verify -strict-concurrency=complete
4+
// RUN: %target-swift-frontend -enable-experimental-move-only %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -enable-experimental-feature SendNonSendable
5+
6+
// REQUIRES: concurrency
7+
8+
public protocol EventLoop: Sendable {}
9+
10+
#if compiler(>=5.9)
11+
/// A helper protocol that can be mixed in to a NIO ``EventLoop`` to provide an
12+
/// automatic conformance to `SerialExecutor`.
13+
///
14+
/// Implementers of `EventLoop` should consider conforming to this protocol as
15+
/// well on Swift 5.9 and later.
16+
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
17+
public protocol NIOSerialEventLoopExecutor: EventLoop, SerialExecutor { }
18+
19+
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
20+
extension NIOSerialEventLoopExecutor {
21+
@inlinable
22+
public func enqueue(_ job: consuming ExecutorJob) {
23+
fatalError("mock impl")
24+
}
25+
26+
@inlinable
27+
public func asUnownedSerialExecutor() -> UnownedSerialExecutor {
28+
UnownedSerialExecutor(ordinary: self)
29+
}
30+
31+
@inlinable
32+
public var executor: any SerialExecutor {
33+
self
34+
}
35+
}
36+
37+
// EARLIER AVAILABILITY
38+
final class NIODefaultSerialEventLoopExecutor {
39+
@usableFromInline
40+
let loop: EventLoop
41+
42+
@inlinable
43+
init(_ loop: EventLoop) {
44+
self.loop = loop
45+
}
46+
}
47+
48+
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
49+
extension NIODefaultSerialEventLoopExecutor: SerialExecutor {
50+
@inlinable
51+
public func enqueue(_ job: consuming ExecutorJob) { // do NOT issue a warning here
52+
fatalError("mock impl")
53+
}
54+
55+
@inlinable
56+
public func asUnownedSerialExecutor() -> UnownedSerialExecutor {
57+
UnownedSerialExecutor(complexEquality: self)
58+
59+
}
60+
61+
@inlinable
62+
public func isSameExclusiveExecutionContext(other: NIODefaultSerialEventLoopExecutor) -> Bool {
63+
false
64+
}
65+
}
66+
#endif

0 commit comments

Comments
 (0)