Skip to content

Commit 7758492

Browse files
committed
[Concurrency] Implement global actor isolation rules.
Extend the actor isolation checking rules to account for global actors. For example, a function annotated with a given global actor can invoke synchronous methods from the same global actor, but not from a different global actor or a particular actor instance. Similarly, a method of an (instance) actor that is annotated with a global actor attribute is not part of the (instance) actor and, therefore, cannot operate on its actor-isolated state.
1 parent df883f8 commit 7758492

16 files changed

+408
-31
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 37 additions & 3 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.
@@ -38,19 +43,31 @@ class ActorIsolation {
3843
/// the actor is isolated to the instance of that actor.
3944
ActorInstance,
4045
/// The declaration can refer to actor-isolated state, but can also be
41-
//// referenced from outside the actor.
46+
/// referenced from outside the actor.
4247
ActorPrivileged,
4348
/// The declaration is explicitly specified to be independent of any actor,
4449
/// meaning that it can be used from any actor but is also unable to
4550
/// refer to the isolated state of any given actor.
4651
Independent,
52+
/// The declaration is isolated to a global actor. It can refer to other
53+
/// entities with the same global actor.
54+
GlobalActor,
55+
/// The declaration can refer to state isolated by the given global actor,
56+
/// and can be used from anywhere.
57+
GlobalActorPrivileged,
4758
};
4859

4960
private:
5061
Kind kind;
51-
ClassDecl *actor;
62+
union {
63+
ClassDecl *actor;
64+
Type globalActor;
65+
void *pointer;
66+
};
5267

5368
ActorIsolation(Kind kind, ClassDecl *actor) : kind(kind), actor(actor) { }
69+
ActorIsolation(Kind kind, Type globalActor)
70+
: kind(kind), globalActor(globalActor) { }
5471

5572
public:
5673
static ActorIsolation forUnspecified() {
@@ -69,6 +86,14 @@ class ActorIsolation {
6986
return ActorIsolation(ActorInstance, actor);
7087
}
7188

89+
static ActorIsolation forGlobalActorPrivileged(Type globalActor) {
90+
return ActorIsolation(GlobalActorPrivileged, globalActor);
91+
}
92+
93+
static ActorIsolation forGlobalActor(Type globalActor) {
94+
return ActorIsolation(GlobalActor, globalActor);
95+
}
96+
7297
Kind getKind() const { return kind; }
7398

7499
operator Kind() const { return getKind(); }
@@ -78,6 +103,11 @@ class ActorIsolation {
78103
return actor;
79104
}
80105

106+
Type getGlobalActor() const {
107+
assert(getKind() == GlobalActor || getKind() == GlobalActorPrivileged);
108+
return globalActor;
109+
}
110+
81111
friend bool operator==(const ActorIsolation &lhs,
82112
const ActorIsolation &rhs) {
83113
if (lhs.kind != rhs.kind)
@@ -91,6 +121,10 @@ class ActorIsolation {
91121
case ActorInstance:
92122
case ActorPrivileged:
93123
return lhs.actor == rhs.actor;
124+
125+
case GlobalActor:
126+
case GlobalActorPrivileged:
127+
return areTypesEqual(lhs.globalActor, rhs.globalActor);
94128
}
95129
}
96130

@@ -100,7 +134,7 @@ class ActorIsolation {
100134
}
101135

102136
friend llvm::hash_code hash_value(const ActorIsolation &state) {
103-
return llvm::hash_combine(state.kind, state.actor);
137+
return llvm::hash_combine(state.kind, state.pointer);
104138
}
105139
};
106140

