Skip to content

Commit d0ffce7

Browse files
committed
[AST/Sema] Intoduce nonisolated(nonsending) as a replacement for @execution(caller)
1 parent c18931b commit d0ffce7

20 files changed

+305
-201
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,11 +1234,18 @@ BridgedNonSendableAttr BridgedNonSendableAttr_createParsed(
12341234
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
12351235
BridgedSourceRange cRange, BridgedNonSendableKind cKind);
12361236

1237-
SWIFT_NAME("BridgedNonisolatedAttr.createParsed(_:atLoc:range:isUnsafe:)")
1237+
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedNonIsolatedModifier {
1238+
BridgedNonIsolatedModifierNone,
1239+
BridgedNonIsolatedModifierUnsafe,
1240+
BridgedNonIsolatedModifierNonSending
1241+
};
1242+
1243+
SWIFT_NAME("BridgedNonisolatedAttr.createParsed(_:atLoc:range:modifier:)")
12381244
BridgedNonisolatedAttr
12391245
BridgedNonisolatedAttr_createParsed(BridgedASTContext cContext,
12401246
BridgedSourceLoc cAtLoc,
1241-
BridgedSourceRange cRange, bool isUnsafe);
1247+
BridgedSourceRange cRange,
1248+
BridgedNonIsolatedModifier modifier);
12421249

12431250
SWIFT_NAME("BridgedObjCAttr.createParsedUnnamed(_:atLoc:attrNameLoc:)")
12441251
BridgedObjCAttr

include/swift/AST/Attr.h

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@ class DeclAttribute : public AttributeBase {
226226
isEarlyAdopter : 1
227227
);
228228

