Skip to content

Commit 77e7dc2

Browse files
Merge pull request #69280 from sophiapoirier/globals_strict_concurrency_opt_out_nonisolated_unsafe
nonisolated(unsafe) to opt out of strict concurrency static checking for global variables
2 parents 0b328f7 + 4c9a726 commit 77e7dc2

31 files changed

+228
-53
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ class ActorIsolation {
6060
/// meaning that it can be used from any actor but is also unable to
6161
/// refer to the isolated state of any given actor.
6262
Nonisolated,
63+
/// The declaration is explicitly specified to be not isolated and with the
64+
/// "unsafe" annotation, which means that we do not enforce isolation.
65+
NonisolatedUnsafe,
6366
/// The declaration is isolated to a global actor. It can refer to other
6467
/// entities with the same global actor.
6568
GlobalActor,
@@ -97,8 +100,8 @@ class ActorIsolation {
97100
return ActorIsolation(Unspecified, nullptr);
98101
}
99102

100-
static ActorIsolation forNonisolated() {
101-
return ActorIsolation(Nonisolated, nullptr);
103+
static ActorIsolation forNonisolated(bool unsafe) {
104+
return ActorIsolation(unsafe ? NonisolatedUnsafe : Nonisolated, nullptr);
102105
}
103106

104107
static ActorIsolation forActorInstanceSelf(NominalTypeDecl *actor) {
@@ -124,8 +127,10 @@ class ActorIsolation {
124127
operator Kind() const { return getKind(); }
125128

126129
bool isUnspecified() const { return kind == Unspecified; }
127-
128-
bool isNonisolated() const { return kind == Nonisolated; }
130+
131+
bool isNonisolated() const {
132+
return (kind == Nonisolated) || (kind == NonisolatedUnsafe);
133+
}
129134

130135
/// Retrieve the parameter to which actor-instance isolation applies.
131136
///
@@ -144,6 +149,7 @@ class ActorIsolation {
144149

145150
case Unspecified:
146151
case Nonisolated:
152+
case NonisolatedUnsafe:
147153
return false;
148154
}
149155
}
@@ -192,6 +198,7 @@ class ActorIsolation {
192198

193199
switch (lhs.getKind()) {
194200
case Nonisolated:
201+
case NonisolatedUnsafe:
195202
case Unspecified:
196203
return true;
197204

include/swift/AST/Attr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(async, Async,
499499
SIMPLE_DECL_ATTR(reasync, Reasync,
500500
OnFunc | OnConstructor | RejectByParser | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,
501501
109)
502-
CONTEXTUAL_SIMPLE_DECL_ATTR(nonisolated, Nonisolated,
502+
CONTEXTUAL_DECL_ATTR(nonisolated, Nonisolated,
503503
DeclModifier | OnFunc | OnConstructor | OnVar | OnSubscript | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
504504
112)
505505
CONTEXTUAL_SIMPLE_DECL_ATTR(distributed, DistributedActor,

include/swift/AST/Attr.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ class DeclAttribute : public AttributeBase {
187187
SWIFT_INLINE_BITFIELD(ObjCImplementationAttr, DeclAttribute, 1,
188188
isCategoryNameInvalid : 1
189189
);
190+
191+
SWIFT_INLINE_BITFIELD(NonisolatedAttr, DeclAttribute, 1,
192+
isUnsafe : 1
193+
);
190194
} Bits;
191195
// clang-format on
192196

@@ -2434,6 +2438,26 @@ class ObjCImplementationAttr final : public DeclAttribute {
24342438
}
24352439
};
24362440

2441+
/// Represents nonisolated modifier.
2442+
class NonisolatedAttr final : public DeclAttribute {
2443+
public:
2444+
NonisolatedAttr(SourceLoc atLoc, SourceRange range, bool unsafe,
2445+
bool implicit)
2446+
: DeclAttribute(DAK_Nonisolated, atLoc, range, implicit) {
2447+
Bits.NonisolatedAttr.isUnsafe = unsafe;
2448+
assert((isUnsafe() == unsafe) && "not enough bits for unsafe state");
2449+
}
2450+
2451+
NonisolatedAttr(bool unsafe, bool implicit)
2452+
: NonisolatedAttr({}, {}, unsafe, implicit) {}
2453+
2454+
bool isUnsafe() const { return Bits.NonisolatedAttr.isUnsafe; }
2455+
2456+
static bool classof(const DeclAttribute *DA) {
2457+
return DA->getKind() == DAK_Nonisolated;
2458+
}
2459+
};
2460+
24372461
/// A macro role attribute, spelled with either @attached or @freestanding,
24382462
/// which declares one of the roles that a given macro can inhabit.
24392463
class MacroRoleAttr final

include/swift/AST/Decl.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6128,7 +6128,10 @@ class VarDecl : public AbstractStorageDecl {
61286128
/// True if this is a top-level global variable from the main source file.
61296129
bool isTopLevelGlobal() const { return Bits.VarDecl.IsTopLevelGlobal; }
61306130
void setTopLevelGlobal(bool b) { Bits.VarDecl.IsTopLevelGlobal = b; }
6131-
6131+
6132+
/// True if this is any storage of static duration (global scope or static).
6133+
bool isGlobalStorage() const;
6134+
61326135
/// Retrieve the custom attributes that attach property wrappers to this
61336136
/// property. The returned list contains all of the attached property wrapper
61346137
/// attributes in source order, which means the outermost wrapper attribute

lib/AST/ASTDumper.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,8 +1456,10 @@ namespace {
14561456
});
14571457
}
14581458

1459-
printFlag(D->getAttrs().hasAttribute<NonisolatedAttr>(), "nonisolated",
1460-
ExprModifierColor);
1459+
if (auto *attr = D->getAttrs().getAttribute<NonisolatedAttr>()) {
1460+
printFlag(attr->isUnsafe() ? "nonisolated(unsafe)" : "nonisolated",
1461+
ExprModifierColor);
1462+
}
14611463
printFlag(D->isDistributed(), "distributed", ExprModifierColor);
14621464
printFlag(D->isDistributedThunk(), "distributed_thunk",ExprModifierColor);
14631465
}
@@ -2735,6 +2737,7 @@ class PrintExpr : public ExprVisitor<PrintExpr, void, StringRef>,
27352737
switch (auto isolation = E->getActorIsolation()) {
27362738
case ActorIsolation::Unspecified:
27372739
case ActorIsolation::Nonisolated:
2740+
case ActorIsolation::NonisolatedUnsafe:
27382741
break;
27392742

27402743
case ActorIsolation::ActorInstance:

lib/AST/Attr.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,14 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
14011401
break;
14021402
}
14031403

1404+
case DAK_Nonisolated: {
1405+
Printer.printAttrName("nonisolated");
1406+
if (cast<NonisolatedAttr>(this)->isUnsafe()) {
1407+
Printer << "(unsafe)";
1408+
}
1409+
break;
1410+
}
1411+
14041412
case DAK_MacroRole: {
14051413
auto Attr = cast<MacroRoleAttr>(this);
14061414

@@ -1721,6 +1729,12 @@ StringRef DeclAttribute::getAttrName() const {
17211729
return "_section";
17221730
case DAK_Documentation:
17231731
return "_documentation";
1732+
case DAK_Nonisolated:
1733+
if (cast<NonisolatedAttr>(this)->isUnsafe()) {
1734+
return "nonisolated(unsafe)";
1735+
} else {
1736+
return "nonisolated";
1737+
}
17241738
case DAK_MacroRole:
17251739
switch (cast<MacroRoleAttr>(this)->getMacroSyntax()) {
17261740
case MacroSyntax::Freestanding:

lib/AST/Decl.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2460,6 +2460,7 @@ static bool deferMatchesEnclosingAccess(const FuncDecl *defer) {
24602460

24612461
switch (getActorIsolation(type)) {
24622462
case ActorIsolation::Unspecified:
2463+
case ActorIsolation::NonisolatedUnsafe:
24632464
case ActorIsolation::GlobalActorUnsafe:
24642465
break;
24652466

@@ -7893,6 +7894,15 @@ VarDecl *VarDecl::getLazyStorageProperty() const {
78937894
{});
78947895
}
78957896

7897+
bool VarDecl::isGlobalStorage() const {
7898+
if (!hasStorage()) {
7899+
return false;
7900+
}
7901+
const auto *dc = getDeclContext();
7902+
return isStatic() || dc->isModuleScopeContext() ||
7903+
(dc->isTypeContext() && !isInstanceMember());
7904+
}
7905+
78967906
bool VarDecl::isPropertyMemberwiseInitializedWithWrappedType() const {
78977907
auto customAttrs = getAttachedPropertyWrappers();
78987908
if (customAttrs.empty())
@@ -10500,6 +10510,7 @@ bool VarDecl::isSelfParamCaptureIsolated() const {
1050010510
switch (auto isolation = closure->getActorIsolation()) {
1050110511
case ActorIsolation::Unspecified:
1050210512
case ActorIsolation::Nonisolated:
10513+
case ActorIsolation::NonisolatedUnsafe:
1050310514
case ActorIsolation::GlobalActor:
1050410515
case ActorIsolation::GlobalActorUnsafe:
1050510516
return false;

lib/AST/DiagnosticEngine.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,8 +921,12 @@ static void formatDiagnosticArgument(StringRef Modifier,
921921
}
922922

923923
case ActorIsolation::Nonisolated:
924+
case ActorIsolation::NonisolatedUnsafe:
924925
case ActorIsolation::Unspecified:
925926
Out << "nonisolated";
927+
if (isolation == ActorIsolation::NonisolatedUnsafe) {
928+
Out << "(unsafe)";
929+
}
926930
break;
927931
}
928932
break;

lib/AST/TypeCheckRequests.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,7 +1741,11 @@ void swift::simple_display(
17411741
break;
17421742

17431743
case ActorIsolation::Nonisolated:
1744+
case ActorIsolation::NonisolatedUnsafe:
17441745
out << "nonisolated";
1746+
if (state == ActorIsolation::NonisolatedUnsafe) {
1747+
out << "(unsafe)";
1748+
}
17451749
break;
17461750

17471751
case ActorIsolation::Unspecified:

lib/ClangImporter/ImportDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7844,7 +7844,8 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
78447844
// Hard-code @actorIndependent, until Objective-C clients start
78457845
// using nonisolated.
78467846
if (swiftAttr->getAttribute() == "@actorIndependent") {
7847-
auto attr = new (SwiftContext) NonisolatedAttr(/*isImplicit=*/true);
7847+
auto attr = new (SwiftContext)
7848+
NonisolatedAttr(/*unsafe=*/false, /*implicit=*/true);
78487849
MappedDecl->getAttrs().add(attr);
78497850
continue;
78507851
}

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,8 @@ ValueDecl *SwiftDeclSynthesizer::createConstant(
422422

423423
// Mark the function transparent so that we inline it away completely.
424424
func->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
425-
auto nonisolatedAttr = new (C) NonisolatedAttr(/*IsImplicit=*/true);
425+
auto nonisolatedAttr =
426+
new (C) NonisolatedAttr(/*unsafe=*/false, /*implicit=*/true);
426427
var->getAttrs().add(nonisolatedAttr);
427428

428429
// Set the function up as the getter.

lib/IDE/CompletionLookup.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,7 @@ void CompletionLookup::analyzeActorIsolation(
789789
}
790790
case ActorIsolation::Unspecified:
791791
case ActorIsolation::Nonisolated:
792+
case ActorIsolation::NonisolatedUnsafe:
792793
return;
793794
}
794795

lib/Parse/ParseDecl.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3872,6 +3872,20 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
38723872
return makeParserSuccess();
38733873
break;
38743874
}
3875+
case DAK_Nonisolated: {
3876+
auto isUnsafe =
3877+
parseSingleAttrOption<bool>(*this, Loc, AttrRange, AttrName, DK,
3878+
{{Context.Id_unsafe, true}}, false);
3879+
if (!isUnsafe) {
3880+
return makeParserSuccess();
3881+
}
3882+
3883+
if (!DiscardAttribute) {
3884+
Attributes.add(new (Context) NonisolatedAttr(AtLoc, AttrRange, *isUnsafe,
3885+
/*implicit*/ false));
3886+
}
3887+
break;
3888+
}
38753889
case DAK_MacroRole: {
38763890
auto syntax = (AttrName == "freestanding" ? MacroSyntax::Freestanding
38773891
: MacroSyntax::Attached);

lib/SILGen/SILGenApply.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5521,6 +5521,7 @@ RValue SILGenFunction::emitApply(
55215521

55225522
case ActorIsolation::Unspecified:
55235523
case ActorIsolation::Nonisolated:
5524+
case ActorIsolation::NonisolatedUnsafe:
55245525
llvm_unreachable("Not isolated");
55255526
break;
55265527
}

lib/SILGen/SILGenConstructor.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ static bool ctorHopsInjectedByDefiniteInit(ConstructorDecl *ctor,
610610

611611
case ActorIsolation::Unspecified:
612612
case ActorIsolation::Nonisolated:
613+
case ActorIsolation::NonisolatedUnsafe:
613614
case ActorIsolation::GlobalActor:
614615
case ActorIsolation::GlobalActorUnsafe:
615616
return false;
@@ -1554,6 +1555,7 @@ void SILGenFunction::emitMemberInitializer(DeclContext *dc, VarDecl *selfDecl,
15541555
// 'nonisolated' expressions can be evaluated from anywhere
15551556
case ActorIsolation::Unspecified:
15561557
case ActorIsolation::Nonisolated:
1558+
case ActorIsolation::NonisolatedUnsafe:
15571559
break;
15581560

15591561
case ActorIsolation::GlobalActor:

lib/SILGen/SILGenProlog.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,7 @@ void SILGenFunction::emitProlog(
12811281
return false;
12821282

12831283
case ActorIsolation::Nonisolated:
1284+
case ActorIsolation::NonisolatedUnsafe:
12841285
case ActorIsolation::Unspecified:
12851286
return false;
12861287
}
@@ -1332,6 +1333,7 @@ void SILGenFunction::emitProlog(
13321333
switch (actorIsolation.getKind()) {
13331334
case ActorIsolation::Unspecified:
13341335
case ActorIsolation::Nonisolated:
1336+
case ActorIsolation::NonisolatedUnsafe:
13351337
break;
13361338

13371339
case ActorIsolation::ActorInstance: {
@@ -1384,6 +1386,7 @@ void SILGenFunction::emitProlog(
13841386
switch (actorIsolation.getKind()) {
13851387
case ActorIsolation::Unspecified:
13861388
case ActorIsolation::Nonisolated:
1389+
case ActorIsolation::NonisolatedUnsafe:
13871390
break;
13881391

13891392
case ActorIsolation::ActorInstance: {
@@ -1572,6 +1575,7 @@ SILGenFunction::emitExecutor(SILLocation loc, ActorIsolation isolation,
15721575
switch (isolation.getKind()) {
15731576
case ActorIsolation::Unspecified:
15741577
case ActorIsolation::Nonisolated:
1578+
case ActorIsolation::NonisolatedUnsafe:
15751579
return llvm::None;
15761580

15771581
case ActorIsolation::ActorInstance: {
@@ -1597,8 +1601,9 @@ void SILGenFunction::emitHopToActorValue(SILLocation loc, ManagedValue actor) {
15971601
getActorIsolationOfContext(FunctionDC, [](AbstractClosureExpr *CE) {
15981602
return CE->getActorIsolation();
15991603
});
1600-
if (isolation != ActorIsolation::Nonisolated
1601-
&& isolation != ActorIsolation::Unspecified) {
1604+
if (isolation != ActorIsolation::Nonisolated &&
1605+
isolation != ActorIsolation::NonisolatedUnsafe &&
1606+
isolation != ActorIsolation::Unspecified) {
16021607
// TODO: Explicit hop with no hop-back should only be allowed in nonisolated
16031608
// async functions. But it needs work for any closure passed to
16041609
// Task.detached, which currently has unspecified isolation.

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,7 @@ void LifetimeChecker::injectActorHops() {
10461046

10471047
case ActorIsolation::Unspecified:
10481048
case ActorIsolation::Nonisolated:
1049+
case ActorIsolation::NonisolatedUnsafe:
10491050
case ActorIsolation::GlobalActorUnsafe:
10501051
case ActorIsolation::GlobalActor:
10511052
return;

lib/Sema/CodeSynthesis.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1634,7 +1634,8 @@ bool swift::addNonIsolatedToSynthesized(NominalTypeDecl *nominal,
16341634
return false;
16351635

16361636
ASTContext &ctx = nominal->getASTContext();
1637-
value->getAttrs().add(new (ctx) NonisolatedAttr(/*isImplicit=*/true));
1637+
value->getAttrs().add(
1638+
new (ctx) NonisolatedAttr(/*unsafe=*/false, /*implicit=*/true));
16381639
return true;
16391640
}
16401641

lib/Sema/CodeSynthesisDistributedActor.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ static VarDecl *addImplicitDistributedActorIDProperty(
108108

109109
// mark as nonisolated, allowing access to it from everywhere
110110
propDecl->getAttrs().add(
111-
new (C) NonisolatedAttr(/*IsImplicit=*/true));
111+
new (C) NonisolatedAttr(/*unsafe=*/false, /*implicit=*/true));
112112
// mark as @_compilerInitialized, since we synthesize the initializing
113113
// assignment during SILGen.
114114
propDecl->getAttrs().add(
@@ -158,7 +158,7 @@ static VarDecl *addImplicitDistributedActorActorSystemProperty(
158158

159159
// mark as nonisolated, allowing access to it from everywhere
160160
propDecl->getAttrs().add(
161-
new (C) NonisolatedAttr(/*IsImplicit=*/true));
161+
new (C) NonisolatedAttr(/*unsafe=*/false, /*implicit=*/true));
162162

163163
auto idProperty = nominal->getDistributedActorIDProperty();
164164
// If the id was not yet synthesized, we need to ensure that eventually
@@ -735,7 +735,8 @@ static FuncDecl *createDistributedThunkFunction(FuncDecl *func) {
735735

736736
thunk->setSynthesized(true);
737737
thunk->setDistributedThunk(true);
738-
thunk->getAttrs().add(new (C) NonisolatedAttr(/*isImplicit=*/true));
738+
thunk->getAttrs().add(
739+
new (C) NonisolatedAttr(/*unsafe=*/false, /*implicit=*/true));
739740

740741
if (isa<ClassDecl>(DC))
741742
thunk->getAttrs().add(new (C) FinalAttr(/*isImplicit=*/true));

lib/Sema/DerivedConformanceActor.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ static ValueDecl *deriveActor_unownedExecutor(DerivedConformance &derived) {
147147
property->getAttrs().add(new (ctx) SemanticsAttr(SEMANTICS_DEFAULT_ACTOR,
148148
SourceLoc(), SourceRange(),
149149
/*implicit*/ true));
150-
property->getAttrs().add(new (ctx) NonisolatedAttr(/*IsImplicit=*/true));
150+
property->getAttrs().add(
151+
new (ctx) NonisolatedAttr(/*unsafe=*/false, /*implicit=*/true));
151152

152153
// Make the property implicitly final.
153154
property->getAttrs().add(new (ctx) FinalAttr(/*IsImplicit=*/true));

0 commit comments

Comments
 (0)