@@ -2656,6 +2656,114 @@ static void emitDeclaredHereIfNeeded(DiagnosticEngine &diags,
26562656 diags.diagnose (value, diag::decl_declared_here, value->getName ());
26572657}
26582658
2659+ bool ConformanceChecker::checkActorIsolation (
2660+ ValueDecl *requirement, ValueDecl *witness) {
2661+ // Ensure that the witness is not actor-isolated in a manner that makes it
2662+ // unsuitable as a witness.
2663+ Type witnessGlobalActor;
2664+ switch (auto witnessRestriction =
2665+ ActorIsolationRestriction::forDeclaration (witness)) {
2666+ case ActorIsolationRestriction::ActorSelf: {
2667+ // Actor-isolated witnesses cannot conform to protocol requirements.
2668+ bool canBeAsyncHandler = false ;
2669+ if (auto witnessFunc = dyn_cast<FuncDecl>(witness)) {
2670+ canBeAsyncHandler = !witnessFunc->isAsyncHandler () &&
2671+ witnessFunc->canBeAsyncHandler ();
2672+ }
2673+ auto diag = witness->diagnose (
2674+ canBeAsyncHandler
2675+ ? diag::actor_isolated_witness_could_be_async_handler
2676+ : diag::actor_isolated_witness,
2677+ witness->getDescriptiveKind (), witness->getName ());
2678+
2679+ if (canBeAsyncHandler) {
2680+ diag.fixItInsert (
2681+ witness->getAttributeInsertionLoc (false ), " @asyncHandler " );
2682+ }
2683+
2684+ return true ;
2685+ }
2686+
2687+ case ActorIsolationRestriction::GlobalActor: {
2688+ // Hang on to the global actor that's used for the witness. It will need
2689+ // to match that of the requirement.
2690+ witnessGlobalActor = witness->getDeclContext ()->mapTypeIntoContext (
2691+ witnessRestriction.getGlobalActor ());
2692+ break ;
2693+ }
2694+
2695+ case ActorIsolationRestriction::Unsafe:
2696+ case ActorIsolationRestriction::LocalCapture:
2697+ break ;
2698+
2699+ case ActorIsolationRestriction::Unrestricted:
2700+ // The witness is completely unrestricted, so ignore any annotations on
2701+ // the requirement.
2702+ return false ;
2703+ }
2704+
2705+ // Check whether the requirement requires some particular actor isolation.
2706+ Type requirementGlobalActor;
2707+ switch (auto requirementIsolation = getActorIsolation (requirement)) {
2708+ case ActorIsolation::ActorInstance:
2709+ llvm_unreachable (" There are not actor protocols" );
2710+
2711+ case ActorIsolation::GlobalActor: {
2712+ auto requirementSubs = SubstitutionMap::getProtocolSubstitutions (
2713+ Proto, Adoptee, ProtocolConformanceRef (Conformance));
2714+ requirementGlobalActor = requirementIsolation.getGlobalActor ()
2715+ .subst (requirementSubs);
2716+ break ;
2717+ }
2718+
2719+ case ActorIsolation::Independent:
2720+ case ActorIsolation::Unspecified:
2721+ break ;
2722+ }
2723+
2724+ // If neither has a global actor, we're done.
2725+ if (!witnessGlobalActor && !requirementGlobalActor)
2726+ return false ;
2727+
2728+ // If the witness has a global actor but the requirement does not, we have
2729+ // an isolation error.
2730+ if (witnessGlobalActor && !requirementGlobalActor) {
2731+ witness->diagnose (
2732+ diag::global_actor_isolated_witness, witness->getDescriptiveKind (),
2733+ witness->getName (), witnessGlobalActor, Proto->getName ());
2734+ requirement->diagnose (diag::decl_declared_here, requirement->getName ());
2735+ return true ;
2736+ }
2737+
2738+ // If the requirement has a global actor but the witness does not, we have
2739+ // an isolation error.
2740+ //
2741+ // FIXME: Within a module, this will be an inference rule.
2742+ if (requirementGlobalActor && !witnessGlobalActor) {
2743+ witness->diagnose (
2744+ diag::global_actor_isolated_requirement, witness->getDescriptiveKind (),
2745+ witness->getName (), requirementGlobalActor, Proto->getName ())
2746+ .fixItInsert (
2747+ witness->getAttributeInsertionLoc (/* forModifier=*/ false ),
2748+ " @" + requirementGlobalActor.getString ());
2749+ requirement->diagnose (diag::decl_declared_here, requirement->getName ());
2750+ return true ;
2751+ }
2752+
2753+ // If both have global actors but they differ, this is an isolation error.
2754+ if (!witnessGlobalActor->isEqual (requirementGlobalActor)) {
2755+ witness->diagnose (
2756+ diag::global_actor_isolated_requirement_witness_conflict,
2757+ witness->getDescriptiveKind (), witness->getName (), witnessGlobalActor,
2758+ Proto->getName (), requirementGlobalActor);
2759+ requirement->diagnose (diag::decl_declared_here, requirement->getName ());
2760+ return true ;
2761+ }
2762+
2763+ // Everything is okay.
2764+ return false ;
2765+ }
2766+
26592767bool ConformanceChecker::checkObjCTypeErasedGenerics (
26602768 AssociatedTypeDecl *assocType,
26612769 Type type,
@@ -4337,39 +4445,8 @@ void ConformanceChecker::resolveValueWitnesses() {
43374445 return ;
43384446 }
43394447
4340- // Check for actor-isolation consistency.
4341- switch (auto restriction =
4342- ActorIsolationRestriction::forDeclaration (witness)) {
4343- case ActorIsolationRestriction::ActorSelf: {
4344- // Actor-isolated witnesses cannot conform to protocol requirements.
4345- bool canBeAsyncHandler = false ;
4346- if (auto witnessFunc = dyn_cast<FuncDecl>(witness)) {
4347- canBeAsyncHandler = !witnessFunc->isAsyncHandler () &&
4348- witnessFunc->canBeAsyncHandler ();
4349- }
4350- auto diag = witness->diagnose (
4351- canBeAsyncHandler
4352- ? diag::actor_isolated_witness_could_be_async_handler
4353- : diag::actor_isolated_witness,
4354- witness->getDescriptiveKind (), witness->getName ());
4355-
4356- if (canBeAsyncHandler) {
4357- diag.fixItInsert (
4358- witness->getAttributeInsertionLoc (false ), " @asyncHandler " );
4359- }
4448+ if (checkActorIsolation (requirement, witness))
43604449 return ;
4361- }
4362-
4363- case ActorIsolationRestriction::GlobalActor: {
4364- // FIXME: Check against the requirement. This needs serious refactoring.
4365- break ;
4366- }
4367-
4368- case ActorIsolationRestriction::Unrestricted:
4369- case ActorIsolationRestriction::Unsafe:
4370- case ActorIsolationRestriction::LocalCapture:
4371- break ;
4372- }
43734450
43744451 // Objective-C checking for @objc requirements.
43754452 if (requirement->isObjC () &&
0 commit comments