Skip to content

Commit 4419f87

Browse files
authored
Merge pull request swiftlang#34201 from DougGregor/concurrency-global-actor
[Concurrency] Global actors
2 parents 301fa01 + 3b807a4 commit 4419f87

20 files changed

+1018
-190
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ class raw_ostream;
2424

2525
namespace swift {
2626
class ClassDecl;
27+
class Type;
28+
29+
/// Determine whether the given types are (canonically) equal, declared here
30+
/// to avoid having to include Types.h.
31+
bool areTypesEqual(Type type1, Type type2);
2732

2833
/// Describes the actor isolation of a given declaration, which determines
2934
/// the actors with which it can interact.
@@ -37,20 +42,26 @@ class ActorIsolation {
3742
/// For example, a mutable stored property or synchronous function within
3843
/// the actor is isolated to the instance of that actor.
3944
ActorInstance,
40-
/// The declaration can refer to actor-isolated state, but can also be
41-
//// referenced from outside the actor.
42-
ActorPrivileged,
4345
/// The declaration is explicitly specified to be independent of any actor,
4446
/// meaning that it can be used from any actor but is also unable to
4547
/// refer to the isolated state of any given actor.
4648
Independent,
49+
/// The declaration is isolated to a global actor. It can refer to other
50+
/// entities with the same global actor.
51+
GlobalActor,
4752
};
4853

4954
private:
5055
Kind kind;
51-
ClassDecl *actor;
56+
union {
57+
ClassDecl *actor;
58+
Type globalActor;
59+
void *pointer;
60+
};
5261

5362
ActorIsolation(Kind kind, ClassDecl *actor) : kind(kind), actor(actor) { }
63+
ActorIsolation(Kind kind, Type globalActor)
64+
: kind(kind), globalActor(globalActor) { }
5465

5566
public:
5667
static ActorIsolation forUnspecified() {
@@ -61,23 +72,28 @@ class ActorIsolation {
6172
return ActorIsolation(Independent, nullptr);
6273
}
6374

64-
static ActorIsolation forActorPrivileged(ClassDecl *actor) {
65-
return ActorIsolation(ActorPrivileged, actor);
66-
}
67-
6875
static ActorIsolation forActorInstance(ClassDecl *actor) {
6976
return ActorIsolation(ActorInstance, actor);
7077
}
7178

79+
static ActorIsolation forGlobalActor(Type globalActor) {
80+
return ActorIsolation(GlobalActor, globalActor);
81+
}
82+
7283
Kind getKind() const { return kind; }
7384

7485
operator Kind() const { return getKind(); }
7586

7687
ClassDecl *getActor() const {
77-
assert(getKind() == ActorInstance || getKind() == ActorPrivileged);
88+
assert(getKind() == ActorInstance);
7889
return actor;
7990
}
8091

92+
Type getGlobalActor() const {
93+
assert(getKind() == GlobalActor);
94+
return globalActor;
95+
}
96+
8197
friend bool operator==(const ActorIsolation &lhs,
8298
const ActorIsolation &rhs) {
8399
if (lhs.kind != rhs.kind)
@@ -89,8 +105,10 @@ class ActorIsolation {
89105
return true;
90106

91107
case ActorInstance:
92-
case ActorPrivileged:
93108
return lhs.actor == rhs.actor;
109+
110+
case GlobalActor:
111+
return areTypesEqual(lhs.globalActor, rhs.globalActor);
94112
}
95113
}
96114

@@ -100,7 +118,7 @@ class ActorIsolation {
100118
}
101119

102120
friend llvm::hash_code hash_value(const ActorIsolation &state) {
103-
return llvm::hash_combine(state.kind, state.actor);
121+
return llvm::hash_combine(state.kind, state.pointer);
104122
}
105123
};
106124

include/swift/AST/Attr.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,12 @@ SIMPLE_DECL_ATTR(actorIndependent, ActorIndependent,
578578
APIStableToAdd | APIBreakingToRemove,
579579
103)
580580

581+
SIMPLE_DECL_ATTR(globalActor, GlobalActor,
582+
OnClass | OnStruct | OnEnum | ConcurrencyOnly |
583+
ABIStableToAdd | ABIBreakingToRemove |
584+
APIStableToAdd | APIBreakingToRemove,
585+
104)
586+
581587
#undef TYPE_ATTR
582588
#undef DECL_ATTR_ALIAS
583589
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/Decl.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,18 @@ class alignas(1 << DeclAlignInBits) Decl {
950950
/// If this returns true, the decl can be safely casted to ValueDecl.
951951
bool isPotentiallyOverridable() const;
952952

953+
/// Returns true if this Decl cannot be seen by any other source file
954+
bool isPrivateToEnclosingFile() const;
955+
956+
/// Retrieve the global actor attribute that applies to this declaration,
957+
/// if any.
958+
///
959+
/// This is the "raw" global actor attribute as written directly on the
960+
/// declaration, along with the nominal type declaration to which it refers,
961+
/// without any inference rules applied.
962+
Optional<std::pair<CustomAttr *, NominalTypeDecl *>>
963+
getGlobalActorAttr() const;
964+
953965
/// If an alternative module name is specified for this decl, e.g. using
954966
/// @_originalDefinedIn attribute, this function returns this module name.
955967
StringRef getAlternateModuleName() const;
@@ -3170,6 +3182,20 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
31703182

31713183
void synthesizeSemanticMembersIfNeeded(DeclName member);
31723184

3185+
/// Retrieves the static 'shared' property of a global actor type, which
3186+
/// is used to extract the actor instance.
3187+
///
3188+
/// \returns the static 'shared' property for a global actor, or \c nullptr
3189+
/// for types that are not global actors.
3190+
VarDecl *getGlobalActorInstance() const;
3191+
3192+
/// Whether this type is a global actor, which can be used as an
3193+
/// attribute to decorate declarations for inclusion in the actor-isolated
3194+
/// state denoted by this type.
3195+
bool isGlobalActor() const {
3196+
return getGlobalActorInstance() != nullptr;
3197+
}
3198+
31733199
// Implement isa/cast/dyncast/etc.
31743200
static bool classof(const Decl *D) {
31753201
return D->getKind() >= DeclKind::First_NominalTypeDecl &&

include/swift/AST/DiagnosticsSema.def

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4153,6 +4153,21 @@ ERROR(actor_isolated_self_independent_context,none,
41534153
"actor-isolated %0 %1 can not be referenced from an "
41544154
"'@actorIndependent' context",
41554155
(DescriptiveDeclKind, DeclName))
4156+
ERROR(actor_isolated_global_actor_context,none,
4157+
"actor-isolated %0 %1 can not be referenced from context of global "
4158+
"actor %2",
4159+
(DescriptiveDeclKind, DeclName, Type))
4160+
ERROR(global_actor_from_instance_actor_context,none,
4161+
"%0 %1 isolated to global actor %2 can not be referenced from actor %3",
4162+
(DescriptiveDeclKind, DeclName, Type, DeclName))
4163+
ERROR(global_actor_from_other_global_actor_context,none,
4164+
"%0 %1 isolated to global actor %2 can not be referenced from "
4165+
"different global actor %3",
4166+
(DescriptiveDeclKind, DeclName, Type, Type))
4167+
ERROR(global_actor_from_independent_context,none,
4168+
"%0 %1 isolated to global actor %2 can not be referenced from an "
4169+
"'@actorIndependent' context",
4170+
(DescriptiveDeclKind, DeclName, Type))
41564171
ERROR(actor_isolated_partial_apply,none,
41574172
"actor-isolated %0 %1 can not be partially applied",
41584173
(DescriptiveDeclKind, DeclName))
@@ -4205,6 +4220,36 @@ ERROR(enqueue_partial_task_not_in_context,none,
42054220
"'enqueue(partialTask:)' can only be implemented in the definition of "
42064221
"actor class %0", (Type))
42074222

4223+
ERROR(global_actor_missing_shared,none,
4224+
"global actor %0 requires a static property 'shared' that produces an "
4225+
"actor instance", (Identifier))
4226+
NOTE(global_actor_shared_not_static,none,
4227+
"'shared' property in global actor is not 'static'", ())
4228+
NOTE(global_actor_shared_inaccessible,none,
4229+
"'shared' property has more restrictive access (%0) than its global actor "
4230+
"(%1)",
4231+
(StringRef, StringRef))
4232+
NOTE(global_actor_shared_constrained_extension,none,
4233+
"'shared' property in global actor cannot be in a constrained extension",
4234+
())
4235+
NOTE(global_actor_shared_non_actor_type,none,
4236+
"'shared' property type %0 does not conform to the 'Actor' protocol",
4237+
(Type))
4238+
4239+
ERROR(multiple_global_actors,none,
4240+
"declaration can not have multiple global actor attributes (%0 and %1)",
4241+
(Identifier, Identifier))
4242+
ERROR(global_actor_disallowed,none,
4243+
"%0 cannot have a global actor", (DescriptiveDeclKind))
4244+
ERROR(global_actor_on_actor_class,none,
4245+
"actor class %0 cannot have a global actor", (Identifier))
4246+
ERROR(global_actor_on_local_variable,none,
4247+
"local variable %0 cannot have a global actor", (DeclName))
4248+
4249+
ERROR(actor_isolation_multiple_attr,none,
4250+
"%0 %1 has multiple actor-isolation attributes ('%2' and '%3')",
4251+
(DescriptiveDeclKind, DeclName, StringRef, StringRef))
4252+
42084253
//------------------------------------------------------------------------------
42094254
// MARK: Type Check Types
42104255
//------------------------------------------------------------------------------

include/swift/AST/KnownIdentifiers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ IDENTIFIER(Selector)
119119
IDENTIFIER(self)
120120
IDENTIFIER(Self)
121121
IDENTIFIER(setObject)
122+
IDENTIFIER(shared)
122123
IDENTIFIER(simd)
123124
IDENTIFIER(storage)
124125
IDENTIFIER(stringValue)

include/swift/AST/TypeCheckRequests.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,55 @@ class IsActorRequest :
853853
bool isCached() const { return true; }
854854
};
855855

856+
/// Retrieve the static "shared" property within a global actor that provides
857+
/// the actor instance representing the global actor.
858+
///
859+
/// Global actors can be applied to a declaration to indicate that the
860+
/// declaration operations on state that is protected by the global actor.
861+
class GlobalActorInstanceRequest :
862+
public SimpleRequest<GlobalActorInstanceRequest,
863+
VarDecl *(NominalTypeDecl *),
864+
RequestFlags::Cached> {
865+
public:
866+
using SimpleRequest::SimpleRequest;
867+
868+
private:
869+
friend SimpleRequest;
870+
871+
VarDecl *evaluate(Evaluator &evaluator, NominalTypeDecl *nominal) const;
872+
873+
public:
874+
// Caching
875+
bool isCached() const { return true; }
876+
};
877+
878+
using CustomAttrNominalPair = std::pair<CustomAttr *, NominalTypeDecl *>;
879+
880+
/// Request the custom attribute which denotes the global actor for the given
881+
/// declaration.
882+
///
883+
/// This is the "raw" global actor attribute as written directly on the
884+
/// declaration, with any inference rules applied.
885+
class GlobalActorAttributeRequest :
886+
public SimpleRequest<
887+
GlobalActorAttributeRequest,
888+
Optional<CustomAttrNominalPair>(Decl *),
889+
RequestFlags::Cached> {
890+
public:
891+
using SimpleRequest::SimpleRequest;
892+
893+
private:
894+
friend SimpleRequest;
895+
896+
// Evaluation.
897+
Optional<std::pair<CustomAttr *, NominalTypeDecl *>>
898+
evaluate(Evaluator &evaluator, Decl *decl) const;
899+
900+
public:
901+
// Caching
902+
bool isCached() const { return true; }
903+
};
904+
856905
/// Determine the actor isolation for the given declaration.
857906
class ActorIsolationRequest :
858907
public SimpleRequest<ActorIsolationRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ SWIFT_REQUEST(TypeChecker, CanBeAsyncHandlerRequest, bool(FuncDecl *),
8686
Cached, NoLocationInfo)
8787
SWIFT_REQUEST(TypeChecker, IsActorRequest, bool(ClassDecl *),
8888
Cached, NoLocationInfo)
89+
SWIFT_REQUEST(TypeChecker, GlobalActorInstanceRequest,
90+
VarDecl *(NominalTypeDecl *),
91+
Cached, NoLocationInfo)
92+
SWIFT_REQUEST(TypeChecker, GlobalActorAttributeRequest,
93+
Optional<CustomAttrNominalPair>(Decl *),
94+
Cached, NoLocationInfo)
8995
SWIFT_REQUEST(TypeChecker, ActorIsolationRequest,
9096
ActorIsolationState(ValueDecl *),
9197
Cached, NoLocationInfo)

include/swift/Basic/CTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ SWIFT_TYPEID_NAMED(std::string, String)
3838
SWIFT_TYPEID_NAMED(evaluator::SideEffect, SideEffect)
3939
SWIFT_TYPEID_TEMPLATE1_NAMED(std::vector, Vector, typename T, T)
4040
SWIFT_TYPEID_TEMPLATE1_NAMED(std::unique_ptr, UniquePtr, typename T, T)
41+
SWIFT_TYPEID_TEMPLATE2_NAMED(std::pair, Pair, typename T1, T1, typename T2, T2)
4142

4243
// LLVM ADT types.
4344
SWIFT_TYPEID_TEMPLATE1_NAMED(llvm::TinyPtrVector, TinyPtrVector, typename T, T)
4445
SWIFT_TYPEID_TEMPLATE1_NAMED(llvm::ArrayRef, ArrayRef, typename T, T)
46+
SWIFT_TYPEID_TEMPLATE1_NAMED(llvm::Optional, Optional, typename T, T)

include/swift/Basic/DefineTypeIDZone.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ template<> struct TypeIDZoneTypes<Zone::SWIFT_TYPEID_ZONE> {
4040
enum Types : uint8_t {
4141
#define SWIFT_TYPEID_NAMED(Type, Name) Name,
4242
#define SWIFT_TYPEID_TEMPLATE1_NAMED(Template, Name, Param1, Arg1) Name,
43+
#define SWIFT_TYPEID_TEMPLATE2_NAMED(Template, Name, Param1, Arg1, Param2, Arg2) Name,
4344
#include SWIFT_TYPEID_HEADER
4445
#undef SWIFT_TYPEID_NAMED
4546
#undef SWIFT_TYPEID_TEMPLATE1_NAMED
47+
#undef SWIFT_TYPEID_TEMPLATE2_NAMED
4648
};
4749
};
4850

@@ -77,12 +79,34 @@ public: \
7779
\
7880
template<Param1> const uint64_t TypeID<Template<Arg1>>::value;
7981

82+
#define SWIFT_TYPEID_TEMPLATE2_NAMED(Template, Name, Param1, Arg1, Param2, Arg2) \
83+
template<Param1, Param2> struct TypeID<Template<Arg1, Arg2>> { \
84+
private: \
85+
static const uint64_t templateID = \
86+
formTypeID(static_cast<uint8_t>(Zone::SWIFT_TYPEID_ZONE), \
87+
TypeIDZoneTypes<Zone::SWIFT_TYPEID_ZONE>::Name); \
88+
\
89+
public: \
90+
static const uint64_t value = \
91+
(TypeID<Arg1>::value << 32) | \
92+
(TypeID<Arg2>::value << 16) | \
93+
templateID; \
94+
\
95+
static std::string getName() { \
96+
return std::string(#Name) + "<" + TypeID<Arg1>::getName() + \
97+
", " + TypeID<Arg2>::getName() + ">"; \
98+
} \
99+
}; \
100+
\
101+
template<Param1, Param2> const uint64_t TypeID<Template<Arg1, Arg2>>::value;
102+
80103
#include SWIFT_TYPEID_HEADER
81104

82105
#undef SWIFT_REQUEST
83106

84107
#undef SWIFT_TYPEID_NAMED
85108
#undef SWIFT_TYPEID_TEMPLATE1_NAMED
109+
#undef SWIFT_TYPEID_TEMPLATE2_NAMED
86110

87111
#undef SWIFT_TYPEID
88112
#undef SWIFT_TYPEID_ZONE

include/swift/Basic/SimpleDisplay.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/Support/raw_ostream.h"
2424
#include <tuple>
2525
#include <type_traits>
26+
#include <utility>
2627

2728
namespace swift {
2829
template<typename T>
@@ -93,7 +94,17 @@ namespace swift {
9394
const std::tuple<Types...> &value) {
9495
simple_display_tuple<0>(out, value);
9596
}
96-
97+
98+
template<typename T1, typename T2>
99+
void simple_display(llvm::raw_ostream &out,
100+
const std::pair<T1, T2> &value) {
101+
out << "(";
102+
simple_display(out, value.first);
103+
out << ", ";
104+
simple_display(out, value.second);
105+
out << ")";
106+
}
107+
97108
template<typename T>
98109
void simple_display(llvm::raw_ostream &out,
99110
const llvm::TinyPtrVector<T> &vector) {

lib/AST/Decl.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,14 @@ static_assert(sizeof(checkSourceLocType(&ID##Decl::getLoc)) == 2, \
672672
llvm_unreachable("invalid file kind");
673673
}
674674

675+
Optional<CustomAttrNominalPair> Decl::getGlobalActorAttr() const {
676+
auto &ctx = getASTContext();
677+
auto mutableThis = const_cast<Decl *>(this);
678+
return evaluateOrDefault(ctx.evaluator,
679+
GlobalActorAttributeRequest{mutableThis},
680+
None);
681+
}
682+
675683
Expr *AbstractFunctionDecl::getSingleExpressionBody() const {
676684
assert(hasSingleExpressionBody() && "Not a single-expression body");
677685
auto braceStmt = getBody();
@@ -4048,6 +4056,13 @@ void NominalTypeDecl::synthesizeSemanticMembersIfNeeded(DeclName member) {
40484056
}
40494057
}
40504058

4059+
VarDecl *NominalTypeDecl::getGlobalActorInstance() const {
4060+
auto mutableThis = const_cast<NominalTypeDecl *>(this);
4061+
return evaluateOrDefault(getASTContext().evaluator,
4062+
GlobalActorInstanceRequest{mutableThis},
4063+
nullptr);
4064+
}
4065+
40514066
ClassDecl::ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
40524067
ArrayRef<TypeLoc> Inherited,
40534068
GenericParamList *GenericParams, DeclContext *Parent)

0 commit comments

Comments
 (0)