Skip to content

Commit 75b18ad

Browse files
authored
Merge pull request #34111 from DougGregor/concurrency-actor-protocol
[Concurrency] Introduce Actor protocol to which actor classes all conform
2 parents b972bef + 592a5e1 commit 75b18ad

29 files changed

+765
-14
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,9 @@ namespace SpecialPointerAuthDiscriminators {
11771177

11781178
/// Resilient class stub initializer callback
11791179
const uint16_t ResilientClassStubInitCallback = 0xC671;
1180+
1181+
/// Actor enqueue(partialTask:).
1182+
const uint16_t ActorEnqueuePartialTask = 0x8f3d;
11801183
}
11811184

11821185
/// The number of arguments that will be passed directly to a generic

include/swift/AST/Attr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ SIMPLE_DECL_ATTR(asyncHandler, AsyncHandler,
567567
101)
568568

569569
CONTEXTUAL_SIMPLE_DECL_ATTR(actor, Actor,
570-
OnClass | ConcurrencyOnly |
570+
DeclModifier | OnClass | ConcurrencyOnly |
571571
ABIBreakingToAdd | ABIBreakingToRemove |
572572
APIBreakingToAdd | APIBreakingToRemove,
573573
102)

include/swift/AST/Decl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3816,6 +3816,7 @@ enum class KnownDerivableProtocolKind : uint8_t {
38163816
Decodable,
38173817
AdditiveArithmetic,
38183818
Differentiable,
3819+
Actor,
38193820
};
38203821

