Skip to content

Commit 07c6b78

Browse files
committed
[SILGen] Ensure that we emit the distributed-actor-as-actor conformance
The distributed-actor-as-actor conformance is synthesized by the frontend, so make sure that when we access the API that exposes it (asLocalActor), we be sure to mark the conformance as "used". This is a very specific workaround for general problem with compiler-synthesized conformances. SIL deserialization can bring in a reference to a conformance late in the SIL pipeline, after the point at which SILGen can create the conformance. We should be able to address this systemically to remove the hack.
1 parent f79a108 commit 07c6b78

File tree

6 files changed

+81
-48
lines changed

6 files changed

+81
-48
lines changed

include/swift/AST/KnownIdentifiers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ IDENTIFIER(accumulated)
3232
IDENTIFIER(ActorType)
3333
IDENTIFIER(Any)
3434
IDENTIFIER(ArrayLiteralElement)
35+
IDENTIFIER(asLocalActor)
3536
IDENTIFIER(atIndexedSubscript)
3637
IDENTIFIER_(bridgeToObjectiveC)
3738
IDENTIFIER(buildArray)

lib/SILGen/SILGen.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
8383
/// Set of delayed conformances that have already been forced.
8484
llvm::DenseSet<NormalProtocolConformance *> forcedConformances;
8585

86+
/// The conformance for any DistributedActor to the Actor protocol,
87+
/// used only by the `distributedActorAsAnyActor` builtin.
88+
RootProtocolConformance *distributedActorAsActorConformance = nullptr;
89+
8690
size_t anonymousSymbolCounter = 0;
8791

8892
llvm::Optional<SILDeclRef> StringToNSStringFn;
@@ -605,6 +609,20 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
605609
/// mentioned by the given type.
606610
void useConformancesFromObjectiveCType(CanType type);
607611

