Skip to content

Commit 3c49e46

Browse files
authored
Merge pull request swiftlang#33906 from DougGregor/concurrency-actors
[Concurrency] Basic support for actor classes and actor isolation
2 parents 4b389cd + 099de9d commit 3c49e46

20 files changed

+728
-12
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
@@ -3986,6 +3986,9 @@ class ClassDecl final : public NominalTypeDecl {
39863986
return getForeignClassKind() != ForeignKind::Normal;
39873987
}
39883988

3989+
/// Whether the class is an actor.
3990+
bool isActor() const;
3991+
39893992
/// Returns true if the class has designated initializers that are not listed
39903993
/// in its members.
39913994
///

include/swift/AST/DiagnosticsSema.def

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4142,6 +4142,32 @@ ERROR(satisfy_async_objc,none,
41424142
ERROR(async_objc_dynamic_self,none,
41434143
"asynchronous method returning 'Self' cannot be '@objc'", ())
41444144

4145+
ERROR(actor_without_concurrency,none,
4146+
"'actor' classes require experimental concurrency support", ())
4147+
ERROR(actor_with_nonactor_superclass,none,
4148+
"actor class cannot inherit from non-actor class %0", (DeclName))
4149+
4150+
ERROR(actor_isolated_non_self_reference,none,
4151+
"actor-isolated %0 %1 can only be referenced "
4152+
"%select{inside the actor|on 'self'}2",
4153+
(DescriptiveDeclKind, DeclName, bool))
4154+
WARNING(concurrent_access_local,none,
4155+
"local %0 %1 is unsafe to reference in code that may execute "
4156+
"concurrently",
4157+
(DescriptiveDeclKind, DeclName))
4158+
ERROR(actor_isolated_concurrent_access,none,
4159+
"actor-isolated %0 %1 is unsafe to reference in code "
4160+
"that may execute concurrently",
4161+
(DescriptiveDeclKind, DeclName))
4162+
NOTE(actor_isolated_method,none,
4163+
"only asynchronous methods can be used outside the actor instance; "
4164+
"do you want to add 'async'?", ())
4165+
NOTE(actor_mutable_state,none,
4166+
"mutable state is only available within the actor instance", ())
4167+
WARNING(shared_mutable_state_access,none,
4168+
"reference to %0 %1 is not concurrency-safe because it involves "
4169+
"shared mutable state", (DescriptiveDeclKind, DeclName))
4170+
41454171
//------------------------------------------------------------------------------
41464172
// MARK: Type Check Types
41474173
//------------------------------------------------------------------------------

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
@@ -4428,6 +4428,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
44284428
}
44294429

