diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index ff2e73923df9d..95359aceee559 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -3564,10 +3564,10 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext { VarDecl *getDistributedActorIDProperty() const; /// Find the 'RemoteCallTarget.init(_:)' initializer function. - ConstructorDecl* getDistributedRemoteCallTargetInitFunction() const; + ConstructorDecl *getDistributedRemoteCallTargetInitFunction() const; /// Find the 'RemoteCallArgument(label:name:value:)' initializer function. - ConstructorDecl* getDistributedRemoteCallArgumentInitFunction() const; + ConstructorDecl *getDistributedRemoteCallArgumentInitFunction() const; /// Collect the set of protocols to which this type should implicitly /// conform, such as AnyObject (for classes). diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index fe02f3f491ae2..2267f88752ee2 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -680,6 +680,8 @@ ERROR(expected_sil_function_type, none, "sil function expected to have SIL function type", ()) ERROR(sil_dynamically_replaced_func_not_found,none, "dynamically replaced function not found %0", (Identifier)) +ERROR(sil_adhoc_requirement_witness_func_not_found,none, + "ad-hoc requirement witness function not found %0", (Identifier)) ERROR(sil_specialize_target_func_not_found,none, "_specialize target function not found %0", (Identifier)) ERROR(sil_availability_expected_version,none, diff --git a/include/swift/AST/DistributedDecl.h b/include/swift/AST/DistributedDecl.h index 68bf4b34e6baa..fe4ac4fdfb0d1 100644 --- a/include/swift/AST/DistributedDecl.h +++ b/include/swift/AST/DistributedDecl.h @@ -53,10 +53,21 @@ Type getDistributedActorIDType(NominalTypeDecl *actor); Type getDistributedSerializationRequirementType( NominalTypeDecl *nominal, ProtocolDecl *protocol); +/// Given a distributed thunk declaration, inside a 'distributed actor', +/// finds the ad-hoc witness for 'decodeNextArgument' on the associated +/// 'ActorSystem.InvocationDecoder' of the actor, or null. +AbstractFunctionDecl * +getAssociatedDistributedInvocationDecoderDecodeNextArgumentFunction( + ValueDecl *thunk); + /// Get the specific 'InvocationEncoder' type of a specific distributed actor /// system. Type getDistributedActorSystemInvocationEncoderType(NominalTypeDecl *system); +/// Get the specific 'InvocationDecoder' type of a specific distributed actor +/// system. +Type getDistributedActorSystemInvocationDecoderType(NominalTypeDecl *system); + /// Get the specific 'ResultHandler' type of a specific distributed actor /// system. Type getDistributedActorSystemResultHandlerType(NominalTypeDecl *system); diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index be958f54030fa..91bd00948a1f1 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -212,6 +212,17 @@ class SILFunction /// @_dynamicReplacement(for:) function. SILFunction *ReplacedFunction = nullptr; + /// This SILFunction REFerences an ad-hoc protocol requirement witness in + /// order to keep it alive, such that it main be obtained in IRGen. Without + /// this explicit reference, the witness would seem not-used, and not be + /// accessible for IRGen. + /// + /// Specifically, one such case is the DistributedTargetInvocationDecoder's + /// 'decodeNextArgument' which must be retained, as it is only used from IRGen + /// and such, appears as-if unused in SIL and would get optimized away. + // TODO: Consider making this a general "references adhoc functions" and make it an array? + SILFunction *RefAdHocRequirementFunction = nullptr; + Identifier ObjCReplacementFor; /// The head of a single-linked list of currently alive BasicBlockBitfield. @@ -298,7 +309,7 @@ class SILFunction /// Whether the implementation can be dynamically replaced. unsigned IsDynamicReplaceable : 1; - + /// If true, this indicates that a class method implementation will always be /// invoked with a `self` argument of the exact base class type. unsigned ExactSelfClass : 1; @@ -466,16 +477,6 @@ class SILFunction ReplacedFunction = f; ReplacedFunction->incrementRefCount(); } - - SILFunction *getDistributedRecordArgumentFunction() const { - return ReplacedFunction; - } - void setDistributedRecordArgumentFunction(SILFunction *f) { - if (f == nullptr) - return; - f->incrementRefCount(); - } - /// This function should only be called when SILFunctions are bulk deleted. void dropDynamicallyReplacedFunction() { if (!ReplacedFunction) @@ -484,6 +485,27 @@ class SILFunction ReplacedFunction = nullptr; } + SILFunction *getReferencedAdHocRequirementWitnessFunction() const { + return RefAdHocRequirementFunction; + } + // Marks that this `SILFunction` uses the passed in ad-hoc protocol + // requirement witness `f` and therefore must retain it explicitly, + // otherwise we might not be able to get a reference to it. + void setReferencedAdHocRequirementWitnessFunction(SILFunction *f) { + assert(RefAdHocRequirementFunction == nullptr && "already set"); + + if (f == nullptr) + return; + RefAdHocRequirementFunction = f; + RefAdHocRequirementFunction->incrementRefCount(); + } + void dropReferencedAdHocRequirementWitnessFunction() { + if (!RefAdHocRequirementFunction) + return; + RefAdHocRequirementFunction->decrementRefCount(); + RefAdHocRequirementFunction = nullptr; + } + bool hasObjCReplacement() const { return !ObjCReplacementFor.empty(); } @@ -758,7 +780,7 @@ class SILFunction IsDynamicReplaceable = value; assert(!Transparent || !IsDynamicReplaceable); } - + IsExactSelfClass_t isExactSelfClass() const { return IsExactSelfClass_t(ExactSelfClass); } diff --git a/lib/AST/DistributedDecl.cpp b/lib/AST/DistributedDecl.cpp index 1b3e172b7f060..854ad41e608a4 100644 --- a/lib/AST/DistributedDecl.cpp +++ b/lib/AST/DistributedDecl.cpp @@ -97,6 +97,10 @@ Type swift::getConcreteReplacementForProtocolActorSystemType(ValueDecl *member) } Type swift::getDistributedActorSystemType(NominalTypeDecl *actor) { + assert(!dyn_cast(actor) && + "Use getConcreteReplacementForProtocolActorSystemType instead to get" + "the concrete ActorSystem, if bound, for this DistributedActor " + "constrained ProtocolDecl!"); assert(actor->isDistributedActor()); auto &C = actor->getASTContext(); @@ -168,6 +172,21 @@ Type swift::getDistributedActorSystemInvocationEncoderType(NominalTypeDecl *syst return conformance.getTypeWitnessByName(selfType, ctx.Id_InvocationEncoder); } +Type swift::getDistributedActorSystemInvocationDecoderType(NominalTypeDecl *system) { + assert(!system->isDistributedActor()); + auto &ctx = system->getASTContext(); + + auto DAS = ctx.getDistributedActorSystemDecl(); + if (!DAS) + return Type(); + + // Dig out the serialization requirement type. + auto module = system->getParentModule(); + Type selfType = system->getSelfInterfaceType(); + auto conformance = module->lookupConformance(selfType, DAS); + return conformance.getTypeWitnessByName(selfType, ctx.Id_InvocationDecoder); +} + Type swift::getDistributedSerializationRequirementType( NominalTypeDecl *nominal, ProtocolDecl *protocol) { assert(nominal); @@ -184,6 +203,32 @@ Type swift::getDistributedSerializationRequirementType( return conformance.getTypeWitnessByName(selfType, ctx.Id_SerializationRequirement); } +AbstractFunctionDecl * +swift::getAssociatedDistributedInvocationDecoderDecodeNextArgumentFunction( + ValueDecl *thunk) { + assert(thunk); + auto &C = thunk->getASTContext(); + + auto *actor = thunk->getDeclContext()->getSelfNominalTypeDecl(); + if (!actor) + return nullptr; + if (!actor->isDistributedActor()) + return nullptr; + + auto systemTy = getConcreteReplacementForProtocolActorSystemType(thunk); + if (!systemTy) + return nullptr; + + auto decoderTy = + getDistributedActorSystemInvocationDecoderType( + systemTy->getAnyNominal()); + if (!decoderTy) + return nullptr; + + return C.getDecodeNextArgumentOnDistributedInvocationDecoder( + decoderTy->getAnyNominal()); +} + Type ASTContext::getAssociatedTypeOfDistributedSystemOfActor( NominalTypeDecl *actor, Identifier member) { auto &ctx = actor->getASTContext(); diff --git a/lib/IRGen/GenDistributed.cpp b/lib/IRGen/GenDistributed.cpp index b8af5db569682..481bd6b31218d 100644 --- a/lib/IRGen/GenDistributed.cpp +++ b/lib/IRGen/GenDistributed.cpp @@ -813,21 +813,13 @@ ArgumentDecoderInfo DistributedAccessor::findArgumentDecoder( decoder = instance.claimNext(); } - if (isa(decoderDecl) || isa(decoderDecl) || - decoderDecl->isFinal()) { - auto *decodeSIL = IGM.getSILModule().lookUpFunction(SILDeclRef(decodeFn)); - auto *fnPtr = IGM.getAddrOfSILFunction(decodeSIL, NotForDefinition, - /*isDynamicallyReplacible=*/false); + auto *decodeSIL = IGM.getSILModule().lookUpFunction(SILDeclRef(decodeFn)); + auto *fnPtr = IGM.getAddrOfSILFunction(decodeSIL, NotForDefinition, + /*isDynamicallyReplacible=*/false); - auto methodPtr = FunctionPointer::forDirect( - classifyFunctionPointerKind(decodeSIL), fnPtr, - /*secondaryValue=*/nullptr, signature); - - return {decoder, decoderTy, witnessTable, methodPtr, methodTy}; - } - - auto methodPtr = - emitVirtualMethodValue(IGF, decoderTy, SILDeclRef(decodeFn), methodTy); + auto methodPtr = FunctionPointer::forDirect( + classifyFunctionPointerKind(decodeSIL), fnPtr, + /*secondaryValue=*/nullptr, signature); return {decoder, decoderTy, witnessTable, methodPtr, methodTy}; } diff --git a/lib/SIL/IR/SILFunctionBuilder.cpp b/lib/SIL/IR/SILFunctionBuilder.cpp index 84dd94b8a1b07..b53ccec81e574 100644 --- a/lib/SIL/IR/SILFunctionBuilder.cpp +++ b/lib/SIL/IR/SILFunctionBuilder.cpp @@ -14,6 +14,7 @@ #include "swift/AST/AttrKind.h" #include "swift/AST/Availability.h" #include "swift/AST/DiagnosticsParse.h" +#include "swift/AST/DistributedDecl.h" #include "swift/AST/Decl.h" #include "swift/AST/ParameterList.h" #include "swift/AST/SemanticAttrs.h" @@ -200,29 +201,35 @@ void SILFunctionBuilder::addFunctionAttributes( // Only assign replacements when the thing being replaced is function-like and // explicitly declared. auto *origDecl = decl->getDynamicallyReplacedDecl(); - auto *replacedDecl = dyn_cast_or_null(origDecl); - if (!replacedDecl) - return; - - // For @objc method replacement we normally use categories to perform the - // replacement. Except for methods in generic class where we can't. Instead, - // we special case this and use the native swift replacement mechanism. - if (decl->isObjC() && !decl->isNativeMethodReplacement()) { - F->setObjCReplacement(replacedDecl); - return; - } - - if (!constant.canBeDynamicReplacement()) - return; + if (auto *replacedDecl = dyn_cast_or_null(origDecl)) { + // For @objc method replacement we normally use categories to perform the + // replacement. Except for methods in generic class where we can't. Instead, + // we special case this and use the native swift replacement mechanism. + if (decl->isObjC() && !decl->isNativeMethodReplacement()) { + F->setObjCReplacement(replacedDecl); + return; + } - SILDeclRef declRef(replacedDecl, constant.kind, false); - auto *replacedFunc = getOrCreateDeclaration(replacedDecl, declRef); + if (constant.canBeDynamicReplacement()) { + SILDeclRef declRef(replacedDecl, constant.kind, false); + auto *replacedFunc = getOrCreateDeclaration(replacedDecl, declRef); - assert(replacedFunc->getLoweredFunctionType() == - F->getLoweredFunctionType() || - replacedFunc->getLoweredFunctionType()->hasOpaqueArchetype()); + assert(replacedFunc->getLoweredFunctionType() == + F->getLoweredFunctionType() || + replacedFunc->getLoweredFunctionType()->hasOpaqueArchetype()); - F->setDynamicallyReplacedFunction(replacedFunc); + F->setDynamicallyReplacedFunction(replacedFunc); + } + } else if (constant.isDistributedThunk()) { + auto decodeFuncDecl = + getAssociatedDistributedInvocationDecoderDecodeNextArgumentFunction( + decl); + assert(decodeFuncDecl && "decodeNextArgument function not found!"); + + auto decodeRef = SILDeclRef(decodeFuncDecl); + auto *adHocFunc = getOrCreateDeclaration(decodeFuncDecl, decodeRef); + F->setReferencedAdHocRequirementWitnessFunction(adHocFunc); + } } SILFunction *SILFunctionBuilder::getOrCreateFunction( diff --git a/lib/SIL/IR/SILModule.cpp b/lib/SIL/IR/SILModule.cpp index 8bd442a03ddd8..7f4d95f57d099 100644 --- a/lib/SIL/IR/SILModule.cpp +++ b/lib/SIL/IR/SILModule.cpp @@ -138,6 +138,7 @@ SILModule::~SILModule() { for (SILFunction &F : *this) { F.dropAllReferences(); F.dropDynamicallyReplacedFunction(); + F.dropReferencedAdHocRequirementWitnessFunction(); F.clearSpecializeAttrs(); } @@ -467,6 +468,7 @@ void SILModule::eraseFunction(SILFunction *F) { // (References are not needed anymore.) F->clear(); F->dropDynamicallyReplacedFunction(); + F->dropReferencedAdHocRequirementWitnessFunction(); // Drop references for any _specialize(target:) functions. F->clearSpecializeAttrs(); } diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index bb7672342628d..06868d3fd0e9f 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -2983,6 +2983,12 @@ void SILFunction::print(SILPrintContext &PrintCtx) const { OS << "\"] "; } + if (auto *usedFunc = getReferencedAdHocRequirementWitnessFunction()) { + OS << "[ref_adhoc_requirement_witness \""; + OS << usedFunc->getName(); + OS << "\"] "; + } + if (hasObjCReplacement()) { OS << "[objc_replacement_for \""; OS << getObjCReplacement().str(); diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index 3f8a75c19534f..0396343828c55 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -973,6 +973,7 @@ static bool parseDeclSILOptional(bool *isTransparent, IsDistributed_t *isDistributed, IsExactSelfClass_t *isExactSelfClass, SILFunction **dynamicallyReplacedFunction, + SILFunction **usedAdHocRequirementWitness, Identifier *objCReplacementFor, SILFunction::Purpose *specialPurpose, Inline_t *inlineStrategy, @@ -1069,7 +1070,7 @@ static bool parseDeclSILOptional(bool *isTransparent, *MRK = EffectsKind::ReadWrite; else if (MRK && SP.P.Tok.getText() == "releasenone") *MRK = EffectsKind::ReleaseNone; - else if (dynamicallyReplacedFunction && SP.P.Tok.getText() == "dynamic_replacement_for") { + else if (dynamicallyReplacedFunction && SP.P.Tok.getText() == "dynamic_replacement_for") { SP.P.consumeToken(tok::identifier); if (SP.P.Tok.getKind() != tok::string_literal) { SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list); @@ -1087,6 +1088,26 @@ static bool parseDeclSILOptional(bool *isTransparent, *dynamicallyReplacedFunction = Func; SP.P.consumeToken(tok::string_literal); + SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list); + continue; + } else if (usedAdHocRequirementWitness && SP.P.Tok.getText() == "ref_adhoc_requirement_witness") { + SP.P.consumeToken(tok::identifier); + if (SP.P.Tok.getKind() != tok::string_literal) { + SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list); + return true; + } + // Drop the double quotes. + StringRef witnessFunc = SP.P.Tok.getText().drop_front().drop_back(); + SILFunction *Func = M.lookUpFunction(witnessFunc.str()); + if (!Func) { + Identifier Id = SP.P.Context.getIdentifier(witnessFunc); + SP.P.diagnose(SP.P.Tok, diag::sil_adhoc_requirement_witness_func_not_found, + Id); + return true; + } + *usedAdHocRequirementWitness = Func; + SP.P.consumeToken(tok::string_literal); + SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list); continue; } else if (objCReplacementFor && @@ -6335,12 +6356,13 @@ bool SILParserState::parseDeclSIL(Parser &P) { EffectsKind MRK = EffectsKind::Unspecified; llvm::SmallVector argEffectLocs; SILFunction *DynamicallyReplacedFunction = nullptr; + SILFunction *AdHocWitnessFunction = nullptr; Identifier objCReplacementFor; if (parseSILLinkage(FnLinkage, P) || parseDeclSILOptional( &isTransparent, &isSerialized, &isCanonical, &hasOwnershipSSA, &isThunk, &isDynamic, &isDistributed, &isExactSelfClass, - &DynamicallyReplacedFunction, &objCReplacementFor, &specialPurpose, + &DynamicallyReplacedFunction, &AdHocWitnessFunction, &objCReplacementFor, &specialPurpose, &inlineStrategy, &optimizationMode, &perfConstr, nullptr, &isWeakImported, &availability, &isWithoutActuallyEscapingThunk, &Semantics, @@ -6378,6 +6400,8 @@ bool SILParserState::parseDeclSIL(Parser &P) { FunctionState.F->setIsExactSelfClass(isExactSelfClass); FunctionState.F->setDynamicallyReplacedFunction( DynamicallyReplacedFunction); + FunctionState.F->setReferencedAdHocRequirementWitnessFunction( + AdHocWitnessFunction); if (!objCReplacementFor.empty()) FunctionState.F->setObjCReplacement(objCReplacementFor); FunctionState.F->setSpecialPurpose(specialPurpose); @@ -6571,7 +6595,7 @@ bool SILParserState::parseSILGlobal(Parser &P) { if (parseSILLinkage(GlobalLinkage, P) || parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, &isLet, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, State, M) || P.parseToken(tok::at_sign, diag::expected_sil_value_name) || @@ -6624,7 +6648,7 @@ bool SILParserState::parseSILProperty(Parser &P) { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - SP, M)) + nullptr, SP, M)) return true; ValueDecl *VD; @@ -6694,7 +6718,7 @@ bool SILParserState::parseSILVTable(Parser &P) { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, VTableState, M)) + nullptr, nullptr, VTableState, M)) return true; // Parse the class name. @@ -7211,7 +7235,7 @@ bool SILParserState::parseSILWitnessTable(Parser &P) { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, WitnessState, M)) + nullptr, nullptr, WitnessState, M)) return true; // Parse the protocol conformance. diff --git a/lib/SILOptimizer/Analysis/CallerAnalysis.cpp b/lib/SILOptimizer/Analysis/CallerAnalysis.cpp index 738d08ab79226..28ffc297ece5c 100644 --- a/lib/SILOptimizer/Analysis/CallerAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/CallerAnalysis.cpp @@ -33,8 +33,10 @@ CallerAnalysis::FunctionInfo::FunctionInfo(SILFunction *f) : callerStates(), // TODO: Make this more aggressive by considering // final/visibility/etc. - mayHaveIndirectCallers(f->getDynamicallyReplacedFunction() || - canBeCalledIndirectly(f->getRepresentation())), + mayHaveIndirectCallers( + f->getDynamicallyReplacedFunction() || + f->getReferencedAdHocRequirementWitnessFunction() || + canBeCalledIndirectly(f->getRepresentation())), mayHaveExternalCallers(f->isPossiblyUsedExternally() || f->isAvailableExternally()) {} diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp index 8857f2d8aac7c..695596b117d55 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp @@ -646,6 +646,7 @@ bool FunctionSignatureTransform::run(bool hasCaller) { hasCaller |= FSOOptimizeIfNotCalled; if (!hasCaller && (F->getDynamicallyReplacedFunction() || + F->getReferencedAdHocRequirementWitnessFunction() || canBeCalledIndirectly(F->getRepresentation()))) { LLVM_DEBUG(llvm::dbgs() << " function has no caller -> abort\n"); return false; diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp index 3004339b6002e..9d9c642f2b95a 100644 --- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp +++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp @@ -101,6 +101,9 @@ class DeadFunctionAndGlobalElimination { if (F->isDynamicallyReplaceable()) return true; + if (F->getReferencedAdHocRequirementWitnessFunction()) + return true; + // Don't remove pre-specialized functions. We need to preserver the // pre-specialization specifications from other modules. if (F->hasPrespecialization()) @@ -325,6 +328,9 @@ class DeadFunctionAndGlobalElimination { LLVM_DEBUG(llvm::dbgs() << " scan function " << F->getName() << '\n'); + if (auto *adHocWitness = F->getReferencedAdHocRequirementWitnessFunction()) + ensureAlive(adHocWitness); + // First scan all instructions of the function. for (SILBasicBlock &BB : *F) { for (SILInstruction &I : BB) { diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 47010bce0d5d4..833bec1f14c17 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -521,9 +521,10 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, DeclID clangNodeOwnerID; TypeID funcTyID; IdentifierID replacedFunctionID; + IdentifierID usedAdHocWitnessFunctionID; GenericSignatureID genericSigID; unsigned rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutactuallyEscapingThunk, specialPurpose, inlineStrategy, + isWithoutActuallyEscapingThunk, specialPurpose, inlineStrategy, optimizationMode, perfConstr, subclassScope, hasCReferences, effect, numAttrs, hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), @@ -531,11 +532,12 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, ArrayRef SemanticsIDs; SILFunctionLayout::readRecord( scratch, rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutactuallyEscapingThunk, specialPurpose, inlineStrategy, + isWithoutActuallyEscapingThunk, specialPurpose, inlineStrategy, optimizationMode, perfConstr, subclassScope, hasCReferences, effect, numAttrs, hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), - isDynamic, isExactSelfClass, isDistributed, funcTyID, replacedFunctionID, + isDynamic, isExactSelfClass, isDistributed, funcTyID, + replacedFunctionID, usedAdHocWitnessFunctionID, genericSigID, clangNodeOwnerID, SemanticsIDs); if (funcTyID == 0) { @@ -566,6 +568,13 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, replacedObjectiveCFunc = MF->getIdentifier(replacedFunctionID); } + SILFunction *usedAdHocWitnessFunction = nullptr; + if (usedAdHocWitnessFunctionID) { + auto usedAdHocWitnessFunctionStr = + MF->getIdentifier(usedAdHocWitnessFunctionID).str(); + usedAdHocWitnessFunction = getFuncForReference(usedAdHocWitnessFunctionStr); + } + auto linkageOpt = fromStableSILLinkage(rawLinkage); if (!linkageOpt) { LLVM_DEBUG(llvm::dbgs() << "invalid linkage code " << rawLinkage @@ -646,7 +655,7 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, fn->setTransparent(IsTransparent_t(isTransparent == 1)); fn->setSerialized(IsSerialized_t(isSerialized)); fn->setThunk(IsThunk_t(isThunk)); - fn->setWithoutActuallyEscapingThunk(bool(isWithoutactuallyEscapingThunk)); + fn->setWithoutActuallyEscapingThunk(bool(isWithoutActuallyEscapingThunk)); fn->setInlineStrategy(Inline_t(inlineStrategy)); fn->setSpecialPurpose(SILFunction::Purpose(specialPurpose)); fn->setEffectsKind(EffectsKind(effect)); @@ -670,6 +679,8 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, fn->setDynamicallyReplacedFunction(replacedFunction); if (!replacedObjectiveCFunc.empty()) fn->setObjCReplacement(replacedObjectiveCFunc); + if (usedAdHocWitnessFunction) + fn->setReferencedAdHocRequirementWitnessFunction(usedAdHocWitnessFunction); if (clangNodeOwner) fn->setClangNodeOwner(clangNodeOwner); for (auto ID : SemanticsIDs) { @@ -2954,9 +2965,10 @@ bool SILDeserializer::hasSILFunction(StringRef Name, DeclID clangOwnerID; TypeID funcTyID; IdentifierID replacedFunctionID; + IdentifierID usedAdHocWitnessFunctionID; GenericSignatureID genericSigID; unsigned rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutactuallyEscapingThunk, isGlobal, inlineStrategy, + isWithoutActuallyEscapingThunk, isGlobal, inlineStrategy, optimizationMode, perfConstr, subclassScope, hasCReferences, effect, numSpecAttrs, hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), @@ -2964,11 +2976,12 @@ bool SILDeserializer::hasSILFunction(StringRef Name, ArrayRef SemanticsIDs; SILFunctionLayout::readRecord( scratch, rawLinkage, isTransparent, isSerialized, isThunk, - isWithoutactuallyEscapingThunk, isGlobal, inlineStrategy, + isWithoutActuallyEscapingThunk, isGlobal, inlineStrategy, optimizationMode, perfConstr, subclassScope, hasCReferences, effect, numSpecAttrs, hasQualifiedOwnership, isWeakImported, LIST_VER_TUPLE_PIECES(available), - isDynamic, isExactSelfClass, isDistributed, funcTyID, replacedFunctionID, + isDynamic, isExactSelfClass, isDistributed, funcTyID, + replacedFunctionID, usedAdHocWitnessFunctionID, genericSigID, clangOwnerID, SemanticsIDs); auto linkage = fromStableSILLinkage(rawLinkage); if (!linkage) { diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 2775a4a0679ae..4a7dde336c627 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 686; // async let bit encoded in any_pattern +const uint16_t SWIFTMODULE_VERSION_MINOR = 687; // RefAdHocRequirementFunction info in SILFunctionLayout /// A standard hash seed used for all string hashes in a serialized module. /// diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h index c09024e80c982..2af2716d589d6 100644 --- a/lib/Serialization/SILFormat.h +++ b/lib/Serialization/SILFormat.h @@ -284,6 +284,7 @@ namespace sil_block { BCFixed<1>, // is distributed TypeIDField, // SILFunctionType DeclIDField, // SILFunction name or 0 (replaced function) + DeclIDField, // SILFunction name or 0 (used ad-hoc requirement witness function) GenericSignatureIDField, DeclIDField, // ClangNode owner BCArray // Semantics Attribute diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index e816999337443..07d26c8e88d85 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -462,12 +462,17 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) { if (auto *fun = F.getDynamicallyReplacedFunction()) { addReferencedSILFunction(fun, true); replacedFunctionID = S.addUniquedStringRef(fun->getName()); - } - else if (F.hasObjCReplacement()) { + } else if (F.hasObjCReplacement()) { replacedFunctionID = S.addUniquedStringRef(F.getObjCReplacement().str()); } + IdentifierID usedAdHocWitnessFunctionID = 0; + if (auto *fun = F.getReferencedAdHocRequirementWitnessFunction()) { + addReferencedSILFunction(fun, true); + usedAdHocWitnessFunctionID = S.addUniquedStringRef(fun->getName()); + } + unsigned numAttrs = NoBody ? 0 : F.getSpecializeAttrs().size(); auto resilience = F.getModule().getSwiftModule()->getResilienceStrategy(); @@ -495,9 +500,11 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) { (unsigned)F.hasCReferences(), (unsigned)F.getEffectsKind(), (unsigned)numAttrs, (unsigned)F.hasOwnership(), F.isAlwaysWeakImported(), LIST_VER_TUPLE_PIECES(available), - (unsigned)F.isDynamicallyReplaceable(), (unsigned)F.isExactSelfClass(), - (unsigned)F.isDistributed(), FnID, replacedFunctionID, genericSigID, - clangNodeOwnerID, SemanticsIDs); + (unsigned)F.isDynamicallyReplaceable(), + (unsigned)F.isExactSelfClass(), + (unsigned)F.isDistributed(), + FnID, replacedFunctionID, usedAdHocWitnessFunctionID, + genericSigID, clangNodeOwnerID, SemanticsIDs); F.visitArgEffects( [&](int effectIdx, bool isDerived, SILFunction::ArgEffectKind) { diff --git a/stdlib/public/Distributed/DistributedActorSystem.swift b/stdlib/public/Distributed/DistributedActorSystem.swift index 65fcf9c302a77..422a2f76144d3 100644 --- a/stdlib/public/Distributed/DistributedActorSystem.swift +++ b/stdlib/public/Distributed/DistributedActorSystem.swift @@ -27,10 +27,11 @@ public protocol DistributedActorSystem: Sendable { associatedtype ResultHandler: DistributedTargetInvocationResultHandler /// The serialization requirement that will be applied to all distributed targets used with this system. + // TODO: constrain SerializationRequirement in typesystem to only be ok with protocol or class here associatedtype SerializationRequirement where SerializationRequirement == InvocationEncoder.SerializationRequirement, - SerializationRequirement == InvocationDecoder.SerializationRequirement, - SerializationRequirement == ResultHandler.SerializationRequirement + SerializationRequirement == InvocationDecoder.SerializationRequirement, + SerializationRequirement == ResultHandler.SerializationRequirement // ==== --------------------------------------------------------------------- // - MARK: Resolving actors by identity diff --git a/stdlib/public/Distributed/LocalTestingDistributedActorSystem.swift b/stdlib/public/Distributed/LocalTestingDistributedActorSystem.swift index 094a9e06f1807..90c108c1f38f5 100644 --- a/stdlib/public/Distributed/LocalTestingDistributedActorSystem.swift +++ b/stdlib/public/Distributed/LocalTestingDistributedActorSystem.swift @@ -170,7 +170,7 @@ public struct LocalTestingInvocationEncoder: DistributedTargetInvocationEncoder } @available(SwiftStdlib 5.7, *) -public class LocalTestingInvocationDecoder : DistributedTargetInvocationDecoder { +public final class LocalTestingInvocationDecoder: DistributedTargetInvocationDecoder { public typealias SerializationRequirement = Codable public func decodeGenericSubstitutions() throws -> [Any.Type] { diff --git a/test/Distributed/Inputs/FakeDistributedActorSystems.swift b/test/Distributed/Inputs/FakeDistributedActorSystems.swift index f864ac3929f84..8ee09b9a1bae9 100644 --- a/test/Distributed/Inputs/FakeDistributedActorSystems.swift +++ b/test/Distributed/Inputs/FakeDistributedActorSystems.swift @@ -36,6 +36,7 @@ public struct ActorAddress: Hashable, Sendable, Codable { // ==== Noop Transport --------------------------------------------------------- +@available(SwiftStdlib 5.7, *) public struct FakeActorSystem: DistributedActorSystem, CustomStringConvertible { public typealias ActorID = ActorAddress public typealias InvocationDecoder = FakeInvocationDecoder @@ -111,6 +112,7 @@ public struct FakeActorSystem: DistributedActorSystem, CustomStringConvertible { // ==== Fake Roundtrip Transport ----------------------------------------------- // TODO(distributed): not thread safe... +@available(SwiftStdlib 5.7, *) public final class FakeRoundtripActorSystem: DistributedActorSystem, @unchecked Sendable { public typealias ActorID = ActorAddress public typealias InvocationEncoder = FakeInvocationEncoder @@ -256,6 +258,7 @@ public final class FakeRoundtripActorSystem: DistributedActorSystem, @unchecked } +@available(SwiftStdlib 5.7, *) public struct FakeInvocationEncoder : DistributedTargetInvocationEncoder { public typealias SerializationRequirement = Codable @@ -300,7 +303,12 @@ public struct FakeInvocationEncoder : DistributedTargetInvocationEncoder { } // === decoding -------------------------------------------------------------- -public class FakeInvocationDecoder : DistributedTargetInvocationDecoder { + +// !!! WARNING !!! +// This is a 'final class' on purpose, to see that we retain the ad-hoc witness +// for 'decodeNextArgument'; Do not change it to just a class! +@available(SwiftStdlib 5.7, *) +public final class FakeInvocationDecoder: DistributedTargetInvocationDecoder { public typealias SerializationRequirement = Codable var genericSubs: [Any.Type] = [] @@ -353,7 +361,7 @@ public class FakeInvocationDecoder : DistributedTargetInvocationDecoder { } } -@available(SwiftStdlib 5.5, *) +@available(SwiftStdlib 5.7, *) public struct FakeRoundtripResultHandler: DistributedTargetInvocationResultHandler { public typealias SerializationRequirement = Codable @@ -382,9 +390,11 @@ public struct FakeRoundtripResultHandler: DistributedTargetInvocationResultHandl // ==== Helpers ---------------------------------------------------------------- +@available(SwiftStdlib 5.7, *) @_silgen_name("swift_distributed_actor_is_remote") func __isRemoteActor(_ actor: AnyObject) -> Bool +@available(SwiftStdlib 5.7, *) func __isLocalActor(_ actor: AnyObject) -> Bool { return !__isRemoteActor(actor) } diff --git a/test/Distributed/Runtime/distributed_actor_cross_module_final_class_adhoc_requirement_not_optimized_away.swift b/test/Distributed/Runtime/distributed_actor_cross_module_final_class_adhoc_requirement_not_optimized_away.swift new file mode 100644 index 0000000000000..03767a199b30d --- /dev/null +++ b/test/Distributed/Runtime/distributed_actor_cross_module_final_class_adhoc_requirement_not_optimized_away.swift @@ -0,0 +1,51 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -parse-as-library -emit-library -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems %S/../Inputs/FakeDistributedActorSystems.swift -o %t/%target-library-name(FakeDistributedActorSystems) +// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -parse-as-library -lFakeDistributedActorSystems -module-name main -I %t -L %t %s -o %t/a.out +// RUN: %target-run %t/a.out | %FileCheck %s --color + +// REQUIRES: OS=macosx && (CPU=x86_64 || CPU=arm64) +// REQUIRES: executable_test +// REQUIRES: concurrency +// REQUIRES: distributed + +// rdar://76038845 +// UNSUPPORTED: use_os_stdlib +// UNSUPPORTED: back_deployment_runtime + +// FIXME(distributed): Distributed actors currently have some issues on windows, isRemote always returns false. rdar://82593574 +// UNSUPPORTED: windows + +import Distributed +import FakeDistributedActorSystems + +@available(SwiftStdlib 5.7, *) +typealias DefaultDistributedActorSystem = FakeRoundtripActorSystem + +@available(SwiftStdlib 5.7, *) +distributed actor Greeter { + distributed func hello() -> String { + return "Hello, World!" + } +} + +@available(SwiftStdlib 5.7, *) +func test() async throws { + let system = DefaultDistributedActorSystem() + + let local = Greeter(actorSystem: system) + let ref = try Greeter.resolve(id: local.id, using: system) + + let response = try await ref.hello() + // CHECK: >> remoteCall: on:main.Greeter, target:main.Greeter.hello(), invocation:FakeInvocationEncoder(genericSubs: [], arguments: [], returnType: Optional(Swift.String), errorType: nil), throwing:Swift.Never, returning:Swift.String + + print("response: \(response)") + // CHECK: response: Hello, World! + +} + +@available(SwiftStdlib 5.7, *) +@main struct Main { + static func main() async { + try! await test() + } +} diff --git a/test/Distributed/distributed_actor_accessor_thunks_32bit.swift b/test/Distributed/distributed_actor_accessor_thunks_32bit.swift index b5c353f68670c..257a92d442d19 100644 --- a/test/Distributed/distributed_actor_accessor_thunks_32bit.swift +++ b/test/Distributed/distributed_actor_accessor_thunks_32bit.swift @@ -100,16 +100,9 @@ public distributed actor MyOtherActor { // CHECK: [[DECODER_PTR:%*]] = bitcast %swift.opaque* %1 to %T27FakeDistributedActorSystems0A17InvocationDecoderC** // CHECK-NEXT: [[DECODER:%.*]] = load %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %T27FakeDistributedActorSystems0A17InvocationDecoderC** [[DECODER_PTR]] -// CHECK-NEXT: [[DECODER_METADATA:%.*]] = bitcast %swift.type* [[DECODER_TYPE]] to void (%swift.opaque*, %swift.type*, i8**, i8**, %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %swift.error**)** -// CHECK-NEXT: [[DECODE_NEXT_ARG_REF:%.*]] = getelementptr inbounds void (%swift.opaque*, %swift.type*, i8**, i8**, %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %swift.error**)*, void (%swift.opaque*, %swift.type*, i8**, i8**, %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %swift.error**)** [[DECODER_METADATA]], i32 35 -// CHECK-NEXT: [[DECODE_NEXT_ARG:%.*]] = load void (%swift.opaque*, %swift.type*, i8**, i8**, %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %swift.error**)*, void (%swift.opaque*, %swift.type*, i8**, i8**, %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %swift.error**)** [[DECODE_NEXT_ARG_REF]] +// CHECK-NEXT: [[DECODER_METADATA:%.*]] = bitcast i8* %2 to %swift.type* +// CHECK-NEXT: [[DECODE_NEXT_ARG_REF:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[DECODER_METADATA]], i32 - -// CHECK: [[ARG_TYPES:%.*]] = bitcast i8* %2 to %swift.type** - -// CHECK: [[ARG_0_TYPE_LOC:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[ARG_TYPES]], i32 0 -// CHECK-NEXT: %arg_type = load %swift.type*, %swift.type** [[ARG_0_TYPE_LOC]] -// CHECK: %size = load i32, i32* {{.*}} // CHECK: [[ARG_0_SIZE_ADJ:%.*]] = add i32 %size, 15 // CHECK-NEXT: [[ARG_0_SIZE:%.*]] = and i32 [[ARG_0_SIZE_ADJ]], -16 // CHECK-NEXT: [[ARG_0_VALUE_BUF:%.*]] = call swiftcc i8* @swift_task_alloc(i32 [[ARG_0_SIZE]]) @@ -126,7 +119,7 @@ public distributed actor MyOtherActor { // CHECK: missing-witness1: // CHECK-NEXT: call void @llvm.trap() // CHECK-NEXT: unreachable -// CHECK: call swiftcc void [[DECODE_NEXT_ARG]](%swift.opaque* noalias nocapture sret(%swift.opaque) [[ARG_0_RES_SLOT]], %swift.type* %arg_type, i8** [[ENCODABLE_WITNESS]], i8** [[DECODABLE_WITNESS]], %T27FakeDistributedActorSystems0A17InvocationDecoderC* swiftself [[DECODER]], %swift.error** noalias nocapture dereferenceable(4) %swifterror) +// CHECK: call swiftcc void @"$s27FakeDistributedActorSystems0A17InvocationDecoderC18decodeNextArgumentxyKSeRzSERzlF"(%swift.opaque* noalias nocapture sret(%swift.opaque) [[ARG_0_RES_SLOT]], %swift.type* %arg_type, i8** [[ENCODABLE_WITNESS]], i8** [[DECODABLE_WITNESS]], %T27FakeDistributedActorSystems0A17InvocationDecoderC* swiftself [[DECODER]], %swift.error** noalias nocapture dereferenceable(4) %swifterror) // CHECK: store %swift.error* null, %swift.error** %swifterror // CHECK-NEXT: [[ARG_0_VAL_ADDR:%.*]] = bitcast i8* [[ARG_0_VALUE_BUF]] to %TSi* diff --git a/test/Distributed/distributed_actor_accessor_thunks_64bit.swift b/test/Distributed/distributed_actor_accessor_thunks_64bit.swift index 0902003307832..39a07847651c9 100644 --- a/test/Distributed/distributed_actor_accessor_thunks_64bit.swift +++ b/test/Distributed/distributed_actor_accessor_thunks_64bit.swift @@ -100,15 +100,9 @@ public distributed actor MyOtherActor { // CHECK: [[DECODER_PTR:%*]] = bitcast %swift.opaque* %1 to %T27FakeDistributedActorSystems0A17InvocationDecoderC** // CHECK-NEXT: [[DECODER:%.*]] = load %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %T27FakeDistributedActorSystems0A17InvocationDecoderC** [[DECODER_PTR]] -// CHECK-NEXT: [[DECODER_METADATA:%.*]] = bitcast %swift.type* [[DECODER_TYPE]] to void (%swift.opaque*, %swift.type*, i8**, i8**, %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %swift.error**)** -// CHECK-NEXT: [[DECODE_NEXT_ARG_REF:%.*]] = getelementptr inbounds void (%swift.opaque*, %swift.type*, i8**, i8**, %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %swift.error**)*, void (%swift.opaque*, %swift.type*, i8**, i8**, %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %swift.error**)** [[DECODER_METADATA]], i64 {{29|32}} -// CHECK-NEXT: [[DECODE_NEXT_ARG:%.*]] = load void (%swift.opaque*, %swift.type*, i8**, i8**, %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %swift.error**)*, void (%swift.opaque*, %swift.type*, i8**, i8**, %T27FakeDistributedActorSystems0A17InvocationDecoderC*, %swift.error**)** [[DECODE_NEXT_ARG_REF]] +// CHECK-NEXT: [[DECODER_METADATA:%.*]] = bitcast i8* %2 to %swift.type* +// CHECK-NEXT: [[DECODE_NEXT_ARG_REF:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[DECODER_METADATA]], i64 -// CHECK-NEXT: [[ARG_TYPES:%.*]] = bitcast i8* %2 to %swift.type** - -// CHECK: [[ARG_0_TYPE_LOC:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[ARG_TYPES]], i64 0 -// CHECK-NEXT: %arg_type = load %swift.type*, %swift.type** [[ARG_0_TYPE_LOC]] -// CHECK: %size = load i64, i64* {{.*}} // CHECK: [[ARG_0_SIZE_ADJ:%.*]] = add i64 %size, 15 // CHECK-NEXT: [[ARG_0_SIZE:%.*]] = and i64 [[ARG_0_SIZE_ADJ]], -16 // CHECK-NEXT: [[ARG_0_VALUE_BUF:%.*]] = call swiftcc i8* @swift_task_alloc(i64 [[ARG_0_SIZE]]) @@ -125,7 +119,7 @@ public distributed actor MyOtherActor { // CHECK: missing-witness1: // CHECK-NEXT: call void @llvm.trap() // CHECK-NEXT: unreachable -// CHECK: call swiftcc void [[DECODE_NEXT_ARG]](%swift.opaque* noalias nocapture sret(%swift.opaque) [[ARG_0_RES_SLOT]], %swift.type* %arg_type, i8** [[ENCODABLE_WITNESS]], i8** [[DECODABLE_WITNESS]], %T27FakeDistributedActorSystems0A17InvocationDecoderC* swiftself [[DECODER]], %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) +// CHECK: call swiftcc void @"$s27FakeDistributedActorSystems0A17InvocationDecoderC18decodeNextArgumentxyKSeRzSERzlF"(%swift.opaque* noalias nocapture sret(%swift.opaque) [[ARG_0_RES_SLOT]], %swift.type* %arg_type, i8** [[ENCODABLE_WITNESS]], i8** [[DECODABLE_WITNESS]], %T27FakeDistributedActorSystems0A17InvocationDecoderC* swiftself [[DECODER]], %swift.error** noalias nocapture swifterror dereferenceable(8) %swifterror) // CHECK: store %swift.error* null, %swift.error** %swifterror // CHECK-NEXT: [[ARG_0_VAL_ADDR:%.*]] = bitcast i8* [[ARG_0_VALUE_BUF]] to %TSi* diff --git a/test/SILGen/distributed_thunk.swift b/test/SILGen/distributed_thunk.swift index 74185c37817e9..e0b0dd8f26e5f 100644 --- a/test/SILGen/distributed_thunk.swift +++ b/test/SILGen/distributed_thunk.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-emit-silgen %s -enable-experimental-distributed -disable-availability-checking | %FileCheck %s --dump-input=fail +// RUN: %target-swift-emit-silgen %s -enable-experimental-distributed -disable-availability-checking | %FileCheck %s // REQUIRES: concurrency // REQUIRES: distributed @@ -9,7 +9,7 @@ distributed actor DA { } extension DA { - // CHECK-LABEL: sil hidden [thunk] [distributed] [ossa] @$s17distributed_thunk2DAC1fyyYaKFTE : $@convention(method) @async (@guaranteed DA) -> @error Error + // CHECK-LABEL: sil hidden [thunk] [distributed] [ref_adhoc_requirement_witness "$s11Distributed29LocalTestingInvocationDecoderC18decodeNextArgumentxyKSeRzSERzlF"] [ossa] @$s17distributed_thunk2DAC1fyyYaKFTE : $@convention(method) @async (@guaranteed DA) -> @error Error { // CHECK: function_ref @swift_distributed_actor_is_remote // Call the actor function