Skip to content

Commit 0f58eb2

Browse files
authored
[Sema] Fix and cleanup distributed id/actorSystem synthesis (#85245)
1 parent e0de61c commit 0f58eb2

28 files changed

+336
-555
lines changed

include/swift/AST/Decl.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,12 @@ bool conflicting(ASTContext &ctx,
374374
bool *wouldConflictInSwift5 = nullptr,
375375
bool skipProtocolExtensionCheck = false);
376376

377+
/// The kind of special compiler synthesized property in a \c distributed actor,
378+
/// currently this includes \c id and \c actorSystem.
379+
enum class SpecialDistributedProperty {
380+
Id, ActorSystem
381+
};
382+
377383
/// The kind of artificial main to generate.
378384
enum class ArtificialMainKind : uint8_t {
379385
NSApplicationMain,
@@ -3056,6 +3062,12 @@ class ValueDecl : public Decl {
30563062
/// `distributed var get { }` accessors.
30573063
bool isDistributedGetAccessor() const;
30583064

3065+
/// Whether this is the special synthesized 'id' or 'actorSystem' property
3066+
/// of a distributed actor. If \p onlyCheckName is set, then any
3067+
/// matching user-defined property with the name is also considered.
3068+
std::optional<SpecialDistributedProperty>
3069+
isSpecialDistributedProperty(bool onlyCheckName = false) const;
3070+
30593071
bool hasName() const { return bool(Name); }
30603072
bool isOperator() const { return Name.isOperator(); }
30613073

@@ -5430,7 +5442,6 @@ enum class KnownDerivableProtocolKind : uint8_t {
54305442
Decodable,
54315443
AdditiveArithmetic,
54325444
Differentiable,
5433-
Identifiable,
54345445
Actor,
54355446
DistributedActor,
54365447
DistributedActorSystem,

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5710,6 +5710,8 @@ ERROR(actor_cannot_inherit_distributed_actor_protocol,none,
57105710
(DeclName))
57115711
ERROR(broken_distributed_actor_requirement,none,
57125712
"DistributedActor protocol is broken: unexpected requirement", ())
5713+
ERROR(broken_distributed_actor_system_requirement,none,
5714+
"DistributedActorSystem protocol is broken: unexpected requirement", ())
57135715
ERROR(distributed_actor_system_conformance_missing_adhoc_requirement,none,
57145716
"%kind0 is missing witness for protocol requirement %1",
57155717
(const ValueDecl *, DeclName))

include/swift/AST/TypeCheckRequests.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2978,9 +2978,6 @@ enum class ImplicitMemberAction : uint8_t {
29782978
ResolveCodingKeys,
29792979
ResolveEncodable,
29802980
ResolveDecodable,
2981-
ResolveDistributedActor,
2982-
ResolveDistributedActorID,
2983-
ResolveDistributedActorSystem,
29842981
};
29852982

29862983
class ResolveImplicitMemberRequest

lib/AST/Decl.cpp

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6449,6 +6449,16 @@ void NominalTypeDecl::synthesizeSemanticMembersIfNeeded(DeclName member) {
64496449
if (isa<ProtocolDecl>(this))
64506450
return;
64516451

6452+
auto baseName = member.getBaseName();
6453+
auto &Context = getASTContext();
6454+
6455+
// For a distributed actor `id` and `actorSystem` can be synthesized without
6456+
// causing cycles so do them above the cycle guard.
6457+
if (member.isSimpleName(Context.Id_id))
6458+
(void)getDistributedActorIDProperty();
6459+
if (member.isSimpleName(Context.Id_actorSystem))
6460+
(void)getDistributedActorSystemProperty();
6461+
64526462
// Silently break cycles here because we can't be sure when and where a
64536463
// request to synthesize will come from yet.
64546464
// FIXME: rdar://56844567
@@ -6458,14 +6468,12 @@ void NominalTypeDecl::synthesizeSemanticMembersIfNeeded(DeclName member) {
64586468
Bits.NominalTypeDecl.IsComputingSemanticMembers = true;
64596469
SWIFT_DEFER { Bits.NominalTypeDecl.IsComputingSemanticMembers = false; };
64606470

6461-
auto baseName = member.getBaseName();
6462-
auto &Context = getASTContext();
64636471
std::optional<ImplicitMemberAction> action = std::nullopt;
64646472
if (baseName.isConstructor())
64656473
action.emplace(ImplicitMemberAction::ResolveImplicitInit);
64666474

64676475
if (member.isSimpleName() && !baseName.isSpecial()) {
6468-
if (baseName.getIdentifier() == getASTContext().Id_CodingKeys) {
6476+
if (baseName.getIdentifier() == Context.Id_CodingKeys) {
64696477
action.emplace(ImplicitMemberAction::ResolveCodingKeys);
64706478
}
64716479
} else {
@@ -6474,22 +6482,13 @@ void NominalTypeDecl::synthesizeSemanticMembersIfNeeded(DeclName member) {
64746482
if (baseName.isConstructor()) {
64756483
if ((member.isSimpleName() || argumentNames.front() == Context.Id_from)) {
64766484
action.emplace(ImplicitMemberAction::ResolveDecodable);
6477-
} else if (argumentNames.front() == Context.Id_system) {
6478-
action.emplace(ImplicitMemberAction::ResolveDistributedActorSystem);
64796485
}
64806486
} else if (!baseName.isSpecial() &&
64816487
baseName.getIdentifier() == Context.Id_encode &&
64826488
(member.isSimpleName() ||
64836489
argumentNames.front() == Context.Id_to)) {
64846490
action.emplace(ImplicitMemberAction::ResolveEncodable);
64856491
}
6486-
} else if (member.isSimpleName() || argumentNames.size() == 2) {
6487-
if (baseName.isConstructor()) {
6488-
if (argumentNames[0] == Context.Id_resolve &&
6489-
argumentNames[1] == Context.Id_using) {
6490-
action.emplace(ImplicitMemberAction::ResolveDistributedActor);
6491-
}
6492-
}
64936492
}
64946493
}
64956494

@@ -7554,8 +7553,6 @@ ProtocolDecl::getKnownDerivableProtocolKind() const {
75547553
return KnownDerivableProtocolKind::AdditiveArithmetic;
75557554
case KnownProtocolKind::Differentiable:
75567555
return KnownDerivableProtocolKind::Differentiable;
7557-
case KnownProtocolKind::Identifiable:
7558-
return KnownDerivableProtocolKind::Identifiable;
75597556
case KnownProtocolKind::Actor:
75607557
return KnownDerivableProtocolKind::Actor;
75617558
case KnownProtocolKind::DistributedActor:

lib/AST/DistributedDecl.cpp

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "swift/AST/DistributedDecl.h"
18-
#include "swift/AST/AccessRequests.h"
19-
#include "swift/AST/AccessScope.h"
2018
#include "swift/AST/ASTContext.h"
21-
#include "swift/AST/ASTWalker.h"
2219
#include "swift/AST/ASTMangler.h"
20+
#include "swift/AST/ASTWalker.h"
21+
#include "swift/AST/AccessRequests.h"
22+
#include "swift/AST/AccessScope.h"
2323
#include "swift/AST/ConformanceLookup.h"
24+
#include "swift/AST/DiagnosticsSema.h"
2425
#include "swift/AST/ExistentialLayout.h"
2526
#include "swift/AST/Expr.h"
2627
#include "swift/AST/ForeignAsyncConvention.h"
@@ -29,7 +30,6 @@
2930
#include "swift/AST/GenericSignature.h"
3031
#include "swift/AST/Initializer.h"
3132
#include "swift/AST/LazyResolver.h"
32-
#include "swift/AST/ASTMangler.h"
3333
#include "swift/AST/Module.h"
3434
#include "swift/AST/NameLookup.h"
3535
#include "swift/AST/NameLookupRequests.h"
@@ -39,9 +39,10 @@
3939
#include "swift/AST/ResilienceExpansion.h"
4040
#include "swift/AST/SourceFile.h"
4141
#include "swift/AST/Stmt.h"
42-
#include "swift/AST/TypeCheckRequests.h"
4342
#include "swift/AST/SwiftNameTranslation.h"
43+
#include "swift/AST/TypeCheckRequests.h"
4444
#include "swift/Basic/Assertions.h"
45+
#include "swift/Basic/StringExtras.h"
4546
#include "swift/ClangImporter/ClangModule.h"
4647
#include "swift/Parse/Lexer.h" // FIXME: Bad dependency
4748
#include "clang/Lex/MacroInfo.h"
@@ -51,7 +52,6 @@
5152
#include "llvm/ADT/Statistic.h"
5253
#include "llvm/Support/Compiler.h"
5354
#include "llvm/Support/raw_ostream.h"
54-
#include "swift/Basic/StringExtras.h"
5555

5656
#include "clang/Basic/CharInfo.h"
5757
#include "clang/Basic/Module.h"
@@ -198,7 +198,7 @@ Type swift::getDistributedActorSystemType(NominalTypeDecl *actor) {
198198

199199
auto DA = C.getDistributedActorDecl();
200200
if (!DA)
201-
return ErrorType::get(C); // FIXME(distributed): just use Type()
201+
return ErrorType::get(C);
202202

203203
// Dig out the actor system type.
204204
Type selfType = actor->getSelfInterfaceType();
@@ -229,17 +229,16 @@ Type swift::getDistributedActorSerializationType(
229229
auto resultTy = getAssociatedTypeOfDistributedSystemOfActor(
230230
actorOrExtension,
231231
ctx.Id_SerializationRequirement);
232+
if (resultTy->hasError())
233+
return resultTy;
232234

233235
// Protocols are allowed to either not provide a `SerializationRequirement`
234236
// at all or provide it in a conformance requirement.
235-
if ((!resultTy || resultTy->hasDependentMember()) &&
237+
if (resultTy->hasDependentMember() &&
236238
actorOrExtension->getSelfProtocolDecl()) {
237239
auto sig = actorOrExtension->getGenericSignatureOfContext();
238240

239241
auto actorProtocol = ctx.getProtocol(KnownProtocolKind::DistributedActor);
240-
if (!actorProtocol)
241-
return Type();
242-
243242
auto serializationTy =
244243
actorProtocol->getAssociatedType(ctx.Id_SerializationRequirement)
245244
->getDeclaredInterfaceType();
@@ -331,29 +330,40 @@ swift::getAssociatedDistributedInvocationDecoderDecodeNextArgumentFunction(
331330
Type swift::getAssociatedTypeOfDistributedSystemOfActor(
332331
DeclContext *actorOrExtension, Identifier member) {
333332
auto &ctx = actorOrExtension->getASTContext();
333+
auto getLoc = [&]() { return extractNearestSourceLoc(actorOrExtension); };
334334

335335
auto actorProtocol = ctx.getProtocol(KnownProtocolKind::DistributedActor);
336-
if (!actorProtocol)
337-
return Type();
336+
if (!actorProtocol) {
337+
ctx.Diags.diagnose(getLoc(), diag::broken_stdlib_type, "DistributedActor");
338+
return ErrorType::get(ctx);
339+
}
338340

339341
AssociatedTypeDecl *actorSystemDecl =
340342
actorProtocol->getAssociatedType(ctx.Id_ActorSystem);
341-
if (!actorSystemDecl)
342-
return Type();
343+
if (!actorSystemDecl) {
344+
ctx.Diags.diagnose(getLoc(), diag::broken_distributed_actor_requirement);
345+
return ErrorType::get(ctx);
346+
}
343347

344348
auto actorSystemProtocol = ctx.getDistributedActorSystemDecl();
345-
if (!actorSystemProtocol)
346-
return Type();
349+
if (!actorSystemProtocol) {
350+
ctx.Diags.diagnose(getLoc(), diag::broken_stdlib_type,
351+
"DistributedActorSystem");
352+
return ErrorType::get(ctx);
353+
}
347354

348355
AssociatedTypeDecl *memberTypeDecl =
349356
actorSystemProtocol->getAssociatedType(member);
350-
if (!memberTypeDecl)
351-
return Type();
357+
if (!memberTypeDecl) {
358+
ctx.Diags.diagnose(getLoc(),
359+
diag::broken_distributed_actor_system_requirement);
360+
return ErrorType::get(ctx);
361+
}
352362

353363
Type memberTy = DependentMemberType::get(
354-
DependentMemberType::get(actorProtocol->getSelfInterfaceType(),
355-
actorSystemDecl),
356-
memberTypeDecl);
364+
DependentMemberType::get(actorProtocol->getSelfInterfaceType(),
365+
actorSystemDecl),
366+
memberTypeDecl);
357367

358368
auto sig = actorOrExtension->getGenericSignatureOfContext();
359369

@@ -365,7 +375,7 @@ Type swift::getAssociatedTypeOfDistributedSystemOfActor(
365375
lookupConformance(
366376
actorType->getDeclaredInterfaceType(), actorProtocol);
367377
if (actorConformance.isInvalid())
368-
return Type();
378+
return ErrorType::get(ctx);
369379

370380
auto subs = SubstitutionMap::getProtocolSubstitutions(actorConformance);
371381

@@ -432,11 +442,7 @@ swift::getDistributedSerializationRequirements(
432442
}
433443

434444
bool swift::checkDistributedSerializationRequirementIsExactlyCodable(
435-
ASTContext &C,
436-
Type type) {
437-
if (!type)
438-
return false;
439-
445+
ASTContext &C, Type type) {
440446
if (type->hasError())
441447
return false;
442448

@@ -1352,6 +1358,42 @@ bool ValueDecl::isDistributedGetAccessor() const {
13521358
return false;
13531359
}
13541360

1361+
std::optional<SpecialDistributedProperty>
1362+
ValueDecl::isSpecialDistributedProperty(bool onlyCheckName) const {
1363+
if (!isa<VarDecl>(this))
1364+
return std::nullopt;
1365+
1366+
auto *DC = getDeclContext();
1367+
auto &ctx = DC->getASTContext();
1368+
1369+
auto kind = [&]() -> std::optional<SpecialDistributedProperty> {
1370+
auto name = getName();
1371+
if (name.isSimpleName(ctx.Id_id))
1372+
return SpecialDistributedProperty::Id;
1373+
if (name.isSimpleName(ctx.Id_actorSystem))
1374+
return SpecialDistributedProperty::ActorSystem;
1375+
1376+
return std::nullopt;
1377+
}();
1378+
if (!kind || onlyCheckName)
1379+
return kind;
1380+
1381+
// The properties can only be synthesized in the nominal itself.
1382+
auto *CD = dyn_cast<ClassDecl>(DC);
1383+
if (!CD || !CD->isDistributedActor())
1384+
return std::nullopt;
1385+
1386+
// The synthesized bit doesn't get preserved by serialization or module
1387+
// interfaces, we only need to check it when compiling a SourceFile though
1388+
// since we'll diagnose any conflicting user-defined versions.
1389+
if (!isSynthesized() && DC->getParentSourceFile() &&
1390+
!DC->isInSwiftinterface()) {
1391+
return std::nullopt;
1392+
}
1393+
1394+
return kind;
1395+
}
1396+
13551397
ConstructorDecl *
13561398
NominalTypeDecl::getDistributedRemoteCallTargetInitFunction() const {
13571399
auto mutableThis = const_cast<NominalTypeDecl *>(this);

lib/AST/TypeCheckRequests.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,15 +1310,6 @@ void swift::simple_display(llvm::raw_ostream &out,
13101310
case ImplicitMemberAction::ResolveDecodable:
13111311
out << "resolve Decodable.init(from:)";
13121312
break;
1313-
case ImplicitMemberAction::ResolveDistributedActor:
1314-
out << "resolve DistributedActor";
1315-
break;
1316-
case ImplicitMemberAction::ResolveDistributedActorID:
1317-
out << "resolve DistributedActor.id";
1318-
break;
1319-
case ImplicitMemberAction::ResolveDistributedActorSystem:
1320-
out << "resolve DistributedActor.actorSystem";
1321-
break;
13221313
}
13231314
}
13241315

lib/SILGen/SILGenDestructor.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,8 @@ void SILGenFunction::emitDistributedRemoteActorDeinit(
7474
continue;
7575

7676
// Just to double-check, we only want to destroy `id` and `actorSystem`
77-
if (vd->getBaseIdentifier() == C.Id_id ||
78-
vd->getBaseIdentifier() == C.Id_actorSystem) {
77+
if (vd->isSpecialDistributedProperty())
7978
destroyClassMember(cleanupLoc, borrowedSelf, vd);
80-
}
8179
}
8280

8381
if (cd->isRootDefaultActor()) {

0 commit comments

Comments
 (0)