229-
SWIFT_INLINE_BITFIELD(NonisolatedAttr, DeclAttribute, 1,
230-
isUnsafe : 1
229+
SWIFT_INLINE_BITFIELD(NonisolatedAttr, DeclAttribute, NumNonIsolatedModifierBits,
230+
Modifier : NumNonIsolatedModifierBits
231231
);
232232

233233
SWIFT_INLINE_BITFIELD_FULL(AllowFeatureSuppressionAttr, DeclAttribute, 1+31,
@@ -2978,29 +2978,38 @@ class ObjCImplementationAttr final : public DeclAttribute {
29782978
/// Represents nonisolated modifier.
29792979
class NonisolatedAttr final : public DeclAttribute {
29802980
public:
2981-
NonisolatedAttr(SourceLoc atLoc, SourceRange range, bool unsafe,
2982-
bool implicit)
2981+
NonisolatedAttr(SourceLoc atLoc, SourceRange range,
2982+
NonIsolatedModifier modifier, bool implicit)
29832983
: DeclAttribute(DeclAttrKind::Nonisolated, atLoc, range, implicit) {
2984-
Bits.NonisolatedAttr.isUnsafe = unsafe;
2985-
assert((isUnsafe() == unsafe) && "not enough bits for unsafe state");
2984+
Bits.NonisolatedAttr.Modifier = static_cast<unsigned>(modifier);
29862985
}
29872986

29882987
NonisolatedAttr(bool unsafe, bool implicit)
2989-
: NonisolatedAttr({}, {}, unsafe, implicit) {}
2988+
: NonisolatedAttr({}, {},
2989+
unsafe ? NonIsolatedModifier::Unsafe
2990+
: NonIsolatedModifier::None,
2991+
implicit) {}
29902992

2991-
bool isUnsafe() const { return Bits.NonisolatedAttr.isUnsafe; }
2993+
NonIsolatedModifier getModifier() const {
2994+
return static_cast<NonIsolatedModifier>(Bits.NonisolatedAttr.Modifier);
2995+
}
2996+
2997+
bool isUnsafe() const { return getModifier() == NonIsolatedModifier::Unsafe; }
2998+
bool isNonSending() const {
2999+
return getModifier() == NonIsolatedModifier::NonSending;
3000+
}
29923001

29933002
static bool classof(const DeclAttribute *DA) {
29943003
return DA->getKind() == DeclAttrKind::Nonisolated;
29953004
}
29963005

29973006
/// Create a copy of this attribute.
29983007
NonisolatedAttr *clone(ASTContext &ctx) const {
2999-
return new (ctx) NonisolatedAttr(AtLoc, Range, isUnsafe(), isImplicit());
3008+
return new (ctx) NonisolatedAttr(AtLoc, Range, getModifier(), isImplicit());
30003009
}
30013010

30023011
bool isEquivalent(const NonisolatedAttr *other, Decl *attachedTo) const {
3003-
return isUnsafe() == other->isUnsafe();
3012+
return getModifier() == other->getModifier();
30043013
}
30053014
};
30063015

include/swift/AST/AttrKind.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,18 @@ enum class ExecutionKind : uint8_t {
138138
enum : unsigned { NumExecutionKindBits =
139139
countBitsUsed(static_cast<unsigned>(ExecutionKind::Last_ExecutionKind)) };
140140

141+
enum class NonIsolatedModifier : uint8_t {
142+
None = 0,
143+
Unsafe,
144+
NonSending,
145+
Last_NonIsolatedModifier = NonSending
146+
};
147+
148+
enum : unsigned {
149+
NumNonIsolatedModifierBits = countBitsUsed(
150+
static_cast<unsigned>(NonIsolatedModifier::Last_NonIsolatedModifier))
151+
};
152+
141153
enum class DeclAttrKind : unsigned {
142154
#define DECL_ATTR(_, CLASS, ...) CLASS,
143155
#define LAST_DECL_ATTR(CLASS) Last_DeclAttr = CLASS,

include/swift/AST/DiagnosticsSema.def

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8541,33 +8541,38 @@ GROUPED_ERROR(isolated_conformance_wrong_domain,IsolatedConformances,none,
85418541
//===----------------------------------------------------------------------===//
85428542
85438543
ERROR(execution_behavior_only_on_async,none,
8544-
"cannot use '%0' on non-async %kind1",
8544+
"cannot use %0 on non-async %kind1",
85458545
(DeclAttribute, ValueDecl *))
85468546
8547+
ERROR(cannot_specify_execution_behavior_for_decl,none,
8548+
"%0 is only applicable to asynchronous functions, "
8549+
"initializers, subscripts and computed properties",
8550+
(DeclAttribute))
8551+
85478552
ERROR(execution_behavior_only_on_async_closure,none,
8548-
"cannot use '%0' on non-async closure",
8553+
"cannot use %0 on non-async closure",
85498554
(DeclAttribute))
85508555
85518556
ERROR(execution_behavior_type_attr_only_on_async,none,
85528557
"cannot use '@%0' on non-async function type",
85538558
(StringRef))
85548559
85558560
ERROR(execution_behavior_incompatible_isolated_parameter,none,
8556-
"cannot use '%0' on %kind1 because it has "
8561+
"cannot use %0 on %kind1 because it has "
85578562
"an isolated parameter: %2",
85588563
(DeclAttribute, ValueDecl *, ValueDecl *))
85598564
85608565
ERROR(execution_behavior_incompatible_dynamically_isolated_parameter,none,
8561-
"cannot use '%0' on %kind1 because it has "
8566+
"cannot use %0 on %kind1 because it has "
85628567
"a dynamically isolated parameter: %2",
85638568
(DeclAttribute, ValueDecl *, ValueDecl *))
85648569
85658570
ERROR(execution_behavior_attr_incompatible_with_global_isolation,none,
8566-
"cannot use '%0' because function type is isolated to a global actor %1",
8571+
"cannot use %0 because function type is isolated to a global actor %1",
85678572
(DeclAttribute, Type))
85688573
85698574
ERROR(execution_behavior_attr_incompatible_with_isolated_param,none,
8570-
"cannot use '%0' together with an isolated parameter",
8575+
"cannot use %0 together with an isolated parameter",
85718576
(DeclAttribute))
85728577
85738578
ERROR(execution_behavior_type_attr_incompatible_with_global_isolation,none,

include/swift/AST/KnownIdentifiers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ IDENTIFIER(main)
127127
IDENTIFIER_WITH_NAME(MainEntryPoint, "$main")
128128
IDENTIFIER(message)
129129
IDENTIFIER(next)
130+
IDENTIFIER(nonsending)
130131
IDENTIFIER_(nsErrorDomain)
131132
IDENTIFIER(objectAtIndexedSubscript)
132133
IDENTIFIER(objectForKeyedSubscript)

lib/AST/ASTDumper.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2389,6 +2389,8 @@ namespace {
23892389
VD->getAttrs().getAttribute<NonisolatedAttr>()) {
23902390
if (nonisolatedAttr->isUnsafe()) {
23912391
printFlag(true, "nonisolated(unsafe)", DeclModifierColor);
2392+
} else if (nonisolatedAttr->isNonSending()) {
2393+
printFlag(true, "nonisolated(nonsending)", DeclModifierColor);
23922394
} else {
23932395
printFlag(true, "nonisolated", DeclModifierColor);
23942396
}
@@ -5183,6 +5185,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
51835185
void visitNonisolatedAttr(NonisolatedAttr *Attr, Label label) {
51845186
printCommon(Attr, "nonisolated_attr", label);
51855187
printFlag(Attr->isUnsafe(), "unsafe");
5188+
printFlag(Attr->isNonSending(), "nonsending");
51865189
printFoot();
51875190
}
51885191
void visitObjCAttr(ObjCAttr *Attr, Label label) {

lib/AST/Attr.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,8 +1535,15 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
15351535

15361536
case DeclAttrKind::Nonisolated: {
15371537
Printer.printAttrName("nonisolated");
1538-
if (cast<NonisolatedAttr>(this)->isUnsafe()) {
1538+
switch (cast<NonisolatedAttr>(this)->getModifier()) {
1539+
case NonIsolatedModifier::None:
1540+
break;
1541+
case NonIsolatedModifier::Unsafe:
15391542
Printer << "(unsafe)";
1543+
break;
1544+
case NonIsolatedModifier::NonSending:
1545+
Printer << "(nonsending)";
1546+
break;
15401547
}
15411548
break;
15421549
}
@@ -1925,10 +1932,13 @@ StringRef DeclAttribute::getAttrName() const {
19251932
case DeclAttrKind::Documentation:
19261933
return "_documentation";
19271934
case DeclAttrKind::Nonisolated:
1928-
if (cast<NonisolatedAttr>(this)->isUnsafe()) {
1929-
return "nonisolated(unsafe)";
1930-
} else {
1931-
return "nonisolated";
1935+
switch (cast<NonisolatedAttr>(this)->getModifier()) {
1936+
case NonIsolatedModifier::None:
1937+
return "nonisolated";
1938+
case NonIsolatedModifier::Unsafe:
1939+
return "nonisolated(unsafe)";
1940+
case NonIsolatedModifier::NonSending:
1941+
return "nonisolated(nonsending)";
19321942
}
19331943
case DeclAttrKind::MacroRole:
19341944
switch (cast<MacroRoleAttr>(this)->getMacroSyntax()) {

lib/AST/Bridging/DeclAttributeBridging.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,12 +627,26 @@ BridgedNonSendableAttr BridgedNonSendableAttr_createParsed(
627627
NonSendableAttr(cAtLoc.unbridged(), cRange.unbridged(), unbridged(cKind));
628628
}
629629

630+
static NonIsolatedModifier unbridged(BridgedNonIsolatedModifier modifier) {
631+
switch (modifier) {
632+
case BridgedNonIsolatedModifierNone:
633+
return NonIsolatedModifier::None;
634+
case BridgedNonIsolatedModifierUnsafe:
635+
return NonIsolatedModifier::Unsafe;
636+
case BridgedNonIsolatedModifierNonSending:
637+
return NonIsolatedModifier::NonSending;
638+
}
639+
llvm_unreachable("unhandled enum value");
640+
}
641+
630642
BridgedNonisolatedAttr
631643
BridgedNonisolatedAttr_createParsed(BridgedASTContext cContext,
632644
BridgedSourceLoc cAtLoc,
633-
BridgedSourceRange cRange, bool isUnsafe) {
645+
BridgedSourceRange cRange,
646+
BridgedNonIsolatedModifier modifier) {
634647
return new (cContext.unbridged()) NonisolatedAttr(
635-
cAtLoc.unbridged(), cRange.unbridged(), isUnsafe, /*implicit=*/false);
648+
cAtLoc.unbridged(), cRange.unbridged(), unbridged(modifier),
649+
/*implicit=*/false);
636650
}
637651

638652
BridgedObjCAttr

lib/AST/Decl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8758,6 +8758,11 @@ void VarDecl::emitLetToVarNoteIfSimple(DeclContext *UseDC) const {
87588758

87598759
std::optional<ExecutionKind>
87608760
AbstractFunctionDecl::getExecutionBehavior() const {
8761+
if (auto *nonisolatedAttr = getAttrs().getAttribute<NonisolatedAttr>()) {
8762+
if (nonisolatedAttr->isNonSending())
8763+
return ExecutionKind::Caller;
8764+
}
8765+
87618766
auto *attr = getAttrs().getAttribute<ExecutionAttr>();
87628767
if (!attr)
87638768
return {};

lib/ASTGen/Sources/ASTGen/DeclAttrs.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,27 +1416,25 @@ extension ASTGenVisitor {
14161416

14171417
// FIXME: This is a decl modifier
14181418
func generateNonisolatedAttr(attribute node: AttributeSyntax) -> BridgedNonisolatedAttr? {
1419-
let isUnsafe = self.generateSingleAttrOption(
1419+
let modifier: BridgedNonIsolatedModifier? = self.generateSingleAttrOption(
14201420
attribute: node,
14211421
{
14221422
switch $0.rawText {
1423-
case "unsafe":
1424-
return true
1425-
default:
1426-
// FIXME: Diagnose.
1427-
return nil
1423+
case "unsafe": return .unsafe
1424+
case "nonsending": return .nonSending
1425+
default: return nil
14281426
}
14291427
},
1430-
valueIfOmitted: false
1428+
valueIfOmitted: BridgedNonIsolatedModifier.none
14311429
)
1432-
guard let isUnsafe else {
1430+
guard let modifier else {
14331431
return nil
14341432
}
14351433
return .createParsed(
14361434
self.ctx,
14371435
atLoc: self.generateSourceLoc(node.atSign),
14381436
range: self.generateAttrSourceRange(node),
1439-
isUnsafe: isUnsafe
1437+
modifier: modifier
14401438
)
14411439
}
14421440

@@ -2410,12 +2408,14 @@ extension ASTGenVisitor {
24102408
}
24112409

24122410
func generateNonisolatedAttr(declModifier node: DeclModifierSyntax) -> BridgedNonisolatedAttr? {
2413-
let isUnsafe: Bool
2411+
let modifier: BridgedNonIsolatedModifier
24142412
switch node.detail?.detail.rawText {
24152413
case "unsafe":
2416-
isUnsafe = true
2414+
modifier = .unsafe
2415+
case "nonsending":
2416+
modifier = .nonSending
24172417
case nil:
2418-
isUnsafe = false
2418+
modifier = .none
24192419
case let text?:
24202420
// TODO: Diagnose
24212421
_ = text
@@ -2426,7 +2426,7 @@ extension ASTGenVisitor {
24262426
self.ctx,
24272427
atLoc: nil,
24282428
range: self.generateSourceRange(node),
2429-
isUnsafe: isUnsafe
2429+
modifier: modifier
24302430
)
24312431
}
24322432

lib/Parse/ParseDecl.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3744,19 +3744,20 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
37443744
}
37453745
case DeclAttrKind::Nonisolated: {
37463746
AttrRange = Loc;
3747-
std::optional<bool> isUnsafe(false);
3747+
std::optional<NonIsolatedModifier> Modifier(NonIsolatedModifier::None);
37483748
if (EnableParameterizedNonisolated) {
3749-
isUnsafe =
3750-
parseSingleAttrOption<bool>(*this, Loc, AttrRange, AttrName, DK,
3751-
{{Context.Id_unsafe, true}}, *isUnsafe,
3752-
ParameterizedDeclAttributeKind::Nonisolated);
3753-
if (!isUnsafe) {
3749+
Modifier = parseSingleAttrOption<NonIsolatedModifier>(
3750+
*this, Loc, AttrRange, AttrName, DK,
3751+
{{Context.Id_unsafe, NonIsolatedModifier::Unsafe},
3752+
{Context.Id_nonsending, NonIsolatedModifier::NonSending}},
3753+
*Modifier, ParameterizedDeclAttributeKind::Nonisolated);
3754+
if (!Modifier) {
37543755
return makeParserSuccess();
37553756
}
37563757
}
37573758

37583759
if (!DiscardAttribute) {
3759-
Attributes.add(new (Context) NonisolatedAttr(AtLoc, AttrRange, *isUnsafe,
3760+
Attributes.add(new (Context) NonisolatedAttr(AtLoc, AttrRange, *Modifier,
37603761
/*implicit*/ false));
37613762
}
37623763
break;
@@ -5660,9 +5661,10 @@ static bool consumeIfParenthesizedUnowned(Parser &P) {
56605661
}
56615662

56625663
/// Given a current token of 'nonisolated', check to see if it is followed by an
5663-
/// "(unsafe)" specifier and consumes if it is.
5664+
/// "(unsafe)" or "(nonsending)" specifier and consumes if it is.
56645665
static bool consumeIfParenthesizedNonisolated(Parser &P) {
5665-
return consumeIfParenthesizedModifier(P, "nonisolated", {"unsafe"});
5666+
return consumeIfParenthesizedModifier(P, "nonisolated",
5667+
{"unsafe", "nonsending"});
56665668
}
56675669

56685670
static void skipAttribute(Parser &P) {

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,6 +2631,12 @@ static CanSILFunctionType getSILFunctionType(
26312631
}
26322632
}
26332633

2634+
if (auto *nonisolatedAttr =
2635+
decl->getAttrs().getAttribute<NonisolatedAttr>()) {
2636+
if (nonisolatedAttr->isNonSending())
2637+
actorIsolation = ActorIsolation::forCallerIsolationInheriting();
2638+
}
2639+
26342640
if (decl->getAttrs().hasAttribute<ConcurrentAttr>()) {
26352641
actorIsolation = ActorIsolation::forNonisolated(false /*unsafe*/);
26362642
}

lib/Sema/AsyncCallerExecutionMigration.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,15 @@ void AsyncCallerExecutionMigrationTarget::diagnose() const {
121121
attrs = &closure->getAttrs();
122122
}
123123

124-
if (attrs && (attrs->hasAttribute<ExecutionAttr>() ||
125-
attrs->hasAttribute<ConcurrentAttr>())) {
126-
return;
124+
if (attrs) {
125+
if (attrs->hasAttribute<ExecutionAttr>() ||
126+
attrs->hasAttribute<ConcurrentAttr>())
127+
return;
128+
129+
if (auto *nonisolated = attrs->getAttribute<NonisolatedAttr>()) {
130+
if (nonisolated->isNonSending())
131+
return;
132+
}
127133
}
128134
}
129135

0 commit comments

Comments
 (0)