44304430
static bool canUseAttributeOnDecl(DeclAttrKind DAK, bool IsInSil,
4431+
bool IsConcurrencyEnabled,
44314432
Optional<DeclKind> DK) {
44324433
if (DeclAttribute::isUserInaccessible(DAK))
44334434
return false;
@@ -4437,6 +4438,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
44374438
return false;
44384439
if (!IsInSil && DeclAttribute::isSilOnly(DAK))
44394440
return false;
4441+
if (!IsConcurrencyEnabled && DeclAttribute::isConcurrencyOnly(DAK))
4442+
return false;
44404443
if (!DK.hasValue())
44414444
return true;
44424445
return DeclAttribute::canAttributeAppearOnDeclKind(DAK, DK.getValue());
@@ -4454,9 +4457,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
44544457
#include "swift/AST/DeclNodes.def"
44554458
}
44564459
}
4460+
bool IsConcurrencyEnabled = Ctx.LangOpts.EnableExperimentalConcurrency;
44574461
std::string Description = TargetName.str() + " Attribute";
44584462
#define DECL_ATTR(KEYWORD, NAME, ...) \
4459-
if (canUseAttributeOnDecl(DAK_##NAME, IsInSil, DK)) \
4463+
if (canUseAttributeOnDecl(DAK_##NAME, IsInSil, IsConcurrencyEnabled, DK)) \
44604464
addDeclAttrKeyword(#KEYWORD, Description);
44614465
#include "swift/AST/Attr.def"
44624466
}
@@ -5503,17 +5507,25 @@ addKeyword(CodeCompletionResultSink &Sink, StringRef Name,
55035507
Builder.setExpectedTypeRelation(TypeRelation);
55045508
}
55055509

5506-
static void addDeclKeywords(CodeCompletionResultSink &Sink) {
5510+
static void addDeclKeywords(CodeCompletionResultSink &Sink,
5511+
bool IsConcurrencyEnabled) {
55075512
auto AddDeclKeyword = [&](StringRef Name, CodeCompletionKeywordKind Kind,
55085513
Optional<DeclAttrKind> DAK) {
55095514
if (Name == "let" || Name == "var") {
55105515
// Treat keywords that could be the start of a pattern specially.
55115516
return;
55125517
}
55135518

5519+
// FIXME: This should use canUseAttributeOnDecl.
5520+
55145521
// Remove user inaccessible keywords.
55155522
if (DAK.hasValue() && DeclAttribute::isUserInaccessible(*DAK)) return;
55165523

5524+
// Remove keywords only available when concurrency is enabled.
5525+
if (DAK.hasValue() && !IsConcurrencyEnabled &&
5526+
DeclAttribute::isConcurrencyOnly(*DAK))
5527+
return;
5528+
55175529
addKeyword(Sink, Name, Kind);
55185530
};
55195531

@@ -5626,7 +5638,7 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
56265638
LLVM_FALLTHROUGH;
56275639
}
56285640
case CompletionKind::StmtOrExpr:
5629-
addDeclKeywords(Sink);
5641+
addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
56305642
addStmtKeywords(Sink, MaybeFuncBody);
56315643
LLVM_FALLTHROUGH;
56325644
case CompletionKind::ReturnStmtExpr:
@@ -5687,7 +5699,7 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
56875699
.Default(false);
56885700
}) != ParsedKeywords.end();
56895701
if (!HasDeclIntroducer) {
5690-
addDeclKeywords(Sink);
5702+
addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
56915703
addLetVarKeywords(Sink);
56925704
}
56935705
break;
@@ -6384,15 +6396,15 @@ void CodeCompletionCallbacksImpl::doneParsing() {
63846396

63856397
if (CurDeclContext->isTypeContext()) {
63866398
// Override completion (CompletionKind::NominalMemberBeginning).
6387-
addDeclKeywords(Sink);
6399+
addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
63886400
addLetVarKeywords(Sink);
63896401
SmallVector<StringRef, 0> ParsedKeywords;
63906402
CompletionOverrideLookup OverrideLookup(Sink, Context, CurDeclContext,
63916403
ParsedKeywords, SourceLoc());
63926404
OverrideLookup.getOverrideCompletions(SourceLoc());
63936405
} else {
63946406
// Global completion (CompletionKind::PostfixExprBeginning).
6395-
addDeclKeywords(Sink);
6407+
addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
63966408
addStmtKeywords(Sink, MaybeFuncBody);
63976409
addSuperKeyword(Sink);
63986410
addLetVarKeywords(Sink);

lib/Parse/ParseDecl.cpp

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

lib/Sema/MiscDiagnostics.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4589,6 +4589,7 @@ void swift::performSyntacticExprDiagnostics(const Expr *E,
45894589
if (ctx.LangOpts.EnableObjCInterop)
45904590
diagDeprecatedObjCSelectors(DC, E);
45914591
diagnoseConstantArgumentRequirement(E, DC);
4592+
checkActorIsolation(E, DC);
45924593
}
45934594

45944595
void swift::performStmtDiagnostics(ASTContext &ctx, const Stmt *S) {

0 commit comments

Comments
 (0)