include/swift/AST/Decl.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -957,8 +957,10 @@ class alignas(1 << DeclAlignInBits) Decl {
957957
/// if any.
958958
///
959959
/// This is the "raw" global actor attribute as written directly on the
960-
/// declaration, with any inference rules applied.
961-
CustomAttr *getGlobalActorAttr() const;
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;
962964

963965
/// If an alternative module name is specified for this decl, e.g. using
964966
/// @_originalDefinedIn attribute, this function returns this module name.

include/swift/AST/DiagnosticsSema.def

Lines changed: 19 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))
@@ -4231,6 +4246,10 @@ ERROR(global_actor_on_actor_class,none,
42314246
ERROR(global_actor_on_local_variable,none,
42324247
"local variable %0 cannot have a global actor", (DeclName))
42334248

4249+
ERROR(actor_isolation_multiple_attr,none,
4250+
"%0 %1 has multiple actor-isolation attributes ('%2' and '%3')",
4251+
(DescriptiveDeclKind, DeclName, StringRef, StringRef))
4252+
42344253
//------------------------------------------------------------------------------
42354254
// MARK: Type Check Types
42364255
//------------------------------------------------------------------------------

include/swift/AST/TypeCheckRequests.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -880,23 +880,26 @@ class GlobalActorInstanceRequest :
880880
bool isCached() const { return true; }
881881
};
882882

883+
using CustomAttrNominalPair = std::pair<CustomAttr *, NominalTypeDecl *>;
884+
883885
/// Request the custom attribute which denotes the global actor for the given
884886
/// declaration.
885887
///
886888
/// This is the "raw" global actor attribute as written directly on the
887889
/// declaration, with any inference rules applied.
888890
class GlobalActorAttributeRequest :
889-
public SimpleRequest<GlobalActorAttributeRequest,
890-
CustomAttr *(Decl *),
891-
RequestFlags::Cached> {
891+
public SimpleRequest<
892+
GlobalActorAttributeRequest,
893+
Optional<CustomAttrNominalPair>(Decl *),
894+
RequestFlags::Cached> {
892895
public:
893896
using SimpleRequest::SimpleRequest;
894897

895898
private:
896899
friend SimpleRequest;
897900

898901
// Evaluation.
899-
CustomAttr *
902+
Optional<std::pair<CustomAttr *, NominalTypeDecl *>>
900903
evaluate(Evaluator &evaluator, Decl *decl) const;
901904

902905
public:

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ SWIFT_REQUEST(TypeChecker, GlobalActorInstanceRequest,
9191
VarDecl *(NominalTypeDecl *),
9292
Cached, NoLocationInfo)
9393
SWIFT_REQUEST(TypeChecker, GlobalActorAttributeRequest,
94-
CustomAttr *(Decl *), Cached, NoLocationInfo)
94+
Optional<CustomAttrNominalPair>(Decl *),
95+
Cached, NoLocationInfo)
9596
SWIFT_REQUEST(TypeChecker, ActorIsolationRequest,
9697
ActorIsolationState(ValueDecl *),
9798
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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -672,12 +672,12 @@ static_assert(sizeof(checkSourceLocType(&ID##Decl::getLoc)) == 2, \
672672
llvm_unreachable("invalid file kind");
673673
}
674674

675-
CustomAttr *Decl::getGlobalActorAttr() const {
675+
Optional<CustomAttrNominalPair> Decl::getGlobalActorAttr() const {
676676
auto &ctx = getASTContext();
677677
auto mutableThis = const_cast<Decl *>(this);
678678
return evaluateOrDefault(ctx.evaluator,
679679
GlobalActorAttributeRequest{mutableThis},
680-
nullptr);
680+
None);
681681
}
682682

683683
Expr *AbstractFunctionDecl::getSingleExpressionBody() const {

lib/AST/TypeCheckRequests.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,9 +1466,26 @@ void swift::simple_display(
14661466
case ActorIsolation::Unspecified:
14671467
out << "unspecified actor isolation";
14681468
break;
1469+
1470+
case ActorIsolation::GlobalActor:
1471+
out << "actor-isolated to global actor "
1472+
<< state.getGlobalActor().getString();
1473+
break;
1474+
1475+
case ActorIsolation::GlobalActorPrivileged:
1476+
out << "actor-privileged to global actor "
1477+
<< state.getGlobalActor().getString();
1478+
break;
14691479
}
14701480
}
14711481

1482+
bool swift::areTypesEqual(Type type1, Type type2) {
1483+
if (!type1 || !type2)
1484+
return !type1 && !type2;
1485+
1486+
return type1->isEqual(type2);
1487+
}
1488+
14721489
void swift::simple_display(
14731490
llvm::raw_ostream &out, BodyInitKind initKind) {
14741491
switch (initKind) {

0 commit comments

Comments
 (0)