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