@@ -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 //
0 commit comments