612+
/// Retrieve a protocol conformance to the `Actor` protocol for a
613+
/// distributed actor type that is described via a substitution map for
614+
/// the generic signature `<T: DistributedActor>`.
615+
///
616+
/// The protocol conformance is a special one that is currently
617+
/// only used by the `distributedActorAsAnyActor` builtin.
618+
ProtocolConformanceRef
619+
getDistributedActorAsActorConformance(SubstitutionMap subs);
620+
621+
/// Make a note of a member reference expression, which allows us
622+
/// to ensure that the conformance above is emitted wherever it
623+
/// needs to be.
624+
void noteMemberRefExpr(MemberRefExpr *e);
625+
608626
/// Map the substitutions for the original declaration to substitutions for
609627
/// the overridden declaration.
610628
static SubstitutionMap mapSubstitutionsForWitnessOverride(

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1889,13 +1889,10 @@ static ManagedValue emitBuiltinInjectEnumTag(SILGenFunction &SGF, SILLocation lo
18891889
return ManagedValue::forObjectRValueWithoutOwnership(bi);
18901890
}
18911891

1892-
static ExtensionDecl *distributedActorAsAnyActorExt = nullptr;
1893-
18941892
/// Find the extension on DistributedActor that defines __actorUnownedExecutor.
18951893
static ExtensionDecl *findDistributedActorAsActorExtension(
18961894
ProtocolDecl *distributedActorProto, ModuleDecl *module) {
18971895
ASTContext &ctx = distributedActorProto->getASTContext();
1898-
#if true
18991896
auto name = ctx.getIdentifier("__actorUnownedExecutor");
19001897
auto results = distributedActorProto->lookupDirect(
19011898
name, SourceLoc(),
@@ -1907,53 +1904,73 @@ static ExtensionDecl *findDistributedActorAsActorExtension(
19071904
}
19081905

19091906
return nullptr;
1910-
#else
1911-
if (!distributedActorAsAnyActorExt) {
1912-
auto ext = ExtensionDecl::create(
1913-
ctx, SourceLoc(), nullptr, { }, module, nullptr);
1914-
ctx.evaluator.cacheOutput(ExtendedTypeRequest{ext},
1915-
distributedActorProto->getDeclaredInterfaceType());
1916-
ctx.evaluator.cacheOutput(ExtendedNominalRequest{ext},
1917-
distributedActorProto);
1918-
1919-
distributedActorAsAnyActorExt = ext;
1907+
}
1908+
1909+
ProtocolConformanceRef
1910+
SILGenModule::getDistributedActorAsActorConformance(SubstitutionMap subs) {
1911+
ASTContext &ctx = M.getASTContext();
1912+
auto actorProto = ctx.getProtocol(KnownProtocolKind::Actor);
1913+
Type distributedActorType = subs.getReplacementTypes()[0];
1914+
1915+
if (!distributedActorAsActorConformance) {
1916+
auto distributedActorProto = ctx.getProtocol(KnownProtocolKind::DistributedActor);
1917+
if (!distributedActorProto)
1918+
return ProtocolConformanceRef();
1919+
1920+
auto ext = findDistributedActorAsActorExtension(
1921+
distributedActorProto, M.getSwiftModule());
1922+
if (!ext)
1923+
return ProtocolConformanceRef();
1924+
1925+
// Conformance of DistributedActor to Actor.
1926+
auto genericParam = subs.getGenericSignature().getGenericParams()[0];
1927+
distributedActorAsActorConformance = ctx.getNormalConformance(
1928+
Type(genericParam), actorProto, SourceLoc(), ext,
1929+
ProtocolConformanceState::Incomplete, /*isUnchecked=*/false,
1930+
/*isPreconcurrency=*/false);
1931+
}
1932+
1933+
return ProtocolConformanceRef(
1934+
actorProto,
1935+
ctx.getSpecializedConformance(distributedActorType,
1936+
distributedActorAsActorConformance,
1937+
subs));
1938+
}
1939+
1940+
void SILGenModule::noteMemberRefExpr(MemberRefExpr *e) {
1941+
VarDecl *var = cast<VarDecl>(e->getMember().getDecl());
1942+
1943+
// If the member is the special `asLocalActor` operation on
1944+
// distributed actors, make sure we have the conformance needed
1945+
// for a builtin.
1946+
ASTContext &ctx = var->getASTContext();
1947+
if (var->getName() == ctx.Id_asLocalActor &&
1948+
var->getDeclContext()->getSelfProtocolDecl() &&
1949+
var->getDeclContext()->getSelfProtocolDecl()
1950+
->isSpecificProtocol(KnownProtocolKind::DistributedActor)) {
1951+
auto conformance =
1952+
getDistributedActorAsActorConformance(
1953+
e->getMember().getSubstitutions());
1954+
useConformance(conformance);
19201955
}
19211956

1922-
return distributedActorAsAnyActorExt;
1923-
#endif
19241957
}
19251958

19261959
static ManagedValue emitBuiltinDistributedActorAsAnyActor(
19271960
SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs,
19281961
ArrayRef<ManagedValue> args, SGFContext C) {
19291962
auto &ctx = SGF.getASTContext();
19301963
auto distributedActor = args[0];
1931-
1932-
auto builtinDecl = cast<FuncDecl>(getBuiltinValueDecl(
1933-
ctx, ctx.getIdentifier("distributedActorAsAnyActor")));
1934-
auto genericSignature = builtinDecl->getGenericSignature();
1935-
auto genericParam = genericSignature.getGenericParams()[0];
1936-
1937-
auto distributedActorProto = ctx.getProtocol(KnownProtocolKind::DistributedActor);
1938-
auto ext = findDistributedActorAsActorExtension(
1939-
distributedActorProto, SGF.getModule().getSwiftModule());
1940-
1941-
// Conformance of DistributedActor to Actor.
1942-
auto actorProto = ctx.getProtocol(KnownProtocolKind::Actor);
1943-
CanType distributedActorType = distributedActor.getType().getASTType();
1944-
RootProtocolConformance *daAsActorConformance = ctx.getNormalConformance(
1945-
Type(genericParam), actorProto, SourceLoc(), ext,
1946-
ProtocolConformanceState::Incomplete, /*isUnchecked=*/false,
1947-
/*isPreconcurrency=*/false);
1948-
ProtocolConformanceRef conformance(
1949-
actorProto,
1950-
ctx.getSpecializedConformance(distributedActorType, daAsActorConformance,
1951-
subs));
1952-
ProtocolConformanceRef conformances[1] = { conformance };
1964+
ProtocolConformanceRef conformances[1] = {
1965+
SGF.SGM.getDistributedActorAsActorConformance(subs)
1966+
};
19531967

19541968
// Erase the distributed actor instance into an `any Actor` existential with
19551969
// the special conformance.
1970+
CanType distributedActorType =
1971+
subs.getReplacementTypes()[0]->getCanonicalType();
19561972
auto &distributedActorTL = SGF.getTypeLowering(distributedActorType);
1973+
auto actorProto = ctx.getProtocol(KnownProtocolKind::Actor);
19571974
auto &anyActorTL = SGF.getTypeLowering(actorProto->getDeclaredExistentialType());
19581975
return SGF.emitExistentialErasure(
19591976
loc, distributedActorType, distributedActorTL, anyActorTL,

lib/SILGen/SILGenLValue.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3055,6 +3055,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenBorrowedBaseVisitor
30553055
options, e->isSuper(), accessKind, strategy,
30563056
getSubstFormalRValueType(e),
30573057
false /*is on self parameter*/, actorIso);
3058+
3059+
SGF.SGM.noteMemberRefExpr(e);
3060+
30583061
return lv;
30593062
}
30603063

@@ -3864,6 +3867,9 @@ LValue SILGenLValue::visitMemberRefExpr(MemberRefExpr *e,
38643867
lv.addMemberVarComponent(SGF, e, var, e->getMember().getSubstitutions(),
38653868
options, e->isSuper(), accessKind, strategy,
38663869
substFormalRValueType, isOnSelfParameter, actorIso);
3870+
3871+
SGF.SGM.noteMemberRefExpr(e);
3872+
38673873
return lv;
38683874
}
38693875

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3465,7 +3465,7 @@ namespace {
34653465
// actor.
34663466
if (isolation.isDistributedActor()) {
34673467
actorExpr = UnresolvedDotExpr::createImplicit(
3468-
ctx, actorExpr, ctx.getIdentifier("asLocalActor"));
3468+
ctx, actorExpr, ctx.Id_asLocalActor);
34693469
}
34703470
break;
34713471
}

test/Distributed/Runtime/distributed_actor_to_actor.swift

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems %S/../Inputs/FakeDistributedActorSystems.swift
3-
// RUN: %target-build-swift -module-name main %import-libdispatch -j2 -parse-as-library -Xfrontend -disable-availability-checking -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift -g -o %t/a.out -enable-experimental-feature BuiltinModule
3+
// RUN: %target-build-swift -module-name main %import-libdispatch -j2 -parse-as-library -Xfrontend -disable-availability-checking -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift -g -o %t/a.out
44
// RUN: %target-codesign %t/a.out
55
// RUN: %target-run %t/a.out | %FileCheck %s --color
66

@@ -16,21 +16,12 @@
1616
// FIXME(distributed): Distributed actors currently have some issues on windows rdar://82593574
1717
// UNSUPPORTED: OS=windows-msvc
1818

19-
import Builtin // FIXME: Part of a hack to get the protocol conformance defined properly
2019
import Dispatch
2120
import Distributed
2221
import FakeDistributedActorSystems
2322

2423
typealias DefaultDistributedActorSystem = FakeRoundtripActorSystem
2524

26-
extension DistributedActor {
27-
func localDistributedAsActor() -> any Actor {
28-
// FIXME: Part of a hack that forces the protocol conformance for DistributedActor -> Actor to be defined
29-
// FIXME: Drop usage of this once we resolve the issue above
30-
Builtin.distributedActorAsAnyActor(self)
31-
}
32-
}
33-
3425
distributed actor Worker {
3526
var counter: Int = 0
3627

0 commit comments

Comments
 (0)