Skip to content

Commit 4f32111

Browse files
committed
[Sema/IRGen] Extend ad-hoc requirement handling to DistributedTargetInvocationEncoder.record{Argument, ReturnType}
1 parent 0db2231 commit 4f32111

File tree

3 files changed

+61
-34
lines changed

3 files changed

+61
-34
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -548,13 +548,14 @@ class EmitPolymorphicParameters : public PolymorphicConvention {
548548
// was a class-pointer source?
549549
bool isClassPointerSource(unsigned paramIndex);
550550

551-
// If we are building a protocol witness thunk for a
552-
// `DistributedActorSystem.remoteCall` requirement we
553-
// need to supply witness tables associated with `Res`
554-
// generic parameter which are not expressible on the
555-
// requirement because they come from `SerializationRequirement`
551+
// If we are building a protocol witness thunks for
552+
// `DistributedActorSystem.remoteCall` or
553+
// `DistributedTargetInvocationEncoder.record{Argument, ReturnType}`
554+
// requirements we need to supply witness tables associated with `Res`,
555+
// `Argument`, `R` generic parameters which are not expressible on the
556+
// protocol requirement because they come from `SerializationRequirement`
556557
// associated type.
557-
void injectAdHocDistributedRemoteCallRequirements();
558+
void injectAdHocDistributedRequirements();
558559
};
559560

560561
} // end anonymous namespace
@@ -730,35 +731,53 @@ bool EmitPolymorphicParameters::isClassPointerSource(unsigned paramIndex) {
730731
return false;
731732
}
732733

733-
void EmitPolymorphicParameters::injectAdHocDistributedRemoteCallRequirements() {
734+
void EmitPolymorphicParameters::injectAdHocDistributedRequirements() {
734735
// FIXME: We need a better way to recognize that function is
735736
// a thunk for witness of `remoteCall` requirement.
736737
if (!Fn.hasLocation())
737738
return;
738739

739740
auto loc = Fn.getLocation();
740741

742+
Type genericParam;
743+
741744
auto *funcDecl = dyn_cast_or_null<FuncDecl>(loc.getAsDeclContext());
742-
if (!(funcDecl && funcDecl->isDistributedActorSystemRemoteCall(
743-
/*isVoidReturn=*/false)))
745+
if (!(funcDecl && funcDecl->isGeneric()))
746+
return;
747+
748+
// DistributedActorSystem.remoteCall
749+
if (funcDecl->isDistributedActorSystemRemoteCall(
750+
/*isVoidReturn=*/false)) {
751+
genericParam = funcDecl->getResultInterfaceType();
752+
}
753+
754+
// DistributedTargetInvocationEncoder.record{Argument, ReturnType}
755+
if (funcDecl->isDistributedTargetInvocationEncoderRecordArgument() ||
756+
funcDecl->isDistributedTargetInvocationEncoderRecordReturnType()) {
757+
auto *argParam = funcDecl->getGenericParams()->getParams().front();
758+
genericParam = argParam->getDeclaredInterfaceType();
759+
}
760+
761+
if (!genericParam)
744762
return;
745763

746764
auto sig = funcDecl->getGenericSignature();
747-
auto resultInterfaceTy = funcDecl->getResultInterfaceType();
748-
auto resultArchetypeTy =
749-
getTypeInContext(resultInterfaceTy->getCanonicalType());
750-
llvm::Value *resultMetadata = IGF.emitTypeMetadataRef(resultArchetypeTy);
765+
auto requirements = sig->getLocalRequirements(genericParam);
766+
if (requirements.protos.empty())
767+
return;
751768

752-
auto resultRequirements = sig->getLocalRequirements(resultInterfaceTy);
753-
for (auto *proto : resultRequirements.protos) {
769+
auto archetypeTy = getTypeInContext(genericParam->getCanonicalType());
770+
llvm::Value *metadata = IGF.emitTypeMetadataRef(archetypeTy);
771+
772+
for (auto *proto : requirements.protos) {
754773
// Lookup the witness table for this protocol dynamically via
755774
// swift_conformsToProtocol(<<archetype>>, <<protocol>>)
756775
auto *witnessTable = IGF.Builder.CreateCall(
757776
IGM.getConformsToProtocolFunctionPointer(),
758-
{resultMetadata, IGM.getAddrOfProtocolDescriptor(proto)});
777+
{metadata, IGM.getAddrOfProtocolDescriptor(proto)});
759778

760779
IGF.setUnscopedLocalTypeData(
761-
resultArchetypeTy,
780+
archetypeTy,
762781
LocalTypeDataKind::forAbstractProtocolWitnessTable(proto),
763782
witnessTable);
764783
}
@@ -2617,8 +2636,9 @@ void EmitPolymorphicParameters::emit(EntryPointArgumentEmission &emission,
26172636
// Bind all the fulfillments we can from the formal parameters.
26182637
bindParameterSources(getParameter);
26192638

2620-
// Inject ad-hoc `remoteCall` requirements if any.
2621-
injectAdHocDistributedRemoteCallRequirements();
2639+
// Inject ad-hoc requirements related to `SerializationRequirement`
2640+
// associated type.
2641+
injectAdHocDistributedRequirements();
26222642
}
26232643

26242644
MetadataResponse

lib/Sema/CSSimplify.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8591,9 +8591,20 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
85918591
return recordConformance(synthesized);
85928592
};
85938593

8594-
if (witness->isDistributedActorSystemRemoteCall(/*isVoidReturn=*/false)) {
8595-
if (GP->isEqual(cast<FuncDecl>(witness)->getResultInterfaceType()))
8596-
return synthesizeConformance();
8594+
if (witness->isGeneric()) {
8595+
// `DistributedActorSystem.remoteCall`
8596+
if (witness->isDistributedActorSystemRemoteCall(/*isVoidReturn=*/false)) {
8597+
if (GP->isEqual(cast<FuncDecl>(witness)->getResultInterfaceType()))
8598+
return synthesizeConformance();
8599+
}
8600+
8601+
// `DistributedTargetInvocationEncoder.record{Argument, ResultType}`
8602+
if (witness->isDistributedTargetInvocationEncoderRecordArgument() ||
8603+
witness->isDistributedTargetInvocationEncoderRecordReturnType()) {
8604+
auto genericParams = witness->getGenericParams()->getParams();
8605+
if (GP->isEqual(genericParams.front()->getDeclaredInterfaceType()))
8606+
return synthesizeConformance();
8607+
}
85978608
}
85988609
}
85998610
}

