@@ -2655,6 +2655,114 @@ static void emitDeclaredHereIfNeeded(DiagnosticEngine &diags,
2655
2655
diags.diagnose (value, diag::decl_declared_here, value->getName ());
2656
2656
}
2657
2657
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
+
2658
2766
bool ConformanceChecker::checkObjCTypeErasedGenerics (
2659
2767
AssociatedTypeDecl *assocType,
2660
2768
Type type,
@@ -4336,39 +4444,8 @@ void ConformanceChecker::resolveValueWitnesses() {
4336
4444
return ;
4337
4445
}
4338
4446
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))
4359
4448
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
- }
4372
4449
4373
4450
// Objective-C checking for @objc requirements.
4374
4451
if (requirement->isObjC () &&
0 commit comments