Skip to content

Commit 5925cb2

Browse files
authored
Merge pull request #37619 from apple/revert-37462-remove-actor-independent
Revert "Remove `@actorIndependent` attribute."
2 parents a8e5ba5 + 7c0b50e commit 5925cb2

25 files changed

+374
-81
lines changed

include/swift/AST/Attr.def

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,12 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(actor, Actor,
574574
APIBreakingToAdd | APIBreakingToRemove,
575575
102)
576576

577-
// Unused attribute 103
577+
DECL_ATTR(actorIndependent, ActorIndependent,
578+
OnClass | OnStruct | OnEnum | OnExtension | OnFunc | OnConstructor |
579+
OnVar | OnSubscript | ConcurrencyOnly |
580+
ABIBreakingToAdd | ABIBreakingToRemove |
581+
APIBreakingToAdd | APIBreakingToRemove,
582+
103)
578583

579584
SIMPLE_DECL_ATTR(globalActor, GlobalActor,
580585
OnClass | OnStruct | OnEnum | ConcurrencyOnly |

include/swift/AST/Attr.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ class DeclAttribute : public AttributeBase {
162162
kind : NumInlineKindBits
163163
);
164164

165+
SWIFT_INLINE_BITFIELD(ActorIndependentAttr, DeclAttribute, NumActorIndependentKindBits,
166+
kind : NumActorIndependentKindBits
167+
);
168+
165169
SWIFT_INLINE_BITFIELD(OptimizeAttr, DeclAttribute, NumOptimizationModeBits,
166170
mode : NumOptimizationModeBits
167171
);
@@ -1212,6 +1216,25 @@ class ReferenceOwnershipAttr : public DeclAttribute {
12121216
}
12131217
};
12141218

