Skip to content

Commit d4ee7bf

Browse files
authored
Merge pull request #67960 from ktoso/pick-pick-dont-use-loc-validness-in-diagnostics-determination-113913291
2 parents b74018b + 4801d22 commit d4ee7bf

File tree

4 files changed

+78
-23
lines changed

4 files changed

+78
-23
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6646,7 +6646,7 @@ WARNING(hashvalue_implementation,Deprecation,
66466646
"conform type %0 to 'Hashable' by implementing 'hash(into:)' instead",
66476647
(Type))
66486648

6649-
WARNING(executor_enqueue_unowned_implementation,Deprecation,
6649+
WARNING(executor_enqueue_deprecated_unowned_implementation,Deprecation,
66506650
"'Executor.enqueue(UnownedJob)' is deprecated as a protocol requirement; "
66516651
"conform type %0 to 'Executor' by implementing 'func enqueue(ExecutorJob)' instead",
66526652
(Type))

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,12 +1283,13 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
12831283
auto &diags = C.Diags;
12841284
auto module = nominal->getParentModule();
12851285
Type nominalTy = nominal->getDeclaredInterfaceType();
1286+
NominalTypeDecl *executorDecl = C.getExecutorDecl();
12861287

12871288
// enqueue(_:)
12881289
auto enqueueDeclName = DeclName(C, DeclBaseName(C.Id_enqueue), { Identifier() });
12891290

12901291
FuncDecl *moveOnlyEnqueueRequirement = nullptr;
1291-
FuncDecl *legacyMoveOnlyEnqueueRequirement = nullptr; // TODO: preferably we'd want to remove handling of `enqueue(Job)` when able to
1292+
FuncDecl *legacyMoveOnlyEnqueueRequirement = nullptr;
12921293
FuncDecl *unownedEnqueueRequirement = nullptr;
12931294
for (auto req: proto->getProtocolRequirements()) {
12941295
auto *funcDecl = dyn_cast<FuncDecl>(req);
@@ -1331,18 +1332,17 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
13311332
assert(unownedEnqueueRequirement && "could not find the enqueue(UnownedJob) requirement, which should be always there");
13321333

13331334
// try to find at least a single implementations of enqueue(_:)
1334-
ConcreteDeclRef unownedEnqueueWitness = concreteConformance->getWitnessDeclRef(unownedEnqueueRequirement);
1335-
ValueDecl *unownedEnqueueWitnessDecl = unownedEnqueueWitness.getDecl();
1335+
ValueDecl *unownedEnqueueWitnessDecl = concreteConformance->getWitnessDecl(unownedEnqueueRequirement);
13361336
ValueDecl *moveOnlyEnqueueWitnessDecl = nullptr;
13371337
ValueDecl *legacyMoveOnlyEnqueueWitnessDecl = nullptr;
13381338

13391339
if (moveOnlyEnqueueRequirement) {
1340-
moveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDeclRef(
1341-
moveOnlyEnqueueRequirement).getDecl();
1340+
moveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDecl(
1341+
moveOnlyEnqueueRequirement);
13421342
}
13431343
if (legacyMoveOnlyEnqueueRequirement) {
1344-
legacyMoveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDeclRef(
1345-
legacyMoveOnlyEnqueueRequirement).getDecl();
1344+
legacyMoveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDecl(
1345+
legacyMoveOnlyEnqueueRequirement);
13461346
}
13471347

13481348
// --- Diagnose warnings and errors
@@ -1365,26 +1365,62 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
13651365
canRemoveOldDecls = declInfo.isContainedIn(requirementInfo);
13661366
}
13671367

1368+
auto concurrencyModule = C.getLoadedModule(C.Id_Concurrency);
1369+
auto isStdlibDefaultImplDecl = [executorDecl, concurrencyModule](ValueDecl *witness) -> bool {
1370+
if (auto declContext = witness->getDeclContext()) {
1371+
if (auto *extension = dyn_cast<ExtensionDecl>(declContext)) {
1372+
auto extensionModule = extension->getParentModule();
1373+
if (extensionModule != concurrencyModule) {
1374+
return false;
1375+
}
1376+
1377+
if (auto extendedNominal = extension->getExtendedNominal()) {
1378+
return extendedNominal->getDeclaredInterfaceType()->isEqual(
1379+
executorDecl->getDeclaredInterfaceType());
1380+
}
1381+
}
1382+
}
1383+
return false;
1384+
};
1385+
13681386
// If both old and new enqueue are implemented, but the old one cannot be removed,
13691387
// 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);
1388+
if (!canRemoveOldDecls && unownedEnqueueWitnessDecl && moveOnlyEnqueueWitnessDecl) {
1389+
if (!isStdlibDefaultImplDecl(moveOnlyEnqueueWitnessDecl)) {
1390+
diags.diagnose(moveOnlyEnqueueWitnessDecl->getLoc(),
1391+
diag::executor_enqueue_unused_implementation);
1392+
}
13741393
}
13751394

13761395
// Old UnownedJob based impl is present, warn about it suggesting the new protocol requirement.
1377-
if (canRemoveOldDecls && unownedEnqueueWitnessDecl && unownedEnqueueWitnessDecl->getLoc().isValid()) {
1378-
diags.diagnose(unownedEnqueueWitnessDecl->getLoc(), diag::executor_enqueue_unowned_implementation, nominalTy);
1396+
if (canRemoveOldDecls && unownedEnqueueWitnessDecl) {
1397+
if (!isStdlibDefaultImplDecl(unownedEnqueueWitnessDecl)) {
1398+
diags.diagnose(unownedEnqueueWitnessDecl->getLoc(),
1399+
diag::executor_enqueue_deprecated_unowned_implementation,
1400+
nominalTy);
1401+
}
13791402
}
13801403
// Old Job based impl is present, warn about it suggesting the new protocol requirement.
1381-
if (legacyMoveOnlyEnqueueWitnessDecl && legacyMoveOnlyEnqueueWitnessDecl->getLoc().isValid()) {
1382-
diags.diagnose(legacyMoveOnlyEnqueueWitnessDecl->getLoc(), diag::executor_enqueue_deprecated_owned_job_implementation, nominalTy);
1404+
if (legacyMoveOnlyEnqueueWitnessDecl) {
1405+
if (!isStdlibDefaultImplDecl(legacyMoveOnlyEnqueueWitnessDecl)) {
1406+
diags.diagnose(legacyMoveOnlyEnqueueWitnessDecl->getLoc(),
1407+
diag::executor_enqueue_deprecated_owned_job_implementation,
1408+
nominalTy);
1409+
}
13831410
}
13841411

1385-
if ((!unownedEnqueueWitnessDecl || unownedEnqueueWitnessDecl->getLoc().isInvalid()) &&
1386-
(!moveOnlyEnqueueWitnessDecl || moveOnlyEnqueueWitnessDecl->getLoc().isInvalid()) &&
1387-
(!legacyMoveOnlyEnqueueWitnessDecl || legacyMoveOnlyEnqueueWitnessDecl->getLoc().isInvalid())) {
1412+
bool unownedEnqueueWitnessIsDefaultImpl = isStdlibDefaultImplDecl(unownedEnqueueWitnessDecl);
1413+
bool moveOnlyEnqueueWitnessIsDefaultImpl = isStdlibDefaultImplDecl(moveOnlyEnqueueWitnessDecl);
1414+
bool legacyMoveOnlyEnqueueWitnessDeclIsDefaultImpl = isStdlibDefaultImplDecl(legacyMoveOnlyEnqueueWitnessDecl);
1415+
1416+
auto missingWitness = !unownedEnqueueWitnessDecl &&
1417+
!moveOnlyEnqueueWitnessDecl &&
1418+
!legacyMoveOnlyEnqueueWitnessDecl;
1419+
auto allWitnessesAreDefaultImpls = unownedEnqueueWitnessIsDefaultImpl &&
1420+
moveOnlyEnqueueWitnessIsDefaultImpl &&
1421+
legacyMoveOnlyEnqueueWitnessDeclIsDefaultImpl;
1422+
if ((missingWitness) ||
1423+
(!missingWitness && allWitnessesAreDefaultImpls)) {
13881424
// Neither old nor new implementation have been found, but we provide default impls for them
13891425
// that are mutually recursive, so we must error and suggest implementing the right requirement.
13901426
//
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking
2+
// REQUIRES: concurrency
3+
4+
// rdar://106849189 move-only types should be supported in freestanding mode
5+
// UNSUPPORTED: freestanding
6+
7+
8+
extension Executor {
9+
func enqueue(_ job: UnownedJob) { // expected-warning{{'Executor.enqueue(UnownedJob)' is deprecated as a protocol requirement; conform type 'NoneExecutor' to 'Executor' by implementing 'func enqueue(ExecutorJob)' instead}}
10+
fatalError()
11+
}
12+
}
13+
14+
final class NoneExecutor: SerialExecutor {
15+
16+
// the enqueue from the extension is properly picked up,
17+
// even though we do warn about deprecation on it in the extension.
18+
19+
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
20+
UnownedSerialExecutor(ordinary: self)
21+
}
22+
}

test/Concurrency/custom_executor_enqueue_impls.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
// RUN: %target-typecheck-verify-swift -enable-experimental-move-only -disable-availability-checking
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking
22
// REQUIRES: concurrency
33

44
// rdar://106849189 move-only types should be supported in freestanding mode
55
// UNSUPPORTED: freestanding
66

7-
// FIXME: rdar://107112715 test failing on iOS simulator, investigating
8-
// UNSUPPORTED: OS=ios
9-
107
// Such type may be encountered since Swift 5.5 (5.1 backdeployed) if someone implemented the
118
// not documented, but public Executor types back then already.
129
//

0 commit comments

Comments
 (0)