Skip to content

Commit 22a350b

Browse files
committed
[Concurrency] Add parsing support for actor classes.
Introduce the "actor class" syntax. Ensure that it is only used for root classes or classes that inherit from other actor classes.
1 parent d50bc21 commit 22a350b

File tree

16 files changed

+129
-7
lines changed

16 files changed

+129
-7
lines changed

include/swift/AST/Attr.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,12 @@ SIMPLE_DECL_ATTR(asyncHandler, AsyncHandler,
566566
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
567567
101)
568568

569+
CONTEXTUAL_SIMPLE_DECL_ATTR(actor, Actor,
570+
OnClass | ConcurrencyOnly |
571+
ABIBreakingToAdd | ABIBreakingToRemove |
572+
APIBreakingToAdd | APIBreakingToRemove,
573+
102)
574+
569575
#undef TYPE_ATTR
570576
#undef DECL_ATTR_ALIAS
571577
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/Attr.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,9 @@ class DeclAttribute : public AttributeBase {
418418

419419
/// The opposite of ABIBreakingToRemove
420420
ABIStableToRemove = 1ull << (unsigned(DeclKindIndex::Last_Decl) + 15),
421+
422+
/// Whether this attribute is only valid when concurrency is enabled.
423+
ConcurrencyOnly = 1ull << (unsigned(DeclKindIndex::Last_Decl) + 16),
421424
};
422425

423426
LLVM_READNONE
@@ -496,6 +499,10 @@ class DeclAttribute : public AttributeBase {
496499
return getOptions(DK) & SILOnly;
497500
}
498501

502+
static bool isConcurrencyOnly(DeclAttrKind DK) {
503+
return getOptions(DK) & ConcurrencyOnly;
504+
}
505+
499506
static bool isUserInaccessible(DeclAttrKind DK) {
500507
return getOptions(DK) & UserInaccessible;
501508
}

include/swift/AST/Decl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4007,6 +4007,9 @@ class ClassDecl final : public NominalTypeDecl {
40074007
return getForeignClassKind() != ForeignKind::Normal;
40084008
}
40094009

4010+
/// Whether the class is an actor.
4011+
bool isActor() const;
4012+
40104013
/// Returns true if the class has designated initializers that are not listed
40114014
/// in its members.
40124015
///

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4132,6 +4132,11 @@ ERROR(satisfy_async_objc,none,
41324132
ERROR(async_objc_dynamic_self,none,
41334133
"asynchronous method returning 'Self' cannot be '@objc'", ())
41344134

4135+
ERROR(actor_without_concurrency,none,
4136+
"'actor' classes require experimental concurrency support", ())
4137+
ERROR(actor_with_nonactor_superclass,none,
4138+
"actor class cannot inherit from non-actor class %0", (DeclName))
4139+
41354140
//------------------------------------------------------------------------------
41364141
// MARK: Type Check Types
41374142
//------------------------------------------------------------------------------

include/swift/AST/TypeCheckRequests.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,24 @@ class IsAsyncHandlerRequest :
799799
bool isCached() const { return true; }
800800
};
801801