1219+
/// Represents an actorIndependent/actorIndependent(unsafe) decl attribute.
1220+
class ActorIndependentAttr : public DeclAttribute {
1221+
public:
1222+
ActorIndependentAttr(SourceLoc atLoc, SourceRange range, ActorIndependentKind kind)
1223+
: DeclAttribute(DAK_ActorIndependent, atLoc, range, /*Implicit=*/false) {
1224+
Bits.ActorIndependentAttr.kind = unsigned(kind);
1225+
}
1226+
1227+
ActorIndependentAttr(ActorIndependentKind kind, bool IsImplicit=false)
1228+
: ActorIndependentAttr(SourceLoc(), SourceRange(), kind) {
1229+
setImplicit(IsImplicit);
1230+
}
1231+
1232+
ActorIndependentKind getKind() const { return ActorIndependentKind(Bits.ActorIndependentAttr.kind); }
1233+
static bool classof(const DeclAttribute *DA) {
1234+
return DA->getKind() == DAK_ActorIndependent;
1235+
}
1236+
};
1237+
12151238
/// Defines the attribute that we use to model documentation comments.
12161239
class RawDocCommentAttr : public DeclAttribute {
12171240
/// Source range of the attached comment. This comment is located before

include/swift/AST/AttrKind.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@ enum : unsigned { NumInlineKindBits =
8080
countBitsUsed(static_cast<unsigned>(InlineKind::Last_InlineKind)) };
8181

8282

83+
/// Indicates whether an actorIndependent decl is unsafe or not
84+
enum class ActorIndependentKind : uint8_t {
85+
Safe = 0,
86+
Unsafe = 1,
87+
Last_InlineKind = Unsafe
88+
};
89+
90+
enum : unsigned { NumActorIndependentKindBits =
91+
countBitsUsed(static_cast<unsigned>(ActorIndependentKind::Last_InlineKind)) };
92+
8393
/// This enum represents the possible values of the @_effects attribute.
8494
/// These values are ordered from the strongest guarantee to the weakest,
8595
/// so please do not reorder existing values.

include/swift/AST/DiagnosticsSema.def

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4489,12 +4489,23 @@ ERROR(concurrent_value_inherit,none,
44894489
"%select{| other than 'NSObject'}0",
44904490
(bool, DeclName))
44914491

4492+
ERROR(actorindependent_let,none,
4493+
"'@actorIndependent' is meaningless on 'let' declarations because "
4494+
"they are immutable",
4495+
())
4496+
ERROR(actorindependent_mutable_storage,none,
4497+
"'@actorIndependent' can not be applied to stored properties",
4498+
())
4499+
ERROR(actorindependent_local_var,none,
4500+
"'@actorIndependent' can not be applied to local variables",
4501+
())
4502+
44924503
ERROR(nonisolated_let,none,
44934504
"'nonisolated' is meaningless on 'let' declarations because "
44944505
"they are immutable",
44954506
())
44964507
ERROR(nonisolated_mutable_storage,none,
4497-
"'nonisolated' can not be applied to stored properties",
4508+
"nonisolated' can not be applied to stored properties",
44984509
())
44994510
ERROR(nonisolated_local_var,none,
45004511
"'nonisolated' can not be applied to local variables",

lib/AST/Attr.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
790790
case DAK_ReferenceOwnership:
791791
case DAK_Effects:
792792
case DAK_Optimize:
793+
case DAK_ActorIndependent:
793794
if (DeclAttribute::isDeclModifier(getKind())) {
794795
Printer.printKeyword(getAttrName(), Options);
795796
} else if (Options.IsForSwiftInterface && getKind() == DAK_ResultBuilder) {
@@ -1177,6 +1178,15 @@ StringRef DeclAttribute::getAttrName() const {
11771178
}
11781179
llvm_unreachable("Invalid inline kind");
11791180
}
1181+
case DAK_ActorIndependent: {
1182+
switch (cast<ActorIndependentAttr>(this)->getKind()) {
1183+
case ActorIndependentKind::Safe:
1184+
return "actorIndependent";
1185+
case ActorIndependentKind::Unsafe:
1186+
return "actorIndependent(unsafe)";
1187+
}
1188+
llvm_unreachable("Invalid actorIndependent kind");
1189+
}
11801190
case DAK_Optimize: {
11811191
switch (cast<OptimizeAttr>(this)->getMode()) {
11821192
case OptimizationMode::NoOptimization:

lib/ClangImporter/ImportDecl.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8706,14 +8706,6 @@ void ClangImporter::Implementation::importAttributes(
87068706
continue;
87078707
}
87088708

8709-
// Hard-code @actorIndependent, until Objective-C clients start
8710-
// using nonisolated.
8711-
if (swiftAttr->getAttribute() == "@actorIndependent") {
8712-
auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true);
8713-
MappedDecl->getAttrs().add(attr);
8714-
continue;
8715-
}
8716-
87178709
// Dig out a buffer with the attribute text.
87188710
unsigned bufferID = getClangSwiftAttrSourceBuffer(
87198711
swiftAttr->getAttribute());
@@ -9638,8 +9630,9 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
96389630

96399631
// Mark the function transparent so that we inline it away completely.
96409632
func->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
9641-
auto nonisolatedAttr = new (C) NonisolatedAttr(/*IsImplicit=*/true);
9642-
var->getAttrs().add(nonisolatedAttr);
9633+
auto actorIndependentAttr = new (C) ActorIndependentAttr(
9634+
ActorIndependentKind::Unsafe, /*IsImplicit=*/true);
9635+
var->getAttrs().add(actorIndependentAttr);
96439636

96449637
// Set the function up as the getter.
96459638
makeComputed(var, func, nullptr);

lib/Parse/ParseDecl.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,6 +1784,45 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
17841784
break;
17851785
}
17861786

1787+
case DAK_ActorIndependent: {
1788+
// if no option is provided, then it's the 'safe' version.
1789+
if (!consumeIf(tok::l_paren)) {
1790+
if (!DiscardAttribute) {
1791+
AttrRange = SourceRange(Loc, Tok.getRange().getStart());
1792+
Attributes.add(new (Context) ActorIndependentAttr(AtLoc, AttrRange,
1793+
ActorIndependentKind::Safe));
1794+
}
1795+
break;
1796+
}
1797+
1798+
// otherwise, make sure it looks like an identifier.
1799+
if (Tok.isNot(tok::identifier)) {
1800+
diagnose(Loc, diag::attr_expected_option_such_as, AttrName, "unsafe");
1801+
return false;
1802+
}
1803+
1804+
// make sure the identifier is 'unsafe'
1805+
if (Tok.getText() != "unsafe") {
1806+
diagnose(Loc, diag::attr_unknown_option, Tok.getText(), AttrName);
1807+
return false;
1808+
}
1809+
1810+
consumeToken(tok::identifier);
1811+
AttrRange = SourceRange(Loc, Tok.getRange().getStart());
1812+
1813+
if (!consumeIf(tok::r_paren)) {
1814+
diagnose(Loc, diag::attr_expected_rparen, AttrName,
1815+
DeclAttribute::isDeclModifier(DK));
1816+
return false;
1817+
}
1818+
1819+
if (!DiscardAttribute)
1820+
Attributes.add(new (Context) ActorIndependentAttr(AtLoc, AttrRange,
1821+
ActorIndependentKind::Unsafe));
1822+
1823+
break;
1824+
}
1825+
17871826
case DAK_Optimize: {
17881827
if (!consumeIf(tok::l_paren)) {
17891828
diagnose(Loc, diag::attr_expected_lparen, AttrName,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
251251
void visitTransposeAttr(TransposeAttr *attr);
252252

253253
void visitActorAttr(ActorAttr *attr);
254+
void visitActorIndependentAttr(ActorIndependentAttr *attr);
254255
void visitGlobalActorAttr(GlobalActorAttr *attr);
255256
void visitAsyncAttr(AsyncAttr *attr);
256257
void visitSpawnAttr(SpawnAttr *attr);
@@ -5381,6 +5382,48 @@ void AttributeChecker::visitActorAttr(ActorAttr *attr) {
53815382
(void)classDecl->isActor();
53825383
}
53835384

5385+
void AttributeChecker::visitActorIndependentAttr(ActorIndependentAttr *attr) {
5386+
// @actorIndependent can be applied to global and static/class variables
5387+
// that do not have storage.
5388+
auto dc = D->getDeclContext();
5389+
if (auto var = dyn_cast<VarDecl>(D)) {
5390+
// @actorIndependent is meaningless on a `let`.
5391+
if (var->isLet()) {
5392+
diagnoseAndRemoveAttr(attr, diag::actorindependent_let);
5393+
return;
5394+
}
5395+
5396+
// @actorIndependent can not be applied to stored properties, unless if
5397+
// the 'unsafe' option was specified
5398+
if (var->hasStorage()) {
5399+
switch (attr->getKind()) {
5400+
case ActorIndependentKind::Safe:
5401+
diagnoseAndRemoveAttr(attr, diag::actorindependent_mutable_storage);
5402+
return;
5403+
5404+
case ActorIndependentKind::Unsafe:
5405+
break;
5406+
}
5407+
}
5408+
5409+
// @actorIndependent can not be applied to local properties.
5410+
if (dc->isLocalContext()) {
5411+
diagnoseAndRemoveAttr(attr, diag::actorindependent_local_var);
5412+
return;
5413+
}
5414+
5415+
// If this is a static or global variable, we're all set.
5416+
if (dc->isModuleScopeContext() ||
5417+
(dc->isTypeContext() && var->isStatic())) {
5418+
return;
5419+
}
5420+
}
5421+
5422+
if (auto VD = dyn_cast<ValueDecl>(D)) {
5423+
(void)getActorIsolation(VD);
5424+
}
5425+
}
5426+
53845427
void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
53855428
// 'nonisolated' can be applied to global and static/class variables
53865429
// that do not have storage.
@@ -5398,7 +5441,7 @@ void AttributeChecker::visitNonisolatedAttr(NonisolatedAttr *attr) {
53985441
return;
53995442
}
54005443

5401-
// nonisolated can not be applied to local properties.
5444+
// @actorIndependent can not be applied to local properties.
54025445
if (dc->isLocalContext()) {
54035446
diagnoseAndRemoveAttr(attr, diag::nonisolated_local_var);
54045447
return;
@@ -5551,6 +5594,10 @@ class ClosureAttributeChecker
55515594
// Nothing else to check.
55525595
}
55535596

5597+
void visitActorIndependentAttr(ActorIndependentAttr *attr) {
5598+
// Nothing else to check.
5599+
}
5600+
55545601
void visitCustomAttr(CustomAttr *attr) {
55555602
// Check whether this custom attribute is the global actor attribute.
55565603
auto globalActorAttr = evaluateOrDefault(

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,6 +2115,9 @@ namespace {
21152115
AbstractClosureExpr *closure) {
21162116
// If the closure specifies a global actor, use it.
21172117
if (auto explicitClosure = dyn_cast<ClosureExpr>(closure)) {
2118+
if (explicitClosure->getAttrs().hasAttribute<ActorIndependentAttr>())
2119+
return ClosureActorIsolation::forIndependent();
2120+
21182121
if (Type globalActorType = resolveGlobalActorType(explicitClosure))
21192122
return ClosureActorIsolation::forGlobalActor(globalActorType);
21202123

@@ -2246,19 +2249,23 @@ static Optional<ActorIsolation> getIsolationFromAttributes(
22462249
const Decl *decl, bool shouldDiagnose = true, bool onlyExplicit = false) {
22472250
// Look up attributes on the declaration that can affect its actor isolation.
22482251
// If any of them are present, use that attribute.
2252+
auto independentAttr = decl->getAttrs().getAttribute<ActorIndependentAttr>();
22492253
auto nonisolatedAttr = decl->getAttrs().getAttribute<NonisolatedAttr>();
22502254
auto globalActorAttr = decl->getGlobalActorAttr();
22512255

22522256
// Remove implicit attributes if we only care about explicit ones.
22532257
if (onlyExplicit) {
2258+
if (independentAttr && independentAttr->isImplicit())
2259+
independentAttr = nullptr;
22542260
if (nonisolatedAttr && nonisolatedAttr->isImplicit())
22552261
nonisolatedAttr = nullptr;
22562262
if (globalActorAttr && globalActorAttr->first->isImplicit())
22572263
globalActorAttr = None;
22582264
}
22592265

22602266
unsigned numIsolationAttrs =
2261-
(nonisolatedAttr ? 1 : 0) + (globalActorAttr ? 1 : 0);
2267+
(nonisolatedAttr ? 1 : 0) + (independentAttr ? 1 : 0) +
2268+
(globalActorAttr ? 1 : 0);
22622269
if (numIsolationAttrs == 0)
22632270
return None;
22642271

@@ -2274,12 +2281,22 @@ static Optional<ActorIsolation> getIsolationFromAttributes(
22742281
}
22752282

22762283
if (globalActorAttr) {
2284+
StringRef nonisolatedAttrName;
2285+
SourceRange nonisolatedRange;
2286+
if (independentAttr) {
2287+
nonisolatedAttrName = independentAttr->getAttrName();
2288+
nonisolatedRange = independentAttr->getRangeWithAt();
2289+
} else {
2290+
nonisolatedAttrName = nonisolatedAttr->getAttrName();
2291+
nonisolatedRange = nonisolatedAttr->getRangeWithAt();
2292+
}
2293+
22772294
if (shouldDiagnose) {
22782295
decl->diagnose(
22792296
diag::actor_isolation_multiple_attr, decl->getDescriptiveKind(),
2280-
name, nonisolatedAttr->getAttrName(),
2297+
name, nonisolatedAttrName,
22812298
globalActorAttr->second->getName().str())
2282-
.highlight(nonisolatedAttr->getRangeWithAt())
2299+
.highlight(nonisolatedRange)
22832300
.highlight(globalActorAttr->first->getRangeWithAt());
22842301
}
22852302
}
@@ -2291,6 +2308,12 @@ static Optional<ActorIsolation> getIsolationFromAttributes(
22912308
return ActorIsolation::forIndependent();
22922309
}
22932310

2311+
// If the declaration is explicitly marked @actorIndependent, report it as
2312+
// independent.
2313+
if (independentAttr) {
2314+
return ActorIsolation::forIndependent();
2315+
}
2316+
22942317
// If the declaration is marked with a global actor, report it as being
22952318
// part of that global actor.
22962319
if (globalActorAttr) {
@@ -2380,7 +2403,7 @@ static Optional<ActorIsolation> getIsolationFromWitnessedRequirements(
23802403
llvm_unreachable("protocol requirements cannot be actor instances");
23812404

23822405
case ActorIsolation::Independent:
2383-
// We only need one nonisolated.
2406+
// We only need one @actorIndependent.
23842407
if (sawActorIndependent)
23852408
return true;
23862409

@@ -2593,7 +2616,8 @@ ActorIsolation ActorIsolationRequest::evaluate(
25932616
if (onlyGlobal)
25942617
return ActorIsolation::forUnspecified();
25952618

2596-
value->getAttrs().add(new (ctx) NonisolatedAttr(/*IsImplicit=*/true));
2619+
value->getAttrs().add(new (ctx) ActorIndependentAttr(
2620+
ActorIndependentKind::Safe, /*IsImplicit=*/true));
25972621
break;
25982622

25992623
case ActorIsolation::GlobalActorUnsafe:
@@ -2842,9 +2866,12 @@ void swift::checkOverrideActorIsolation(ValueDecl *value) {
28422866
bool swift::contextUsesConcurrencyFeatures(const DeclContext *dc) {
28432867
while (!dc->isModuleScopeContext()) {
28442868
if (auto closure = dyn_cast<AbstractClosureExpr>(dc)) {
2845-
// A closure with an explicit global actor or nonindependent
2869+
// A closure with an explicit global actor or @actorIndependent
28462870
// uses concurrency features.
28472871
if (auto explicitClosure = dyn_cast<ClosureExpr>(closure)) {
2872+
if (explicitClosure->getAttrs().hasAttribute<ActorIndependentAttr>())
2873+
return true;
2874+
28482875
if (getExplicitGlobalActor(const_cast<ClosureExpr *>(explicitClosure)))
28492876
return true;
28502877
}

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,7 @@ namespace {
15331533
UNINTERESTING_ATTR(ProjectedValueProperty)
15341534
UNINTERESTING_ATTR(OriginallyDefinedIn)
15351535
UNINTERESTING_ATTR(Actor)
1536+
UNINTERESTING_ATTR(ActorIndependent)
15361537
UNINTERESTING_ATTR(GlobalActor)
15371538
UNINTERESTING_ATTR(Async)
15381539
UNINTERESTING_ATTR(Spawn)

lib/Serialization/Deserialization.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4284,6 +4284,14 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() {
42844284
break;
42854285
}
42864286

4287+
case decls_block::ActorIndependent_DECL_ATTR: {
4288+
unsigned kind;
4289+
serialization::decls_block::ActorIndependentDeclAttrLayout::readRecord(
4290+
scratch, kind);
4291+
Attr = new (ctx) ActorIndependentAttr((ActorIndependentKind)kind);
4292+
break;
4293+
}
4294+
42874295
case decls_block::Optimize_DECL_ATTR: {
42884296
unsigned kind;
42894297
serialization::decls_block::OptimizeDeclAttrLayout::readRecord(

0 commit comments

Comments
 (0)