@@ -1276,12 +1276,13 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
1276
1276
auto &diags = C.Diags ;
1277
1277
auto module = nominal->getParentModule ();
1278
1278
Type nominalTy = nominal->getDeclaredInterfaceType ();
1279
+ NominalTypeDecl *executorDecl = C.getExecutorDecl ();
1279
1280
1280
1281
// enqueue(_:)
1281
1282
auto enqueueDeclName = DeclName (C, DeclBaseName (C.Id_enqueue ), { Identifier () });
1282
1283
1283
1284
FuncDecl *moveOnlyEnqueueRequirement = nullptr ;
1284
- FuncDecl *legacyMoveOnlyEnqueueRequirement = nullptr ; // TODO: preferably we'd want to remove handling of `enqueue(Job)` when able to
1285
+ FuncDecl *legacyMoveOnlyEnqueueRequirement = nullptr ;
1285
1286
FuncDecl *unownedEnqueueRequirement = nullptr ;
1286
1287
for (auto req: proto->getProtocolRequirements ()) {
1287
1288
auto *funcDecl = dyn_cast<FuncDecl>(req);
@@ -1324,18 +1325,17 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
1324
1325
assert (unownedEnqueueRequirement && " could not find the enqueue(UnownedJob) requirement, which should be always there" );
1325
1326
1326
1327
// try to find at least a single implementations of enqueue(_:)
1327
- ConcreteDeclRef unownedEnqueueWitness = concreteConformance->getWitnessDeclRef (unownedEnqueueRequirement);
1328
- ValueDecl *unownedEnqueueWitnessDecl = unownedEnqueueWitness.getDecl ();
1328
+ ValueDecl *unownedEnqueueWitnessDecl = concreteConformance->getWitnessDecl (unownedEnqueueRequirement);
1329
1329
ValueDecl *moveOnlyEnqueueWitnessDecl = nullptr ;
1330
1330
ValueDecl *legacyMoveOnlyEnqueueWitnessDecl = nullptr ;
1331
1331
1332
1332
if (moveOnlyEnqueueRequirement) {
1333
- moveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDeclRef (
1334
- moveOnlyEnqueueRequirement). getDecl () ;
1333
+ moveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDecl (
1334
+ moveOnlyEnqueueRequirement);
1335
1335
}
1336
1336
if (legacyMoveOnlyEnqueueRequirement) {
1337
- legacyMoveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDeclRef (
1338
- legacyMoveOnlyEnqueueRequirement). getDecl () ;
1337
+ legacyMoveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDecl (
1338
+ legacyMoveOnlyEnqueueRequirement);
1339
1339
}
1340
1340
1341
1341
// --- Diagnose warnings and errors
@@ -1358,26 +1358,62 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
1358
1358
canRemoveOldDecls = declInfo.isContainedIn (requirementInfo);
1359
1359
}
1360
1360
1361
+ auto concurrencyModule = C.getLoadedModule (C.Id_Concurrency );
1362
+ auto isStdlibDefaultImplDecl = [executorDecl, concurrencyModule](ValueDecl *witness) -> bool {
1363
+ if (auto declContext = witness->getDeclContext ()) {
1364
+ if (auto *extension = dyn_cast<ExtensionDecl>(declContext)) {
1365
+ auto extensionModule = extension->getParentModule ();
1366
+ if (extensionModule != concurrencyModule) {
1367
+ return false ;
1368
+ }
1369
+
1370
+ if (auto extendedNominal = extension->getExtendedNominal ()) {
1371
+ return extendedNominal->getDeclaredInterfaceType ()->isEqual (
1372
+ executorDecl->getDeclaredInterfaceType ());
1373
+ }
1374
+ }
1375
+ }
1376
+ return false ;
1377
+ };
1378
+
1361
1379
// If both old and new enqueue are implemented, but the old one cannot be removed,
1362
1380
// emit a warning that the new enqueue is unused.
1363
- if (!canRemoveOldDecls &&
1364
- unownedEnqueueWitnessDecl && unownedEnqueueWitnessDecl->getLoc ().isValid () &&
1365
- moveOnlyEnqueueWitnessDecl && moveOnlyEnqueueWitnessDecl->getLoc ().isValid ()) {
1366
- diags.diagnose (moveOnlyEnqueueWitnessDecl->getLoc (), diag::executor_enqueue_unused_implementation);
1381
+ if (!canRemoveOldDecls && unownedEnqueueWitnessDecl && moveOnlyEnqueueWitnessDecl) {
1382
+ if (!isStdlibDefaultImplDecl (moveOnlyEnqueueWitnessDecl)) {
1383
+ diags.diagnose (moveOnlyEnqueueWitnessDecl->getLoc (),
1384
+ diag::executor_enqueue_unused_implementation);
1385
+ }
1367
1386
}
1368
1387
1369
1388
// Old UnownedJob based impl is present, warn about it suggesting the new protocol requirement.
1370
- if (canRemoveOldDecls && unownedEnqueueWitnessDecl && unownedEnqueueWitnessDecl->getLoc ().isValid ()) {
1371
- diags.diagnose (unownedEnqueueWitnessDecl->getLoc (), diag::executor_enqueue_unowned_implementation, nominalTy);
1389
+ if (canRemoveOldDecls && unownedEnqueueWitnessDecl) {
1390
+ if (!isStdlibDefaultImplDecl (unownedEnqueueWitnessDecl)) {
1391
+ diags.diagnose (unownedEnqueueWitnessDecl->getLoc (),
1392
+ diag::executor_enqueue_deprecated_unowned_implementation,
1393
+ nominalTy);
1394
+ }
1372
1395
}
1373
1396
// Old Job based impl is present, warn about it suggesting the new protocol requirement.
1374
- if (legacyMoveOnlyEnqueueWitnessDecl && legacyMoveOnlyEnqueueWitnessDecl->getLoc ().isValid ()) {
1375
- diags.diagnose (legacyMoveOnlyEnqueueWitnessDecl->getLoc (), diag::executor_enqueue_deprecated_owned_job_implementation, nominalTy);
1397
+ if (legacyMoveOnlyEnqueueWitnessDecl) {
1398
+ if (!isStdlibDefaultImplDecl (legacyMoveOnlyEnqueueWitnessDecl)) {
1399
+ diags.diagnose (legacyMoveOnlyEnqueueWitnessDecl->getLoc (),
1400
+ diag::executor_enqueue_deprecated_owned_job_implementation,
1401
+ nominalTy);
1402
+ }
1376
1403
}
1377
1404
1378
- if ((!unownedEnqueueWitnessDecl || unownedEnqueueWitnessDecl->getLoc ().isInvalid ()) &&
1379
- (!moveOnlyEnqueueWitnessDecl || moveOnlyEnqueueWitnessDecl->getLoc ().isInvalid ()) &&
1380
- (!legacyMoveOnlyEnqueueWitnessDecl || legacyMoveOnlyEnqueueWitnessDecl->getLoc ().isInvalid ())) {
1405
+ bool unownedEnqueueWitnessIsDefaultImpl = isStdlibDefaultImplDecl (unownedEnqueueWitnessDecl);
1406
+ bool moveOnlyEnqueueWitnessIsDefaultImpl = isStdlibDefaultImplDecl (moveOnlyEnqueueWitnessDecl);
1407
+ bool legacyMoveOnlyEnqueueWitnessDeclIsDefaultImpl = isStdlibDefaultImplDecl (legacyMoveOnlyEnqueueWitnessDecl);
1408
+
1409
+ auto missingWitness = !unownedEnqueueWitnessDecl &&
1410
+ !moveOnlyEnqueueWitnessDecl &&
1411
+ !legacyMoveOnlyEnqueueWitnessDecl;
1412
+ auto allWitnessesAreDefaultImpls = unownedEnqueueWitnessIsDefaultImpl &&
1413
+ moveOnlyEnqueueWitnessIsDefaultImpl &&
1414
+ legacyMoveOnlyEnqueueWitnessDeclIsDefaultImpl;
1415
+ if ((missingWitness) ||
1416
+ (!missingWitness && allWitnessesAreDefaultImpls)) {
1381
1417
// Neither old nor new implementation have been found, but we provide default impls for them
1382
1418
// that are mutually recursive, so we must error and suggest implementing the right requirement.
1383
1419
//
0 commit comments