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
This commit is contained in:
Konrad `ktoso` Malawski
2023-09-19 17:46:18 +09:00
parent 469a614eef
commit 6714f4b301
3 changed files with 72 additions and 2 deletions

View File

@@ -1394,9 +1394,13 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
// If both old and new enqueue are implemented, but the old one cannot be removed, // If both old and new enqueue are implemented, but the old one cannot be removed,
// emit a warning that the new enqueue is unused. // emit a warning that the new enqueue is unused.
if (!canRemoveOldDecls && unownedEnqueueWitnessDecl && moveOnlyEnqueueWitnessDecl) { if (!canRemoveOldDecls && unownedEnqueueWitnessDecl && moveOnlyEnqueueWitnessDecl) {
if (!isStdlibDefaultImplDecl(moveOnlyEnqueueWitnessDecl)) { if (!isStdlibDefaultImplDecl(moveOnlyEnqueueWitnessDecl) &&
!isStdlibDefaultImplDecl(unownedEnqueueWitnessDecl)) {
diags.diagnose(moveOnlyEnqueueWitnessDecl->getLoc(), diags.diagnose(moveOnlyEnqueueWitnessDecl->getLoc(),
diag::executor_enqueue_unused_implementation); diag::executor_enqueue_unused_implementation);
if (auto decl = unownedEnqueueWitnessDecl) {
decl->diagnose(diag::decl_declared_here, decl);
}
} }
} }

View File

@@ -26,7 +26,7 @@ final class OldExecutorOldStdlib: SerialExecutor {
/// availability, since in this case the UnownedJob version needs to exist. /// availability, since in this case the UnownedJob version needs to exist.
@available(SwiftStdlib 5.1, *) @available(SwiftStdlib 5.1, *)
final class BothExecutorOldStdlib: SerialExecutor { final class BothExecutorOldStdlib: SerialExecutor {
func enqueue(_ job: UnownedJob) {} func enqueue(_ job: UnownedJob) {} // expected-note{{'enqueue' declared here}}
@available(SwiftStdlib 5.9, *) @available(SwiftStdlib 5.9, *)
func enqueue(_ job: __owned ExecutorJob) {} // expected-warning{{'Executor.enqueue(ExecutorJob)' will never be used, due to the presence of 'enqueue(UnownedJob)'}} func enqueue(_ job: __owned ExecutorJob) {} // expected-warning{{'Executor.enqueue(ExecutorJob)' will never be used, due to the presence of 'enqueue(UnownedJob)'}}

View File

@@ -0,0 +1,66 @@
// RUN: %target-swift-frontend -enable-experimental-move-only %s -emit-sil -o /dev/null -verify
// RUN: %target-swift-frontend -enable-experimental-move-only %s -emit-sil -o /dev/null -verify -strict-concurrency=targeted
// RUN: %target-swift-frontend -enable-experimental-move-only %s -emit-sil -o /dev/null -verify -strict-concurrency=complete
// RUN: %target-swift-frontend -enable-experimental-move-only %s -emit-sil -o /dev/null -verify -strict-concurrency=complete -enable-experimental-feature SendNonSendable
// REQUIRES: concurrency
public protocol EventLoop: Sendable {}
#if compiler(>=5.9)
/// A helper protocol that can be mixed in to a NIO ``EventLoop`` to provide an
/// automatic conformance to `SerialExecutor`.
///
/// Implementers of `EventLoop` should consider conforming to this protocol as
/// well on Swift 5.9 and later.
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
public protocol NIOSerialEventLoopExecutor: EventLoop, SerialExecutor { }
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
extension NIOSerialEventLoopExecutor {
@inlinable
public func enqueue(_ job: consuming ExecutorJob) {
fatalError("mock impl")
}
@inlinable
public func asUnownedSerialExecutor() -> UnownedSerialExecutor {
UnownedSerialExecutor(ordinary: self)
}
@inlinable
public var executor: any SerialExecutor {
self
}
}
// EARLIER AVAILABILITY
final class NIODefaultSerialEventLoopExecutor {
@usableFromInline
let loop: EventLoop
@inlinable
init(_ loop: EventLoop) {
self.loop = loop
}
}
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
extension NIODefaultSerialEventLoopExecutor: SerialExecutor {
@inlinable
public func enqueue(_ job: consuming ExecutorJob) { // do NOT issue a warning here
fatalError("mock impl")
}
@inlinable
public func asUnownedSerialExecutor() -> UnownedSerialExecutor {
UnownedSerialExecutor(complexEquality: self)
}
@inlinable
public func isSameExclusiveExecutionContext(other: NIODefaultSerialEventLoopExecutor) -> Bool {
false
}
}
#endif