38213822
/// ProtocolDecl - A declaration of a protocol, for example:
@@ -5969,6 +5970,14 @@ class FuncDecl : public AbstractFunctionDecl {
59695970

59705971
bool isMainTypeMainMethod() const;
59715972

5973+
/// Whether the given name is enqueue(partialTask:), which is used for
5974+
/// actors.
5975+
static bool isEnqueuePartialTaskName(ASTContext &ctx, DeclName name);
5976+
5977+
/// Determine whether this function is the witness to the Actor protocol's
5978+
/// enqueue(partialTask:) operation within an actor.
5979+
bool isActorEnqueuePartialTaskWitness() const;
5980+
59725981
SelfAccessKind getSelfAccessKind() const;
59735982

59745983
void setSelfAccessKind(SelfAccessKind mod) {

include/swift/AST/DiagnosticsSema.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4101,6 +4101,9 @@ ERROR(not_objc_function_async,none,
41014101
"'async' function cannot be represented in Objective-C", ())
41024102
NOTE(not_objc_function_type_async,none,
41034103
"'async' function types cannot be represented in Objective-C", ())
4104+
ERROR(actor_isolated_objc,none,
4105+
"actor-isolated %0 %1 cannot be @objc",
4106+
(DescriptiveDeclKind, DeclName))
41044107
NOTE(protocol_witness_async_conflict,none,
41054108
"candidate is %select{not |}0'async', but protocol requirement is%select{| not}0",
41064109
(bool))
@@ -4195,6 +4198,13 @@ ERROR(actorisolated_not_actor_instance_member,none,
41954198
"'@actorIsolated' can only be applied to instance members of actors",
41964199
())
41974200

4201+
ERROR(concurrency_lib_missing,none,
4202+
"missing '%0' declaration, probably because the '_Concurrency' "
4203+
"module was not imported", (StringRef))
4204+
ERROR(enqueue_partial_task_not_in_context,none,
4205+
"'enqueue(partialTask:)' can only be implemented in the definition of "
4206+
"actor class %0", (Type))
4207+
41984208
//------------------------------------------------------------------------------
41994209
// MARK: Type Check Types
42004210
//------------------------------------------------------------------------------

include/swift/AST/KnownIdentifiers.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ IDENTIFIER(Change)
4444
IDENTIFIER_WITH_NAME(code_, "_code")
4545
IDENTIFIER(CodingKeys)
4646
IDENTIFIER(combine)
47+
IDENTIFIER_(Concurrency)
4748
IDENTIFIER(container)
4849
IDENTIFIER(CoreGraphics)
4950
IDENTIFIER(CoreMedia)
@@ -67,6 +68,7 @@ IDENTIFIER(encode)
6768
IDENTIFIER(encodeIfPresent)
6869
IDENTIFIER(Encoder)
6970
IDENTIFIER(encoder)
71+
IDENTIFIER(enqueue)
7072
IDENTIFIER(erasing)
7173
IDENTIFIER(error)
7274
IDENTIFIER(errorDomain)
@@ -105,6 +107,8 @@ IDENTIFIER(oldValue)
105107
IDENTIFIER(Optional)
106108
IDENTIFIER_(OptionalNilComparisonType)
107109
IDENTIFIER(parameter)
110+
IDENTIFIER(partialTask)
111+
IDENTIFIER(PartialAsyncTask)
108112
IDENTIFIER(projected)
109113
IDENTIFIER(projectedValue)
110114
IDENTIFIER(Protocol)
@@ -137,6 +141,7 @@ IDENTIFIER(withKeywordArguments)
137141
IDENTIFIER(wrapped)
138142
IDENTIFIER(wrappedValue)
139143
IDENTIFIER(wrapperValue)
144+
IDENTIFIER_WITH_NAME(actorStorage, "$__actor_storage")
140145

141146
// Kinds of layout constraints
142147
IDENTIFIER_WITH_NAME(UnknownLayout, "_UnknownLayout")

include/swift/AST/KnownProtocols.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#define BUILTIN_EXPRESSIBLE_BY_LITERAL_PROTOCOL_(name) \
5959
BUILTIN_EXPRESSIBLE_BY_LITERAL_PROTOCOL_WITH_NAME(name, "_" #name)
6060

61+
PROTOCOL(Actor)
6162
PROTOCOL(Sequence)
6263
PROTOCOL(IteratorProtocol)
6364
PROTOCOL(RawRepresentable)

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,9 @@ ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const {
947947
case KnownProtocolKind::Differentiable:
948948
M = getLoadedModule(Id_Differentiation);
949949
break;
950+
case KnownProtocolKind::Actor:
951+
M = getLoadedModule(Id_Concurrency);
952+
break;
950953
default:
951954
M = getStdlibModule();
952955
break;

lib/AST/Decl.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4922,7 +4922,8 @@ void ProtocolDecl::computeKnownProtocolKind() const {
49224922
auto module = getModuleContext();
49234923
if (module != module->getASTContext().getStdlibModule() &&
49244924
!module->getName().is("Foundation") &&
4925-
!module->getName().is("_Differentiation")) {
4925+
!module->getName().is("_Differentiation") &&
4926+
!module->getName().is("_Concurrency")) {
49264927
const_cast<ProtocolDecl *>(this)->Bits.ProtocolDecl.KnownProtocol = 1;
49274928
return;
49284929
}
@@ -4968,6 +4969,8 @@ Optional<KnownDerivableProtocolKind>
49684969
return KnownDerivableProtocolKind::AdditiveArithmetic;
49694970
case KnownProtocolKind::Differentiable:
49704971
return KnownDerivableProtocolKind::Differentiable;
4972+
case KnownProtocolKind::Actor:
4973+
return KnownDerivableProtocolKind::Actor;
49714974
default: return None;
49724975
}
49734976
}
@@ -7380,6 +7383,56 @@ bool FuncDecl::isMainTypeMainMethod() const {
73807383
getParameters()->size() == 0;
73817384
}
73827385

7386+
bool FuncDecl::isEnqueuePartialTaskName(ASTContext &ctx, DeclName name) {
7387+
if (name.isCompoundName() && name.getBaseName() == ctx.Id_enqueue) {
7388+
auto argumentNames = name.getArgumentNames();
7389+
return argumentNames.size() == 1 && argumentNames[0] == ctx.Id_partialTask;
7390+
}
7391+
7392+
return false;
7393+
}
7394+
7395+
bool FuncDecl::isActorEnqueuePartialTaskWitness() const {
7396+
if (!isEnqueuePartialTaskName(getASTContext(), getName()))
7397+
return false;
7398+
7399+
auto classDecl = getDeclContext()->getSelfClassDecl();
7400+
if (!classDecl)
7401+
return false;
7402+
7403+
if (!classDecl->isActor())
7404+
return false;
7405+
7406+
ASTContext &ctx = getASTContext();
7407+
auto actorProto = ctx.getProtocol(KnownProtocolKind::Actor);
7408+
if (!actorProto)
7409+
return false;
7410+
7411+
FuncDecl *requirement = nullptr;
7412+
for (auto protoMember : actorProto->getParsedMembers()) {
7413+
if (auto protoFunc = dyn_cast<FuncDecl>(protoMember)) {
7414+
if (isEnqueuePartialTaskName(ctx, protoFunc->getName())) {
7415+
requirement = protoFunc;
7416+
break;
7417+
}
7418+
}
7419+
}
7420+
7421+
if (!requirement)
7422+
return false;
7423+
7424+
SmallVector<ProtocolConformance *, 1> conformances;
7425+
classDecl->lookupConformance(
7426+
classDecl->getModuleContext(), actorProto, conformances);
7427+
for (auto conformance : conformances) {
7428+
auto witness = conformance->getWitnessDecl(requirement);
7429+
if (witness == this)
7430+
return true;
7431+
}
7432+
7433+
return false;
7434+
}
7435+
73837436
ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
73847437
bool Failable, SourceLoc FailabilityLoc,
73857438
bool Throws,

lib/AST/ProtocolConformance.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,12 @@ void NominalTypeDecl::prepareConformanceTable() const {
12561256
addSynthesized(KnownProtocolKind::RawRepresentable);
12571257
}
12581258
}
1259+
1260+
// Actor classes conform to the actor protocol.
1261+
if (auto classDecl = dyn_cast<ClassDecl>(mutableThis)) {
1262+
if (classDecl->isActor())
1263+
addSynthesized(KnownProtocolKind::Actor);
1264+
}
12591265
}
12601266

12611267
bool NominalTypeDecl::lookupConformance(

lib/IRGen/GenMeta.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5045,6 +5045,7 @@ SpecialProtocol irgen::getSpecialProtocolID(ProtocolDecl *P) {
50455045
case KnownProtocolKind::AdditiveArithmetic:
50465046
case KnownProtocolKind::Differentiable:
50475047
case KnownProtocolKind::FloatingPoint:
5048+
case KnownProtocolKind::Actor:
50485049
return SpecialProtocol::None;
50495050
}
50505051

lib/IRGen/GenPointerAuth.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,17 @@ PointerAuthEntity::getDeclDiscriminator(IRGenModule &IGM) const {
400400
assert(!constant.isForeign &&
401401
"discriminator for foreign declaration not supported yet!");
402402

403+
// Special case: methods that are witnesses to Actor.enqueue(partialTask:)
404+
// have their own descriminator, which is shared across all actor classes.
405+
if (constant.hasFuncDecl()) {
406+
auto func = dyn_cast<FuncDecl>(constant.getFuncDecl());
407+
if (func->isActorEnqueuePartialTaskWitness()) {
408+
cache = IGM.getSize(
409+
Size(SpecialPointerAuthDiscriminators::ActorEnqueuePartialTask));
410+
return cache;
411+
}
412+
}
413+
403414
auto mangling = constant.mangle();
404415
cache = getDiscriminatorForString(IGM, mangling);
405416
return cache;

lib/Sema/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ add_swift_host_library(swiftSema STATIC
1717
ConstraintLocator.cpp
1818
ConstraintSystem.cpp
1919
DebuggerTestingTransform.cpp
20+
DerivedConformanceActor.cpp
2021
DerivedConformanceAdditiveArithmetic.cpp
2122
DerivedConformanceCaseIterable.cpp
2223
DerivedConformanceCodable.cpp

0 commit comments

Comments
 (0)