@@ -1283,12 +1283,13 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
1283
1283
auto &diags = C.Diags ;
1284
1284
auto module = nominal->getParentModule ();
1285
1285
Type nominalTy = nominal->getDeclaredInterfaceType ();
1286
+ NominalTypeDecl *executorDecl = C.getExecutorDecl ();
1286
1287
1287
1288
// enqueue(_:)
1288
1289
auto enqueueDeclName = DeclName (C, DeclBaseName (C.Id_enqueue ), { Identifier () });
1289
1290
1290
1291
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 ;
1292
1293
FuncDecl *unownedEnqueueRequirement = nullptr ;
1293
1294
for (auto req: proto->getProtocolRequirements ()) {
1294
1295
auto *funcDecl = dyn_cast<FuncDecl>(req);
@@ -1331,18 +1332,17 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
1331
1332
assert (unownedEnqueueRequirement && " could not find the enqueue(UnownedJob) requirement, which should be always there" );
1332
1333
1333
1334
// 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);
1336
1336
ValueDecl *moveOnlyEnqueueWitnessDecl = nullptr ;
1337
1337
ValueDecl *legacyMoveOnlyEnqueueWitnessDecl = nullptr ;
1338
1338
1339
1339
if (moveOnlyEnqueueRequirement) {
1340
- moveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDeclRef (
1341
- moveOnlyEnqueueRequirement). getDecl () ;
1340
+ moveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDecl (
1341
+ moveOnlyEnqueueRequirement);
1342
1342
}
1343
1343
if (legacyMoveOnlyEnqueueRequirement) {
1344
- legacyMoveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDeclRef (
1345
- legacyMoveOnlyEnqueueRequirement). getDecl () ;
1344
+ legacyMoveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDecl (
1345
+ legacyMoveOnlyEnqueueRequirement);
1346
1346
}
1347
1347
1348
1348
// --- Diagnose warnings and errors
@@ -1365,26 +1365,62 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
1365
1365
canRemoveOldDecls = declInfo.isContainedIn (requirementInfo);
1366
1366
}
1367
1367
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
+
1368
1386
// If both old and new enqueue are implemented, but the old one cannot be removed,
1369
1387
// 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
+ }
1374
1393
}
1375
1394
1376
1395
// 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
+ }
1379
1402
}
1380
1403
// 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
+ }
1383
1410
}
1384
1411
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)) {
1388
1424
// Neither old nor new implementation have been found, but we provide default impls for them
1389
1425
// that are mutually recursive, so we must error and suggest implementing the right requirement.
1390
1426
//
0 commit comments