802+
/// Determine whether the given class is an actor.
803+
class IsActorRequest :
804+
public SimpleRequest<IsActorRequest,
805+
bool(ClassDecl *),
806+
RequestFlags::Cached> {
807+
public:
808+
using SimpleRequest::SimpleRequest;
809+
810+
private:
811+
friend SimpleRequest;
812+
813+
bool evaluate(Evaluator &evaluator, ClassDecl *classDecl) const;
814+
815+
public:
816+
// Caching
817+
bool isCached() const { return true; }
818+
};
819+
802820
/// Request whether the storage has a mutating getter.
803821
class IsGetterMutatingRequest :
804822
public SimpleRequest<IsGetterMutatingRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ SWIFT_REQUEST(TypeChecker, FunctionBuilderTypeRequest, Type(ValueDecl *),
8383
Cached, NoLocationInfo)
8484
SWIFT_REQUEST(TypeChecker, IsAsyncHandlerRequest, bool(FuncDecl *),
8585
Cached, NoLocationInfo)
86+
SWIFT_REQUEST(TypeChecker, IsActorRequest, bool(ClassDecl *),
87+
Cached, NoLocationInfo)
8688
SWIFT_REQUEST(TypeChecker, FunctionOperatorRequest, OperatorDecl *(FuncDecl *),
8789
Cached, NoLocationInfo)
8890
SWIFT_REQUEST(NameLookup, GenericSignatureRequest,

lib/AST/Decl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4222,6 +4222,13 @@ GetDestructorRequest::evaluate(Evaluator &evaluator, ClassDecl *CD) const {
42224222
return DD;
42234223
}
42244224

4225+
bool ClassDecl::isActor() const {
4226+
auto mutableThis = const_cast<ClassDecl *>(this);
4227+
return evaluateOrDefault(getASTContext().evaluator,
4228+
IsActorRequest{mutableThis},
4229+
false);
4230+
}
4231+
42254232
bool ClassDecl::hasMissingDesignatedInitializers() const {
42264233
return evaluateOrDefault(
42274234
getASTContext().evaluator,

lib/IDE/CodeCompletion.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4417,6 +4417,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
44174417
}
44184418

44194419
static bool canUseAttributeOnDecl(DeclAttrKind DAK, bool IsInSil,
4420+
bool IsConcurrencyEnabled,
44204421
Optional<DeclKind> DK) {
44214422
if (DeclAttribute::isUserInaccessible(DAK))
44224423
return false;
@@ -4426,6 +4427,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
44264427
return false;
44274428
if (!IsInSil && DeclAttribute::isSilOnly(DAK))
44284429
return false;
4430+
if (!IsConcurrencyEnabled && DeclAttribute::isConcurrencyOnly(DAK))
4431+
return false;
44294432
if (!DK.hasValue())
44304433
return true;
44314434
return DeclAttribute::canAttributeAppearOnDeclKind(DAK, DK.getValue());
@@ -4443,9 +4446,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
44434446
#include "swift/AST/DeclNodes.def"
44444447
}
44454448
}
4449+
bool IsConcurrencyEnabled = Ctx.LangOpts.EnableExperimentalConcurrency;
44464450
std::string Description = TargetName.str() + " Attribute";
44474451
#define DECL_ATTR(KEYWORD, NAME, ...) \
4448-
if (canUseAttributeOnDecl(DAK_##NAME, IsInSil, DK)) \
4452+
if (canUseAttributeOnDecl(DAK_##NAME, IsInSil, IsConcurrencyEnabled, DK)) \
44494453
addDeclAttrKeyword(#KEYWORD, Description);
44504454
#include "swift/AST/Attr.def"
44514455
}
@@ -5488,17 +5492,25 @@ addKeyword(CodeCompletionResultSink &Sink, StringRef Name,
54885492
Builder.setExpectedTypeRelation(TypeRelation);
54895493
}
54905494

5491-
static void addDeclKeywords(CodeCompletionResultSink &Sink) {
5495+
static void addDeclKeywords(CodeCompletionResultSink &Sink,
5496+
bool IsConcurrencyEnabled) {
54925497
auto AddDeclKeyword = [&](StringRef Name, CodeCompletionKeywordKind Kind,
54935498
Optional<DeclAttrKind> DAK) {
54945499
if (Name == "let" || Name == "var") {
54955500
// Treat keywords that could be the start of a pattern specially.
54965501
return;
54975502
}
54985503

5504+
// FIXME: This should use canUseAttributeOnDecl.
5505+
54995506
// Remove user inaccessible keywords.
55005507
if (DAK.hasValue() && DeclAttribute::isUserInaccessible(*DAK)) return;
55015508

5509+
// Remove keywords only available when concurrency is enabled.
5510+
if (DAK.hasValue() && !IsConcurrencyEnabled &&
5511+
DeclAttribute::isConcurrencyOnly(*DAK))
5512+
return;
5513+
55025514
addKeyword(Sink, Name, Kind);
55035515
};
55045516

@@ -5611,7 +5623,7 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
56115623
LLVM_FALLTHROUGH;
56125624
}
56135625
case CompletionKind::StmtOrExpr:
5614-
addDeclKeywords(Sink);
5626+
addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
56155627
addStmtKeywords(Sink, MaybeFuncBody);
56165628
LLVM_FALLTHROUGH;
56175629
case CompletionKind::ReturnStmtExpr:
@@ -5672,7 +5684,7 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
56725684
.Default(false);
56735685
}) != ParsedKeywords.end();
56745686
if (!HasDeclIntroducer) {
5675-
addDeclKeywords(Sink);
5687+
addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
56765688
addLetVarKeywords(Sink);
56775689
}
56785690
break;
@@ -6186,15 +6198,15 @@ void CodeCompletionCallbacksImpl::doneParsing() {
61866198

61876199
if (CurDeclContext->isTypeContext()) {
61886200
// Override completion (CompletionKind::NominalMemberBeginning).
6189-
addDeclKeywords(Sink);
6201+
addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
61906202
addLetVarKeywords(Sink);
61916203
SmallVector<StringRef, 0> ParsedKeywords;
61926204
CompletionOverrideLookup OverrideLookup(Sink, Context, CurDeclContext,
61936205
ParsedKeywords, SourceLoc());
61946206
OverrideLookup.getOverrideCompletions(SourceLoc());
61956207
} else {
61966208
// Global completion (CompletionKind::PostfixExprBeginning).
6197-
addDeclKeywords(Sink);
6209+
addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
61986210
addStmtKeywords(Sink, MaybeFuncBody);
61996211
addSuperKeyword(Sink);
62006212
addLetVarKeywords(Sink);

lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3079,6 +3079,7 @@ ParserStatus Parser::parseDeclAttributeList(DeclAttributes &Attributes) {
30793079
// 'nonmutating'
30803080
// '__consuming'
30813081
// 'convenience'
3082+
// 'actor'
30823083
bool Parser::parseDeclModifierList(DeclAttributes &Attributes,
30833084
SourceLoc &StaticLoc,
30843085
StaticSpellingKind &StaticSpelling) {

lib/Sema/TypeCheckAttr.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,14 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
273273
// Trigger the request to check for @asyncHandler.
274274
(void)func->isAsyncHandler();
275275
}
276+
277+
void visitActorAttr(ActorAttr *attr) {
278+
auto classDecl = dyn_cast<ClassDecl>(D);
279+
if (!classDecl)
280+
return; // already diagnosed
281+
282+
(void)classDecl->isActor();
283+
}
276284
};
277285
} // end anonymous namespace
278286

0 commit comments

Comments
 (0)