stdlib/public/Distributed/DistributedActorSystem.swift

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -749,25 +749,21 @@ public protocol DistributedTargetInvocationEncoder {
749749
/// - Parameter type: a generic substitution type to be recorded for this invocation.
750750
mutating func recordGenericSubstitution<T>(_ type: T.Type) throws
751751

752-
// /// Ad-hoc requirement
753-
// ///
754-
// /// Record an argument of `Argument` type.
755-
// /// This will be invoked for every argument of the target, in declaration order.
756-
// mutating func recordArgument<Value: SerializationRequirement>(
757-
// _ argument: DistributedTargetArgument<Value>
758-
// ) throws
752+
/// Record an argument of `Argument` type.
753+
/// This will be invoked for every argument of the target, in declaration order.
754+
mutating func recordArgument<Value/*: SerializationRequirement*/>(
755+
_ argument: RemoteCallArgument<Value>
756+
) throws
759757

760758
/// Record the error type of the distributed method.
761759
/// This method will not be invoked if the target is not throwing.
762760
///
763761
/// - Parameter type: the type of error that was declared to be thrown by the invocation target. Currently this can only ever be `Error.self`.
764762
mutating func recordErrorType<E: Error>(_ type: E.Type) throws
765763

766-
// /// Ad-hoc requirement
767-
// ///
768-
// /// Record the return type of the distributed method.
769-
// /// This method will not be invoked if the target is returning `Void`.
770-
// mutating func recordReturnType<R: SerializationRequirement>(_ type: R.Type) throws
764+
/// Record the return type of the distributed method.
765+
/// This method will not be invoked if the target is returning `Void`.
766+
mutating func recordReturnType<R/*: SerializationRequirement*/>(_ type: R.Type) throws
771767

772768
/// Invoked to signal to the encoder that no further `record...` calls will be made on it.
773769
///

0 commit comments

Comments
 (0)