33
33
34
34
using namespace swift ;
35
35
36
+ static ActorIsolation getOverriddenIsolationFor (const ValueDecl *value);
37
+
36
38
// / Determine whether it makes sense to infer an attribute in the given
37
39
// / context.
38
40
static bool shouldInferAttributeInContext (const DeclContext *dc) {
@@ -1663,32 +1665,42 @@ static bool wasLegacyEscapingUseRestriction(AbstractFunctionDecl *fn) {
1663
1665
assert (fn->getDeclContext ()->getSelfClassDecl ()->isAnyActor ());
1664
1666
assert (isa<ConstructorDecl>(fn) || isa<DestructorDecl>(fn));
1665
1667
1666
- // according to today's isolation, determine whether it use to have the
1667
- // escaping-use restriction
1668
- switch (getActorIsolation (fn).getKind ()) {
1668
+ auto isolationKind = getActorIsolation (fn).getKind ();
1669
+ if (isa<DestructorDecl>(fn)) {
1670
+ switch (isolationKind) {
1671
+ case ActorIsolation::GlobalActor:
1672
+ case ActorIsolation::ActorInstance:
1673
+ // Isolated deinits did not exist before
1674
+ return false ;
1675
+ case ActorIsolation::Nonisolated:
1676
+ case ActorIsolation::NonisolatedUnsafe:
1677
+ case ActorIsolation::Unspecified:
1678
+ assert (!fn->hasAsync ());
1679
+ return true ;
1680
+ case ActorIsolation::Erased:
1681
+ llvm_unreachable (" destructor decl cannot have erased isolation" );
1682
+ }
1683
+ } else if (auto *ctor = dyn_cast<ConstructorDecl>(fn)) {
1684
+ switch (isolationKind) {
1669
1685
case ActorIsolation::Nonisolated:
1670
1686
case ActorIsolation::NonisolatedUnsafe:
1671
1687
case ActorIsolation::GlobalActor:
1672
1688
// convenience inits did not have the restriction.
1673
- if (auto *ctor = dyn_cast<ConstructorDecl>(fn))
1674
- if (ctor->isConvenienceInit ())
1675
- return false ;
1676
-
1677
- break ; // goto basic case
1678
-
1689
+ if (ctor->isConvenienceInit ())
1690
+ return false ;
1691
+ break ;
1679
1692
case ActorIsolation::ActorInstance:
1680
1693
// none of these had the restriction affect them.
1681
1694
assert (fn->hasAsync ());
1682
1695
return false ;
1683
-
1684
1696
case ActorIsolation::Erased:
1685
1697
llvm_unreachable (" function decl cannot have erased isolation" );
1686
1698
1687
1699
case ActorIsolation::Unspecified:
1688
1700
// this is basically just objc-marked inits.
1689
1701
break ;
1690
- };
1691
-
1702
+ }
1703
+ }
1692
1704
return !(fn->hasAsync ()); // basic case: not async = had restriction.
1693
1705
}
1694
1706
@@ -4388,30 +4400,64 @@ getIsolationFromAttributes(const Decl *decl, bool shouldDiagnose = true,
4388
4400
bool onlyExplicit = false ) {
4389
4401
// Look up attributes on the declaration that can affect its actor isolation.
4390
4402
// If any of them are present, use that attribute.
4403
+ auto isolatedAttr = decl->getAttrs ().getAttribute <IsolatedAttr>();
4391
4404
auto nonisolatedAttr = decl->getAttrs ().getAttribute <NonisolatedAttr>();
4392
4405
auto globalActorAttr = decl->getGlobalActorAttr ();
4393
4406
4394
4407
// Remove implicit attributes if we only care about explicit ones.
4395
4408
if (onlyExplicit) {
4396
4409
if (nonisolatedAttr && nonisolatedAttr->isImplicit ())
4397
4410
nonisolatedAttr = nullptr ;
4411
+ if (isolatedAttr && isolatedAttr->isImplicit ())
4412
+ isolatedAttr = nullptr ;
4398
4413
if (globalActorAttr && globalActorAttr->first ->isImplicit ())
4399
4414
globalActorAttr = std::nullopt;
4400
4415
}
4401
4416
4402
- unsigned numIsolationAttrs =
4403
- (nonisolatedAttr ? 1 : 0 ) + (globalActorAttr ? 1 : 0 );
4404
- if (numIsolationAttrs == 0 )
4417
+ unsigned numIsolationAttrs = (isolatedAttr ? 1 : 0 ) +
4418
+ (nonisolatedAttr ? 1 : 0 ) +
4419
+ (globalActorAttr ? 1 : 0 );
4420
+ if (numIsolationAttrs == 0 ) {
4421
+ if (isa<DestructorDecl>(decl) && !decl->isImplicit ()) {
4422
+ return ActorIsolation::forNonisolated (false );
4423
+ }
4405
4424
return std::nullopt;
4425
+ }
4406
4426
4407
4427
// Only one such attribute is valid, but we only actually care of one of
4408
4428
// them is a global actor.
4409
4429
if (numIsolationAttrs > 1 && globalActorAttr && shouldDiagnose) {
4410
- decl->diagnose (diag::actor_isolation_multiple_attr, decl,
4411
- nonisolatedAttr->getAttrName (),
4412
- globalActorAttr->second ->getName ().str ())
4413
- .highlight (nonisolatedAttr->getRangeWithAt ())
4414
- .highlight (globalActorAttr->first ->getRangeWithAt ());
4430
+ struct NameAndRange {
4431
+ StringRef name;
4432
+ SourceRange range;
4433
+ };
4434
+
4435
+ llvm::SmallVector<NameAndRange, 3 > attributes;
4436
+ if (isolatedAttr) {
4437
+ attributes.push_back ({.name = isolatedAttr->getAttrName (),
4438
+ .range = isolatedAttr->getRangeWithAt ()});
4439
+ }
4440
+ if (nonisolatedAttr) {
4441
+ attributes.push_back ({.name = nonisolatedAttr->getAttrName (),
4442
+ .range = nonisolatedAttr->getRangeWithAt ()});
4443
+ }
4444
+ if (globalActorAttr) {
4445
+ attributes.push_back ({.name = globalActorAttr->second ->getName ().str (),
4446
+ .range = globalActorAttr->first ->getRangeWithAt ()});
4447
+ }
4448
+ if (attributes.size () == 3 ) {
4449
+ decl->diagnose (diag::actor_isolation_multiple_attr_3, decl,
4450
+ attributes[0 ].name , attributes[1 ].name , attributes[2 ].name )
4451
+ .highlight (attributes[0 ].range )
4452
+ .highlight (attributes[1 ].range )
4453
+ .highlight (attributes[2 ].range );
4454
+ } else {
4455
+ assert (attributes.size () == 2 );
4456
+ decl->diagnose (diag::actor_isolation_multiple_attr_2, decl,
4457
+ attributes[0 ].name , attributes[1 ].name )
4458
+ .highlight (attributes[0 ].range )
4459
+ .highlight (attributes[1 ].range );
4460
+ }
4415
4461
}
4416
4462
4417
4463
// If the declaration is explicitly marked 'nonisolated', report it as
@@ -4420,6 +4466,54 @@ getIsolationFromAttributes(const Decl *decl, bool shouldDiagnose = true,
4420
4466
return ActorIsolation::forNonisolated (nonisolatedAttr->isUnsafe ());
4421
4467
}
4422
4468
4469
+ // If the declaration is explicitly marked 'isolated', infer actor isolation
4470
+ // from the context. Currently applies only to DestructorDecl
4471
+ if (isolatedAttr) {
4472
+ assert (isa<DestructorDecl>(decl));
4473
+
4474
+ auto dc = decl->getDeclContext ();
4475
+ auto selfTypeDecl = dc->getSelfNominalTypeDecl ();
4476
+ std::optional<ActorIsolation> result;
4477
+ if (selfTypeDecl) {
4478
+ if (selfTypeDecl->isAnyActor ()) {
4479
+ result = ActorIsolation::forActorInstanceSelf (selfTypeDecl);
4480
+ } else {
4481
+ // If the declaration is in an extension that has one of the isolation
4482
+ // attributes, use that.
4483
+ if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
4484
+ result = getIsolationFromAttributes (ext);
4485
+ }
4486
+
4487
+ if (!result) {
4488
+ result = getActorIsolation (selfTypeDecl);
4489
+ }
4490
+ }
4491
+
4492
+ if (!result || !result->isActorIsolated ()) {
4493
+ if (shouldDiagnose) {
4494
+ ASTContext &ctx = decl->getASTContext ();
4495
+ ctx.Diags .diagnose (isolatedAttr->getLocation (),
4496
+ diag::isolated_deinit_no_isolation,
4497
+ selfTypeDecl->getName ());
4498
+ }
4499
+ // Try to use isolation of the overridden decl as a recovery strategy.
4500
+ // This prevents additions errors about mismatched isolation.
4501
+ if (auto value = dyn_cast<ValueDecl>(decl)) {
4502
+ ValueDecl *overriddenValue = value->getOverriddenDeclOrSuperDeinit ();
4503
+ if (overriddenValue) {
4504
+ // use the overridden decl's iso as the default isolation for this
4505
+ // decl.
4506
+ auto overriddenIsolation = getOverriddenIsolationFor (value);
4507
+ if (overriddenIsolation.isActorIsolated ()) {
4508
+ result = overriddenIsolation;
4509
+ }
4510
+ }
4511
+ }
4512
+ }
4513
+ }
4514
+ return result;
4515
+ }
4516
+
4423
4517
// If the declaration is marked with a global actor, report it as being
4424
4518
// part of that global actor.
4425
4519
if (globalActorAttr) {
@@ -4747,9 +4841,15 @@ getMemberIsolationPropagation(const ValueDecl *value) {
4747
4841
return MemberIsolationPropagation::GlobalActor;
4748
4842
4749
4843
case DeclKind::Constructor:
4750
- case DeclKind::Destructor:
4751
4844
return MemberIsolationPropagation::AnyIsolation;
4752
4845
4846
+ case DeclKind::Destructor:
4847
+ if (value->getAttrs ().getAttribute <IsolatedAttr>()) {
4848
+ return MemberIsolationPropagation::AnyIsolation;
4849
+ } else {
4850
+ return std::nullopt;
4851
+ }
4852
+
4753
4853
case DeclKind::Func:
4754
4854
case DeclKind::Accessor:
4755
4855
case DeclKind::Subscript:
@@ -4917,7 +5017,7 @@ namespace {
4917
5017
4918
5018
// / Return the isolation of the declaration overridden by this declaration,
4919
5019
// / in the context of the
4920
- static ActorIsolation getOverriddenIsolationFor (ValueDecl *value) {
5020
+ static ActorIsolation getOverriddenIsolationFor (const ValueDecl *value) {
4921
5021
auto overridden = value->getOverriddenDeclOrSuperDeinit ();
4922
5022
assert (overridden && " Doesn't have an overridden declaration" );
4923
5023
@@ -5086,10 +5186,6 @@ static void addAttributesForActorIsolation(ValueDecl *value,
5086
5186
}
5087
5187
}
5088
5188
5089
- static bool isImplicitDeinit (ValueDecl *value) {
5090
- return isa<DestructorDecl>(value) && value->isImplicit ();
5091
- }
5092
-
5093
5189
ActorIsolation ActorIsolationRequest::evaluate (Evaluator &evaluator,
5094
5190
ValueDecl *value) const {
5095
5191
// If this declaration has actor-isolated "self", it's isolated to that
@@ -5098,16 +5194,6 @@ ActorIsolation ActorIsolationRequest::evaluate(Evaluator &evaluator,
5098
5194
auto actor = value->getDeclContext ()->getSelfNominalTypeDecl ();
5099
5195
assert (actor && " could not find the actor that 'self' is isolated to" );
5100
5196
5101
- // Bootstrapping hack: force _Concurrency.MainActor.deinit() to be
5102
- // non-isolated even when importing from host SDK's swiftmodule without
5103
- // `nonisolated` attribute.
5104
- if (isa<DestructorDecl>(value) && actor->getName ().is (" MainActor" ) &&
5105
- actor->getDeclContext ()->isModuleScopeContext () &&
5106
- actor->getDeclContext ()->getParentModule ()->getABIName ().is (" Swift" )) {
5107
- auto isolation = ActorIsolation::forNonisolated (false );
5108
- addAttributesForActorIsolation (value, isolation);
5109
- return isolation;
5110
- }
5111
5197
return ActorIsolation::forActorInstanceSelf (value);
5112
5198
}
5113
5199
@@ -5444,12 +5530,7 @@ ActorIsolation ActorIsolationRequest::evaluate(Evaluator &evaluator,
5444
5530
// has isolation, use that.
5445
5531
if (auto selfTypeDecl = value->getDeclContext ()->getSelfNominalTypeDecl ()) {
5446
5532
if (auto selfTypeIsolation = getActorIsolation (selfTypeDecl)) {
5447
- if (isImplicitDeinit (value)) {
5448
- return inferredIsolation (ActorIsolation::forUnspecified (),
5449
- onlyGlobal);
5450
- } else {
5451
- return inferredIsolation (selfTypeIsolation, onlyGlobal);
5452
- }
5533
+ return inferredIsolation (selfTypeIsolation, onlyGlobal);
5453
5534
}
5454
5535
}
5455
5536
}
@@ -5495,8 +5576,12 @@ bool HasIsolatedSelfRequest::evaluate(
5495
5576
5496
5577
// Check whether this member can be isolated to an actor at all.
5497
5578
auto memberIsolation = getMemberIsolationPropagation (value);
5498
- if (!memberIsolation)
5579
+ if (!memberIsolation) {
5580
+ // Actors don't have inheritance (except inheriting from NSObject),
5581
+ // but if it were introduced, we would need to check for isolation
5582
+ // of the deinit in the super class.
5499
5583
return false ;
5584
+ }
5500
5585
5501
5586
switch (*memberIsolation) {
5502
5587
case MemberIsolationPropagation::GlobalActor:
@@ -5508,13 +5593,15 @@ bool HasIsolatedSelfRequest::evaluate(
5508
5593
5509
5594
// Check whether the default isolation was overridden by any attributes on
5510
5595
// this declaration.
5511
- if (getIsolationFromAttributes (value))
5512
- return false ;
5513
-
5596
+ auto attrIsolation = getIsolationFromAttributes (value);
5514
5597
// ... or its extension context.
5515
- if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
5516
- if (getIsolationFromAttributes (ext))
5517
- return false ;
5598
+ if (!attrIsolation) {
5599
+ if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
5600
+ attrIsolation = getIsolationFromAttributes (ext);
5601
+ }
5602
+ }
5603
+ if (attrIsolation) {
5604
+ return attrIsolation == ActorIsolation::forActorInstanceSelf (selfTypeDecl);
5518
5605
}
5519
5606
5520
5607
// If this is a variable, check for a property wrapper that alters its
@@ -5546,24 +5633,6 @@ bool HasIsolatedSelfRequest::evaluate(
5546
5633
return false ;
5547
5634
}
5548
5635
5549
- if (isImplicitDeinit (value)) {
5550
- // Actors don't have inheritance (except inheriting from NSObject),
5551
- // but check for it anyway, just in case it will be re-introduced later.
5552
- ValueDecl *overriddenValue = value->getOverriddenDeclOrSuperDeinit ();
5553
- if (overriddenValue) {
5554
- ActorIsolation isolation = getOverriddenIsolationFor (value);
5555
- if (isolation.isActorIsolated ()) {
5556
- return isolation.getKind () == ActorIsolation::ActorInstance;
5557
- }
5558
- }
5559
-
5560
- // No need to isolate implicit deinit, unless there is already an isolated
5561
- // one in the superclass
5562
- addAttributesForActorIsolation (value,
5563
- ActorIsolation::forNonisolated (false ));
5564
- return false ;
5565
- }
5566
-
5567
5636
return true ;
5568
5637
}
5569
5638
0 commit comments