Skip to content

Commit bbce215

Browse files
authored
Merge pull request #67231 from ktoso/pick-serial-executor-warning
🍒[5.9][Sema] Improve SerialExecutor diagnostics
2 parents 3f67cab + 5d766a0 commit bbce215

File tree

3 files changed

+101
-1
lines changed

3 files changed

+101
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6650,6 +6650,10 @@ WARNING(executor_enqueue_deprecated_owned_job_implementation,Deprecation,
66506650
"'Executor.enqueue(Job)' is deprecated as a protocol requirement; "
66516651
"conform type %0 to 'Executor' by implementing 'func enqueue(ExecutorJob)' instead",
66526652
(Type))
6653+
WARNING(executor_enqueue_unused_implementation, none,
6654+
"'Executor.enqueue(ExecutorJob)' will never be used, due to the presence of "
6655+
"'enqueue(UnownedJob)'",
6656+
())
66536657

66546658
//------------------------------------------------------------------------------
66556659
// MARK: property wrapper diagnostics

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1347,8 +1347,34 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
13471347

13481348
// --- Diagnose warnings and errors
13491349

1350+
// true iff the nominal type's availability allows the legacy requirement
1351+
// to be omitted in favor of moveOnlyEnqueueRequirement
1352+
bool canRemoveOldDecls;
1353+
if (!moveOnlyEnqueueRequirement) {
1354+
// The move only enqueue does not exist in this lib version, we must keep relying on the UnownedJob version
1355+
canRemoveOldDecls = false;
1356+
} else if (C.LangOpts.DisableAvailabilityChecking) {
1357+
// Assume we have all APIs available, and thus can use the ExecutorJob
1358+
canRemoveOldDecls = true;
1359+
} else {
1360+
// Check if the availability of nominal is high enough to be using the ExecutorJob version
1361+
AvailabilityContext requirementInfo
1362+
= AvailabilityInference::availableRange(moveOnlyEnqueueRequirement, C);
1363+
AvailabilityContext declInfo =
1364+
TypeChecker::overApproximateAvailabilityAtLocation(nominal->getLoc(), dyn_cast<DeclContext>(nominal));
1365+
canRemoveOldDecls = declInfo.isContainedIn(requirementInfo);
1366+
}
1367+
1368+
// If both old and new enqueue are implemented, but the old one cannot be removed,
1369+
// emit a warning that the new enqueue is unused.
1370+
if (!canRemoveOldDecls &&
1371+
unownedEnqueueWitnessDecl && unownedEnqueueWitnessDecl->getLoc().isValid() &&
1372+
moveOnlyEnqueueWitnessDecl && moveOnlyEnqueueWitnessDecl->getLoc().isValid()) {
1373+
diags.diagnose(moveOnlyEnqueueWitnessDecl->getLoc(), diag::executor_enqueue_unused_implementation);
1374+
}
1375+
13501376
// Old UnownedJob based impl is present, warn about it suggesting the new protocol requirement.
1351-
if (unownedEnqueueWitnessDecl && unownedEnqueueWitnessDecl->getLoc().isValid()) {
1377+
if (canRemoveOldDecls && unownedEnqueueWitnessDecl && unownedEnqueueWitnessDecl->getLoc().isValid()) {
13521378
diags.diagnose(unownedEnqueueWitnessDecl->getLoc(), diag::executor_enqueue_unowned_implementation, nominalTy);
13531379
}
13541380
// Old Job based impl is present, warn about it suggesting the new protocol requirement.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-move-only
2+
// REQUIRES: concurrency
3+
// REQUIRES: OS=macosx
4+
5+
// rdar://106849189 move-only types should be supported in freestanding mode
6+
// UNSUPPORTED: freestanding
7+
8+
/// Such a type may be encountered since Swift 5.5 (5.1 backdeployed) if someone implemented the
9+
/// not documented, but public Executor types back then already. Allow these to be implemented
10+
/// without warnings.
11+
@available(SwiftStdlib 5.1, *)
12+
final class OldExecutorOldStdlib: SerialExecutor {
13+
func enqueue(_ job: UnownedJob) {}
14+
15+
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
16+
UnownedSerialExecutor(ordinary: self)
17+
}
18+
}
19+
20+
/// We warn on the ExecutorJob witness if the type has a broader
21+
/// availability, since in this case the UnownedJob version needs to exist.
22+
@available(SwiftStdlib 5.1, *)
23+
final class BothExecutorOldStdlib: SerialExecutor {
24+
func enqueue(_ job: UnownedJob) {}
25+
26+
@available(SwiftStdlib 5.9, *)
27+
func enqueue(_ job: __owned ExecutorJob) {} // expected-warning{{'Executor.enqueue(ExecutorJob)' will never be used, due to the presence of 'enqueue(UnownedJob)'}}
28+
29+
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
30+
UnownedSerialExecutor(ordinary: self)
31+
}
32+
}
33+
34+
/// Meanwhile, we warn on the UnownedJob overload if the availability is new enough
35+
/// that it can be dropped.
36+
@available(SwiftStdlib 5.9, *)
37+
final class BothExecutorNewStdlib: SerialExecutor {
38+
func enqueue(_ job: UnownedJob) {} // expected-warning{{'Executor.enqueue(UnownedJob)' is deprecated as a protocol requirement; conform type 'BothExecutorNewStdlib' to 'Executor' by implementing 'func enqueue(ExecutorJob)' instead}}
39+
40+
func enqueue(_ job: __owned ExecutorJob) {}
41+
42+
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
43+
UnownedSerialExecutor(ordinary: self)
44+
}
45+
}
46+
47+
@available(SwiftStdlib 5.9, *)
48+
final class TripleExecutor: SerialExecutor {
49+
func enqueue(_ job: UnownedJob) {} // expected-warning{{'Executor.enqueue(UnownedJob)' is deprecated as a protocol requirement; conform type 'TripleExecutor' to 'Executor' by implementing 'func enqueue(ExecutorJob)' instead}}
50+
51+
// expected-warning@+2{{'Job' is deprecated: renamed to 'ExecutorJob'}}
52+
// expected-note@+1{{use 'ExecutorJob' instead}}
53+
func enqueue(_ job: __owned Job) {} // expected-warning{{'Executor.enqueue(Job)' is deprecated as a protocol requirement; conform type 'TripleExecutor' to 'Executor' by implementing 'func enqueue(ExecutorJob)' instead}}
54+
55+
func enqueue(_ job: consuming ExecutorJob) {}
56+
57+
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
58+
UnownedSerialExecutor(ordinary: self)
59+
}
60+
}
61+
62+
/// Implementing the new signature on 5.9 platforms is good, no warnings
63+
@available(SwiftStdlib 5.9, *)
64+
final class NewExecutorNewStdlib: SerialExecutor {
65+
func enqueue(_ job: __owned ExecutorJob) {}
66+
67+
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
68+
UnownedSerialExecutor(ordinary: self)
69+
}
70+
}

0 commit comments

Comments
 (0)