Skip to content

Commit c58e22f

Browse files
committed
Simplify APIs for accessing conformance isolation
The NormalProtocolConformance APIs for checking for an explicitly-written isolation on a conformance were easy to get to, and the real semantic API was buried in the type checker, leading to some unprincipled checking. Instead, create a central ProtocolConformance::getIsolation() to get the (semantic) actor isolation, and let that be the only place that will access the explicitly-written global actor isolation for a conformance. Update all call sites appropriately.
1 parent 0cfa048 commit c58e22f

10 files changed

+63
-48
lines changed

include/swift/AST/ProtocolConformance.h

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,14 @@ class alignas(1 << DeclAlignInBits) ProtocolConformance
240240
/// Otherwise a new conformance will be created.
241241
ProtocolConformance *getCanonicalConformance();
242242

243+
/// Determine the actor isolation of this conformance.
244+
ActorIsolation getIsolation() const;
245+
246+
/// Determine whether this conformance is isolated to an actor.
247+
bool isIsolated() const {
248+
return getIsolation().isActorIsolated();
249+
}
250+
243251
/// Return true if the conformance has a witness for the given associated
244252
/// type.
245253
bool hasTypeWitness(AssociatedTypeDecl *assocType) const;
@@ -529,6 +537,7 @@ class NormalProtocolConformance : public RootProtocolConformance,
529537
{
530538
friend class ValueWitnessRequest;
531539
friend class TypeWitnessRequest;
540+
friend class ConformanceIsolationRequest;
532541

533542
/// The protocol being conformed to.
534543
ProtocolDecl *Protocol;
@@ -573,6 +582,9 @@ class NormalProtocolConformance : public RootProtocolConformance,
573582

574583
void resolveLazyInfo() const;
575584

585+
/// Set up global actor isolation for this conformance.
586+
void setGlobalActorIsolation(Type globalActorType);
587+
576588
public:
577589
NormalProtocolConformance(Type conformingType, ProtocolDecl *protocol,
578590
SourceLoc loc, DeclContext *dc,
@@ -674,16 +686,6 @@ class NormalProtocolConformance : public RootProtocolConformance,
674686
return getOptions().contains(ProtocolConformanceFlags::Preconcurrency);
675687
}
676688

677-
/// Whether this is a global-actor isolated conformance.
678-
bool isGlobalActorIsolated() const {
679-
return getOptions().contains(
680-
ProtocolConformanceFlags::GlobalActorIsolated);
681-
}
682-
683-
TypeExpr *getGlobalActorIsolation() const {
684-
return globalActorIsolation;
685-
}
686-
687689
/// Retrieve the location of `@preconcurrency`, if there is one and it is
688690
/// known.
689691
SourceLoc getPreconcurrencyLoc() const { return PreconcurrencyLoc; }

lib/AST/ProtocolConformance.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,17 @@ void NormalProtocolConformance::resolveLazyInfo() const {
474474
loader->finishNormalConformance(mutableThis, LoaderContextData);
475475
}
476476

477+
void NormalProtocolConformance::setGlobalActorIsolation(Type globalActorType) {
478+
ASTContext &ctx = getDeclContext()->getASTContext();
479+
if (globalActorIsolation)
480+
globalActorIsolation->setType(MetatypeType::get(globalActorType));
481+
else
482+
globalActorIsolation = TypeExpr::createImplicit(globalActorType, ctx);
483+
484+
Bits.NormalProtocolConformance.Options |=
485+
static_cast<unsigned>(ProtocolConformanceFlags::GlobalActorIsolated);
486+
}
487+
477488
void NormalProtocolConformance::setLazyLoader(LazyConformanceLoader *loader,
478489
uint64_t contextData) {
479490
assert(!Loader && "already has a loader");

lib/AST/ProtocolConformanceRef.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ bool ProtocolConformanceRef::forEachIsolatedConformance(
406406
auto concrete = getConcrete();
407407
if (auto normal =
408408
dyn_cast<NormalProtocolConformance>(concrete->getRootConformance())) {
409-
if (normal->isGlobalActorIsolated()) {
409+
if (normal->isIsolated()) {
410410
if (body(concrete))
411411
return true;
412412
}

lib/AST/TypeCheckRequests.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1381,7 +1381,18 @@ bool ConformanceIsolationRequest::isCached() const {
13811381
if (!rootNormal)
13821382
return false;
13831383

1384-
return rootNormal->isGlobalActorIsolated();
1384+
if (rootNormal->globalActorIsolation)
1385+
return true;
1386+
1387+
// If we might infer conformance isolation, then we should cache the result.
1388+
auto dc = rootNormal->getDeclContext();
1389+
auto nominal = dc->getSelfNominalTypeDecl();
1390+
if (nominal &&
1391+
((isa<ClassDecl>(nominal) && cast<ClassDecl>(nominal)->isActor()) ||
1392+
nominal->getSemanticAttrs().hasAttribute<NonisolatedAttr>()))
1393+
return false;
1394+
1395+
return true;
13851396
}
13861397

13871398
//----------------------------------------------------------------------------//

lib/IRGen/GenProto.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,6 @@
9494
using namespace swift;
9595
using namespace irgen;
9696

97-
namespace swift {
98-
// FIXME: Move this on to ProtocolConformance?
99-
ActorIsolation getConformanceIsolation(ProtocolConformance *conformance);
100-
}
101-
10297
namespace {
10398

10499
/// A class for computing how to pass arguments to a polymorphic
@@ -2238,10 +2233,11 @@ namespace {
22382233
void addFlags() {
22392234
// Miscellaneous flags.
22402235
if (auto conf = dyn_cast<NormalProtocolConformance>(Conformance)) {
2236+
auto isolation = conf->getIsolation();
22412237
Flags = Flags.withIsRetroactive(conf->isRetroactive());
22422238
Flags = Flags.withIsSynthesizedNonUnique(conf->isSynthesizedNonUnique());
22432239
Flags = Flags.withIsConformanceOfProtocol(conf->isConformanceOfProtocol());
2244-
Flags = Flags.withHasGlobalActorIsolation(conf->isGlobalActorIsolated());
2240+
Flags = Flags.withHasGlobalActorIsolation(isolation.isGlobalActor());
22452241
} else {
22462242
Flags = Flags.withIsRetroactive(false)
22472243
.withIsSynthesizedNonUnique(false);
@@ -2435,13 +2431,11 @@ namespace {
24352431
return;
24362432

24372433
auto normal = cast<NormalProtocolConformance>(Conformance);
2438-
assert(normal->isGlobalActorIsolated());
24392434
auto nominal = normal->getDeclContext()->getSelfNominalTypeDecl();
24402435

24412436
// Add global actor type.
24422437
auto sig = nominal->getGenericSignatureOfContext();
2443-
auto isolation = getConformanceIsolation(
2444-
const_cast<RootProtocolConformance *>(Conformance));
2438+
auto isolation = Conformance->getIsolation();
24452439
assert(isolation.isGlobalActor());
24462440
Type globalActorType = isolation.getGlobalActor();
24472441
auto globalActorTypeName = IGM.getTypeRef(

lib/Sema/CSDiagnostics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9568,7 +9568,7 @@ bool DisallowedIsolatedConformance::diagnoseAsError() {
95689568
emitDiagnostic(diag::isolated_conformance_with_sendable_simple,
95699569
conformance->getType(),
95709570
conformance->getProtocol()->getName(),
9571-
getConformanceIsolation(conformance));
9571+
conformance->getIsolation());
95729572

95739573
auto selectedOverload = getCalleeOverloadChoiceIfAvailable(getLocator());
95749574
if (!selectedOverload)

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7868,8 +7868,9 @@ bool swift::diagnoseNonSendableFromDeinit(
78687868
var->getDescriptiveKind(), var->getName());
78697869
}
78707870

7871-
ActorIsolation swift::getConformanceIsolation(ProtocolConformance *conformance) {
7872-
ASTContext &ctx = conformance->getDeclContext()->getASTContext();
7871+
ActorIsolation ProtocolConformance::getIsolation() const {
7872+
ASTContext &ctx = getDeclContext()->getASTContext();
7873+
auto conformance = const_cast<ProtocolConformance *>(this);
78737874
return evaluateOrDefault(
78747875
ctx.evaluator, ConformanceIsolationRequest{conformance},
78757876
ActorIsolation());
@@ -7882,10 +7883,10 @@ ConformanceIsolationRequest::evaluate(Evaluator &evaluator, ProtocolConformance
78827883
if (!rootNormal)
78837884
return ActorIsolation::forNonisolated(false);
78847885

7885-
if (!rootNormal->isGlobalActorIsolated())
7886+
if (!rootNormal->globalActorIsolation)
78867887
return ActorIsolation::forNonisolated(false);
78877888

7888-
auto globalActorTypeExpr = rootNormal->getGlobalActorIsolation();
7889+
auto globalActorTypeExpr = rootNormal->globalActorIsolation;
78897890
assert(globalActorTypeExpr && "global actor type is out-of-sync");
78907891

78917892
// If we don't already have a resolved global actor type, resolve it now.
@@ -7945,11 +7946,9 @@ namespace {
79457946
if (!normal)
79467947
return false;
79477948

7948-
if (!normal->isGlobalActorIsolated())
7949-
return false;
7950-
7951-
auto conformanceIsolation = getConformanceIsolation(concrete);
7952-
if (conformanceIsolation == getContextIsolation())
7949+
auto conformanceIsolation = concrete->getIsolation();
7950+
if (!conformanceIsolation.isGlobalActor() ||
7951+
conformanceIsolation == getContextIsolation())
79537952
return true;
79547953

79557954
badIsolatedConformances.push_back(concrete);
@@ -7966,7 +7965,7 @@ namespace {
79667965
auto firstConformance = badIsolatedConformances.front();
79677966
ctx.Diags.diagnose(
79687967
loc, diag::isolated_conformance_wrong_domain,
7969-
getConformanceIsolation(firstConformance),
7968+
firstConformance->getIsolation(),
79707969
firstConformance->getType(),
79717970
firstConformance->getProtocol()->getName(),
79727971
getContextIsolation());

lib/Sema/TypeCheckConcurrency.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -699,10 +699,6 @@ void introduceUnsafeInheritExecutorReplacements(
699699
void introduceUnsafeInheritExecutorReplacements(
700700
const DeclContext *dc, Type base, SourceLoc loc, LookupResult &result);
701701

702-
/// Determine the isolation of the given conformance. This only applies to
703-
/// the immediate conformance, not any conformances on which it depends.
704-
ActorIsolation getConformanceIsolation(ProtocolConformance *conformance);
705-
706702
/// Check for correct use of isolated conformances in the given reference.
707703
///
708704
/// This checks that any isolated conformances that occur in the given

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ void TypeChecker::diagnoseRequirementFailure(
938938
.IsolatedConformanceProto->isSpecificProtocol(
939939
KnownProtocolKind::SendableMetatype),
940940
req.getFirstType(),
941-
getConformanceIsolation(isolatedConformance));
941+
isolatedConformance->getIsolation());
942942
diagnosticNote = diag::type_does_not_inherit_or_conform_requirement;
943943
break;
944944
}

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2543,7 +2543,7 @@ checkIndividualConformance(NormalProtocolConformance *conformance) {
25432543
}
25442544

25452545
// Complain if the global-actor-isolated conformances are not enabled.
2546-
if (conformance->isGlobalActorIsolated() &&
2546+
if (conformance->isIsolated() &&
25472547
!Context.LangOpts.hasFeature(Feature::IsolatedConformances)) {
25482548
Context.Diags.diagnose(
25492549
ComplainLoc, diag::isolated_conformance_experimental_feature);
@@ -3382,18 +3382,20 @@ ConformanceChecker::checkActorIsolation(ValueDecl *requirement,
33823382
}
33833383

33843384
return std::nullopt;
3385-
case ActorReferenceResult::EntersActor:
3385+
case ActorReferenceResult::EntersActor: {
33863386
// If the conformance itself is isolated to the same isolation domain as
33873387
// the witness, treat this as being in the same concurrency domain.
3388-
if (Conformance->isGlobalActorIsolated() &&
3389-
refResult.isolation == getConformanceIsolation(Conformance)) {
3388+
auto conformanceIsolation = Conformance->getIsolation();
3389+
if (conformanceIsolation.isGlobalActor() &&
3390+
refResult.isolation == conformanceIsolation) {
33903391
sameConcurrencyDomain = true;
33913392
isIsolatedConformance = true;
33923393
}
33933394

33943395
// Handled below.
33953396
break;
33963397
}
3398+
}
33973399

33983400
// Keep track of what modifiers are missing from the requirement and witness,
33993401
// so we can decide what to diagnose.
@@ -3572,7 +3574,7 @@ ConformanceChecker::checkActorIsolation(ValueDecl *requirement,
35723574
// Another way to address the issue is to mark the conformance as
35733575
// isolated to the global actor or "@preconcurrency".
35743576
if (Conformance->getSourceKind() == ConformanceEntryKind::Explicit &&
3575-
!Conformance->isGlobalActorIsolated() &&
3577+
!Conformance->getIsolation().isGlobalActor() &&
35763578
!Conformance->isPreconcurrency() &&
35773579
!suggestedPreconcurrencyOrIsolated &&
35783580
!requirementIsolation.isActorIsolated() &&
@@ -5218,20 +5220,22 @@ static void ensureRequirementsAreSatisfied(ASTContext &ctx,
52185220
}
52195221

52205222
if (!diagnosedIsolatedConformanceIssue) {
5223+
auto outerIsolation = conformance->getIsolation();
52215224
bool foundIssue = ProtocolConformanceRef(assocConf)
52225225
.forEachIsolatedConformance(
52235226
[&](ProtocolConformance *isolatedConformance) {
5227+
auto innerIsolation = isolatedConformance->getIsolation();
5228+
52245229
// If the conformance we're checking isn't isolated at all, it
52255230
// needs "isolated".
5226-
if (!conformance->isGlobalActorIsolated()) {
5227-
auto isolation = getConformanceIsolation(isolatedConformance);
5231+
if (!outerIsolation.isGlobalActor()) {
52285232
std::string globalActorStr = "@" +
5229-
isolation.getGlobalActor().getString();
5233+
innerIsolation.getGlobalActor().getString();
52305234
ctx.Diags.diagnose(
52315235
conformance->getLoc(),
52325236
diag::nonisolated_conformance_depends_on_isolated_conformance,
52335237
typeInContext, conformance->getProtocol()->getName(),
5234-
getConformanceIsolation(isolatedConformance),
5238+
innerIsolation,
52355239
isolatedConformance->getType(),
52365240
isolatedConformance->getProtocol()->getName(),
52375241
globalActorStr
@@ -5243,8 +5247,6 @@ static void ensureRequirementsAreSatisfied(ASTContext &ctx,
52435247

52445248
// The conformance is isolated, but we need it to have the same
52455249
// isolation as the other isolated conformance we found.
5246-
auto outerIsolation = getConformanceIsolation(conformance);
5247-
auto innerIsolation = getConformanceIsolation(isolatedConformance);
52485250
if (outerIsolation != innerIsolation) {
52495251
ctx.Diags.diagnose(
52505252
conformance->getLoc(),

0 commit comments

Comments
 (0)