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