Skip to content

Commit 9a56f1b

Browse files
committed
[AST/Parse] Implement nonisolated(nonsending) type modifier
1 parent d0ffce7 commit 9a56f1b

18 files changed

+256
-5
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2782,6 +2782,12 @@ BridgedSendingTypeRepr_createParsed(BridgedASTContext cContext,
27822782
BridgedTypeRepr base,
27832783
BridgedSourceLoc cSpecifierLoc);
27842784

2785+
SWIFT_NAME("BridgedCallerIsolatedTypeRepr.createParsed(_:base:specifierLoc:)")
2786+
BridgedCallerIsolatedTypeRepr
2787+
BridgedCallerIsolatedTypeRepr_createParsed(BridgedASTContext cContext,
2788+
BridgedTypeRepr base,
2789+
BridgedSourceLoc cSpecifierLoc);
2790+
27852791
SWIFT_NAME(
27862792
"BridgedTupleTypeRepr.createParsed(_:elements:leftParenLoc:rightParenLoc:)")
27872793
BridgedTupleTypeRepr BridgedTupleTypeRepr_createParsed(

include/swift/AST/DiagnosticsParse.def

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,5 +2172,18 @@ ERROR(sil_thunkinst_failed_to_parse_kind,none,
21722172
ERROR(sil_failed_to_parse_sil_optional,none,
21732173
"Expected SIL optional value of the form '[' NAME ']'", ())
21742174

2175+
//------------------------------------------------------------------------------
2176+
// MARK: nonisolated(nonsending)
2177+
//------------------------------------------------------------------------------
2178+
2179+
ERROR(nonisolated_nonsending_expected_lparen,PointsToFirstBadToken,
2180+
"expected '(' following 'nonisolated'", ())
2181+
ERROR(nonisolated_nonsending_incorrect_modifier,PointsToFirstBadToken,
2182+
"expected 'nonsending' in modifier", ())
2183+
ERROR(nonisolated_nonsending_expected_rparen,PointsToFirstBadToken,
2184+
"expected '(' after 'nonisolated' modifier", ())
2185+
ERROR(nonisolated_nonsending_repeated,none,
2186+
"parameter may have at most one 'nonisolated(nonsending)' specifier", ())
2187+
21752188
#define UNDEFINE_DIAGNOSTIC_MACROS
21762189
#include "DefineDiagnosticMacros.h"

include/swift/AST/DiagnosticsSema.def

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8537,7 +8537,7 @@ GROUPED_ERROR(isolated_conformance_wrong_domain,IsolatedConformances,none,
85378537
(ActorIsolation, Type, DeclName, ActorIsolation))
85388538
85398539
//===----------------------------------------------------------------------===//
8540-
// MARK: @execution Attribute
8540+
// MARK: @execution, @concurrent and nonisolated(nonsending) attributes
85418541
//===----------------------------------------------------------------------===//
85428542
85438543
ERROR(execution_behavior_only_on_async,none,
@@ -8557,6 +8557,18 @@ ERROR(execution_behavior_type_attr_only_on_async,none,
85578557
"cannot use '@%0' on non-async function type",
85588558
(StringRef))
85598559
8560+
ERROR(nonisolated_nonsending_only_on_function_types, none,
8561+
"%0 may only be used on function types",
8562+
(TypeRepr *))
8563+
8564+
ERROR(nonisolated_nonsending_only_on_async,none,
8565+
"cannot use %0 on non-async function type",
8566+
(TypeRepr *))
8567+
8568+
ERROR(cannot_use_nonisolated_nonsending_together_with_concurrent,none,
8569+
"cannot use %0 together with '@concurrent'",
8570+
(TypeRepr *))
8571+
85608572
ERROR(execution_behavior_incompatible_isolated_parameter,none,
85618573
"cannot use %0 on %kind1 because it has "
85628574
"an isolated parameter: %2",
@@ -8579,14 +8591,26 @@ ERROR(execution_behavior_type_attr_incompatible_with_global_isolation,none,
85798591
"cannot use '@%0' because function type is isolated to a global actor %1",
85808592
(StringRef, Type))
85818593
8594+
ERROR(nonisolated_nonsending_incompatible_with_global_isolation,none,
8595+
"cannot use %0 because function type is isolated to a global actor %1",
8596+
(TypeRepr *, Type))
8597+
85828598
ERROR(execution_behavior_type_attr_incompatible_with_isolated_param,none,
85838599
"cannot use '@%0' together with an isolated parameter",
85848600
(StringRef))
85858601
8602+
ERROR(nonisolated_nonsending_incompatible_with_isolated_param,none,
8603+
"cannot use %0 together with an isolated parameter",
8604+
(TypeRepr *))
8605+
85868606
ERROR(execution_behavior_type_attr_incompatible_with_isolated_any,none,
85878607
"cannot use '@%0' together with @isolated(any)",
85888608
(StringRef))
85898609

8610+
ERROR(nonisolated_nonsending_incompatible_with_isolated_any,none,
8611+
"cannot use %0 together with @isolated(any)",
8612+
(TypeRepr *))
8613+
85908614
ERROR(invalid_function_conversion_with_non_sendable,none,
85918615
"cannot convert %0 to %1 because crossing of an isolation boundary "
85928616
"requires parameter and result types to conform to 'Sendable' protocol",

include/swift/AST/TypeRepr.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,35 @@ class SendingTypeRepr : public SpecifierTypeRepr {
12491249
static bool classof(const SendingTypeRepr *T) { return true; }
12501250
};
12511251

1252+
/// A 'nonisolated(nonsending)' function type.
1253+
/// \code
1254+
/// x : nonisolated(nonsending) () async -> Int
1255+
/// \endcode
1256+
class CallerIsolatedTypeRepr : public TypeRepr {
1257+
TypeRepr *Base;
1258+
SourceLoc Loc;
1259+
1260+
public:
1261+
CallerIsolatedTypeRepr(TypeRepr *Base, SourceLoc Loc)
1262+
: TypeRepr(TypeReprKind::CallerIsolated), Base(Base), Loc(Loc) {
1263+
assert(Base);
1264+
}
1265+
1266+
TypeRepr *getBase() const { return Base; }
1267+
1268+
static bool classof(const TypeRepr *T) {
1269+
return T->getKind() == TypeReprKind::CallerIsolated;
1270+
}
1271+
static bool classof(const CallerIsolatedTypeRepr *T) { return true; }
1272+
1273+
private:
1274+
SourceLoc getStartLocImpl() const { return Loc; }
1275+
SourceLoc getEndLocImpl() const { return Base->getEndLoc(); }
1276+
SourceLoc getLocImpl() const { return Base->getLoc(); }
1277+
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
1278+
friend class TypeRepr;
1279+
};
1280+
12521281
/// A TypeRepr for a known, fixed type.
12531282
///
12541283
/// Fixed type representations should be used sparingly, in places
@@ -1680,6 +1709,7 @@ inline bool TypeRepr::isSimple() const {
16801709
case TypeReprKind::ConstValue:
16811710
case TypeReprKind::LifetimeDependent:
16821711
case TypeReprKind::Integer:
1712+
case TypeReprKind::CallerIsolated:
16831713
return true;
16841714
}
16851715
llvm_unreachable("bad TypeRepr kind");

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ TYPEREPR(Fixed, TypeRepr)
7777
TYPEREPR(SILBox, TypeRepr)
7878
TYPEREPR(Self, TypeRepr)
7979
TYPEREPR(LifetimeDependent, TypeRepr)
80+
TYPEREPR(CallerIsolated, TypeRepr)
8081
TYPEREPR(Integer, TypeRepr)
8182
LAST_TYPEREPR(Integer)
8283

include/swift/Parse/Parser.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,8 @@ class Parser {
11691169
Tok.isContextualKeyword("isolated") ||
11701170
Tok.isContextualKeyword("_const"))
11711171
return true;
1172+
if (isCallerIsolatedSpecifier())
1173+
return true;
11721174
if (Context.LangOpts.hasFeature(Feature::SendingArgsAndResults) &&
11731175
Tok.isContextualKeyword("sending"))
11741176
return true;
@@ -1187,6 +1189,12 @@ class Parser {
11871189
(peekToken().isContextualKeyword("lifetime"));
11881190
}
11891191

1192+
bool isCallerIsolatedSpecifier() {
1193+
if (!Tok.isContextualKeyword("nonisolated"))
1194+
return false;
1195+
return peekToken().isFollowingLParen();
1196+
}
1197+
11901198
bool canHaveParameterSpecifierContextualKeyword() {
11911199
// The parameter specifiers like `isolated`, `consuming`, `borrowing` are
11921200
// also valid identifiers and could be the name of a type. Check whether
@@ -1421,6 +1429,7 @@ class Parser {
14211429
SourceLoc IsolatedLoc;
14221430
SourceLoc ConstLoc;
14231431
SourceLoc SendingLoc;
1432+
SourceLoc CallerIsolatedLoc;
14241433
SmallVector<TypeOrCustomAttr> Attributes;
14251434
LifetimeEntry *lifetimeEntry = nullptr;
14261435

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4646,6 +4646,12 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr, void, Label>,
46464646
printFoot();
46474647
}
46484648

4649+
void visitCallerIsolatedTypeRepr(CallerIsolatedTypeRepr *T, Label label) {
4650+
printCommon("caller_isolated", label);
4651+
printRec(T->getBase(), Label::optional("base"));
4652+
printFoot();
4653+
}
4654+
46494655
void visitCompileTimeLiteralTypeRepr(CompileTimeLiteralTypeRepr *T, Label label) {
46504656
printCommon("_const", label);
46514657
printRec(T->getBase(), Label::optional("base"));

lib/AST/ASTWalker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,6 +2324,10 @@ bool Traversal::visitSendingTypeRepr(SendingTypeRepr *T) {
23242324
return doIt(T->getBase());
23252325
}
23262326

2327+
bool Traversal::visitCallerIsolatedTypeRepr(CallerIsolatedTypeRepr *T) {
2328+
return doIt(T->getBase());
2329+
}
2330+
23272331
bool Traversal::visitCompileTimeLiteralTypeRepr(CompileTimeLiteralTypeRepr *T) {
23282332
return doIt(T->getBase());
23292333
}

lib/AST/Bridging/TypeReprBridging.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,14 @@ BridgedSendingTypeRepr_createParsed(BridgedASTContext cContext,
211211
SendingTypeRepr(base.unbridged(), cSpecifierLoc.unbridged());
212212
}
213213

214+
BridgedCallerIsolatedTypeRepr
215+
BridgedCallerIsolatedTypeRepr_createParsed(BridgedASTContext cContext,
216+
BridgedTypeRepr base,
217+
BridgedSourceLoc cSpecifierLoc) {
218+
return new (cContext.unbridged())
219+
CallerIsolatedTypeRepr(base.unbridged(), cSpecifierLoc.unbridged());
220+
}
221+
214222
BridgedVarargTypeRepr
215223
BridgedVarargTypeRepr_createParsed(BridgedASTContext cContext,
216224
BridgedTypeRepr base,

lib/AST/NameLookup.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3209,6 +3209,12 @@ directReferencesForTypeRepr(Evaluator &evaluator, ASTContext &ctx,
32093209
isolated->getBase(), dc, options);
32103210
}
32113211

3212+
case TypeReprKind::CallerIsolated: {
3213+
auto callerIsolated = cast<CallerIsolatedTypeRepr>(typeRepr);
3214+
return directReferencesForTypeRepr(evaluator, ctx,
3215+
callerIsolated->getBase(), dc, options);
3216+
}
3217+
32123218
case TypeReprKind::Composition: {
32133219
auto composition = cast<CompositionTypeRepr>(typeRepr);
32143220
for (auto component : composition->getTypes()) {

lib/AST/TypeRepr.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,11 @@ ValueOwnership OwnershipTypeRepr::getValueOwnership() const {
923923
return ParamDecl::getValueOwnershipForSpecifier(getSpecifier());
924924
}
925925

926+
void CallerIsolatedTypeRepr::printImpl(ASTPrinter &Printer,
927+
const PrintOptions &Opts) const {
928+
Printer.printKeyword("nonisolated(nonsending)", Opts);
929+
}
930+
926931
void PlaceholderTypeRepr::printImpl(ASTPrinter &Printer,
927932
const PrintOptions &Opts) const {
928933
Printer.printText("_");

lib/ASTGen/Sources/ASTGen/Types.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ extension ASTGenVisitor {
362362
var constLoc: BridgedSourceLoc = nil
363363
var sendingLoc: BridgedSourceLoc = nil
364364
var lifetimeEntry: BridgedLifetimeEntry? = nil
365+
var nonisolatedLoc: BridgedSourceLoc = nil
365366

366367
// TODO: Diagnostics for duplicated specifiers, and ordering.
367368
for node in node.specifiers {
@@ -398,6 +399,8 @@ extension ASTGenVisitor {
398399
),
399400
sources: node.arguments.lazy.compactMap(self.generateLifetimeDescriptor(lifetimeSpecifierArgument:)).bridgedArray(in: self)
400401
)
402+
case .nonisolatedTypeSpecifier(_):
403+
nonisolatedLoc = loc
401404
}
402405
}
403406

@@ -454,6 +457,14 @@ extension ASTGenVisitor {
454457
).asTypeRepr
455458
}
456459

460+
if nonisolatedLoc.isValid {
461+
type = BridgedCallerIsolatedTypeRepr.createParsed(
462+
self.ctx,
463+
base: type,
464+
specifierLoc: nonisolatedLoc
465+
).asTypeRepr
466+
}
467+
457468
return type
458469
}
459470
}

lib/Migrator/APIDiffMigratorPass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ class ChildIndexFinder : public TypeReprVisitor<ChildIndexFinder, FoundResult> {
162162
return visit(T->getBase());
163163
}
164164

165+
FoundResult visitCallerIsolatedTypeRepr(CallerIsolatedTypeRepr *T) {
166+
return visit(T->getBase());
167+
}
168+
165169
FoundResult visitArrayTypeRepr(ArrayTypeRepr *T) {
166170
return handleParent(T, T->getBase());
167171
}

lib/Parse/ParseDecl.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5297,6 +5297,7 @@ ParserStatus Parser::parseDeclModifierList(DeclAttributes &Attributes,
52975297
/// '__shared' attribute-list-clause attribute-list
52985298
/// '__owned' attribute-list-clause attribute-list
52995299
/// 'some' attribute-list-clause attribute-list
5300+
/// 'nonisolated(nonsending)' attribute-list-clause attribute-list
53005301
/// attribute-list-clause:
53015302
/// '@' attribute
53025303
/// '@' attribute attribute-list-clause
@@ -5323,6 +5324,43 @@ ParserStatus Parser::ParsedTypeAttributeList::slowParse(Parser &P) {
53235324
continue;
53245325
}
53255326

5327+
// nonisolated(nonsending)
5328+
if (Tok.isContextualKeyword("nonisolated")) {
5329+
Tok.setKind(tok::contextual_keyword);
5330+
5331+
auto kwLoc = P.consumeToken();
5332+
5333+
if (CallerIsolatedLoc.isValid()) {
5334+
P.diagnose(kwLoc, diag::nonisolated_nonsending_repeated)
5335+
.fixItRemove(SpecifierLoc);
5336+
}
5337+
5338+
// '('
5339+
if (!P.consumeIfAttributeLParen()) {
5340+
P.diagnose(Tok, diag::nonisolated_nonsending_expected_lparen);
5341+
status.setIsParseError();
5342+
continue;
5343+
}
5344+
5345+
if (!Tok.isContextualKeyword("nonsending")) {
5346+
P.diagnose(Tok, diag::nonisolated_nonsending_incorrect_modifier);
5347+
status.setIsParseError();
5348+
continue;
5349+
}
5350+
5351+
(void)P.consumeToken();
5352+
5353+
// ')'
5354+
if (!P.consumeIf(tok::r_paren)) {
5355+
P.diagnose(Tok, diag::nonisolated_nonsending_expected_rparen);
5356+
status.setIsParseError();
5357+
continue;
5358+
}
5359+
5360+
CallerIsolatedLoc = kwLoc;
5361+
continue;
5362+
}
5363+
53265364
// Perform an extra check for 'sending'. Since it is a specifier, we use
53275365
// the actual parsing logic below.
53285366
if (Tok.isContextualKeyword("sending")) {

lib/Parse/ParseExpr.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,8 +542,9 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
542542
consumeToken();
543543
}
544544

545-
// Try to parse '@' sign or 'inout' as a attributed typerepr.
546-
if (Tok.isAny(tok::at_sign, tok::kw_inout)) {
545+
// Try to parse '@' sign, 'inout' or 'nonisolated' as a attributed typerepr.
546+
if (Tok.isAny(tok::at_sign, tok::kw_inout) ||
547+
Tok.isContextualKeyword("nonisolated")) {
547548
bool isType = false;
548549
{
549550
BacktrackingScope backtrack(*this);

lib/Parse/ParseType.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ Parser::ParsedTypeAttributeList::applyAttributesToType(Parser &p,
5959
ty = new (p.Context) SendingTypeRepr(ty, SendingLoc);
6060
}
6161

62+
if (CallerIsolatedLoc.isValid()) {
63+
ty = new (p.Context) CallerIsolatedTypeRepr(ty, CallerIsolatedLoc);
64+
}
65+
6266
if (lifetimeEntry) {
6367
ty = LifetimeDependentTypeRepr::create(p.Context, ty, lifetimeEntry);
6468
}
@@ -1737,6 +1741,13 @@ bool Parser::canParseTypeScalar() {
17371741
if (Tok.isContextualKeyword("sending"))
17381742
consumeToken();
17391743

1744+
if (Tok.isContextualKeyword("nonisolated")) {
1745+
consumeToken();
1746+
if (Tok.is(tok::l_paren)) {
1747+
skipSingle();
1748+
}
1749+
}
1750+
17401751
if (!canParseTypeSimpleOrComposition())
17411752
return false;
17421753

lib/Sema/TypeCheckDecl.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2294,7 +2294,11 @@ ParamSpecifierRequest::evaluate(Evaluator &evaluator,
22942294
}
22952295
return ownershipRepr->getSpecifier();
22962296
}
2297-
2297+
2298+
if (auto callerIsolated = dyn_cast<CallerIsolatedTypeRepr>(nestedRepr)) {
2299+
nestedRepr = callerIsolated->getBase();
2300+
}
2301+
22982302
return ParamSpecifier::Default;
22992303
}
23002304

0 commit comments

Comments
 (0)