@@ -3755,6 +3755,96 @@ static SILFunction *getOrCreateKeyPathAppliedMethod(
37553755 return thunk;
37563756}
37573757
3758+ static SILFunction *getOrCreateUnappliedKeypathMethod (
3759+ SILGenModule &SGM, AbstractFunctionDecl *method, SubstitutionMap subs,
3760+ GenericEnvironment *genericEnv, ResilienceExpansion expansion,
3761+ ArrayRef<IndexTypePair> args, CanType baseType, CanType methodType) {
3762+ lookupMethodViaProtocol (method, subs);
3763+
3764+ auto genericSig =
3765+ genericEnv ? genericEnv->getGenericSignature ().getCanonicalSignature ()
3766+ : nullptr ;
3767+ if (genericSig && genericSig->areAllParamsConcrete ()) {
3768+ genericSig = nullptr ;
3769+ genericEnv = nullptr ;
3770+ }
3771+
3772+ // Build the thunk signature for an unapplied method.
3773+ auto signature = [&]() {
3774+ CanType loweredBaseTy = SGM.Types .getLoweredRValueType (
3775+ TypeExpansionContext::minimal (), AbstractionPattern::getOpaque (),
3776+ baseType);
3777+ CanType loweredMethodTy = SGM.Types .getLoweredRValueType (
3778+ TypeExpansionContext::minimal (), AbstractionPattern::getOpaque (),
3779+ methodType);
3780+
3781+ return SILFunctionType::get (
3782+ genericSig,
3783+ SILFunctionType::ExtInfo ().withRepresentation (
3784+ SILFunctionType::Representation::KeyPathAccessorGetter),
3785+ SILCoroutineKind::None, ParameterConvention::Direct_Unowned,
3786+ {SILParameterInfo (loweredBaseTy,
3787+ ParameterConvention::Indirect_In_Guaranteed)},
3788+ {}, SILResultInfo (loweredMethodTy, ResultConvention::Indirect),
3789+ std::nullopt , SubstitutionMap (), SubstitutionMap (),
3790+ SGM.getASTContext ());
3791+ }();
3792+
3793+ // Mangle the name of the thunk to see if we already created it.
3794+ auto name = Mangle::ASTMangler (SGM.getASTContext (), method)
3795+ .mangleKeyPathUnappliedMethodThunkHelper (
3796+ method, genericSig, baseType, subs, expansion);
3797+ auto loc = RegularLocation::getAutoGeneratedLocation ();
3798+ auto thunk =
3799+ getOrCreateKeypathThunk (SGM, name, signature, genericEnv, expansion, loc);
3800+ if (!thunk->empty ())
3801+ return thunk;
3802+
3803+ // Emit the thunk, which accesses the underlying property normally with
3804+ // reabstraction where necessary.
3805+ if (genericEnv) {
3806+ baseType = genericEnv->mapTypeIntoContext (baseType)->getCanonicalType ();
3807+ methodType = genericEnv->mapTypeIntoContext (methodType)->getCanonicalType ();
3808+ thunk->setGenericEnvironment (genericEnv);
3809+ }
3810+ SILGenFunction subSGF (SGM, *thunk, SGM.SwiftModule );
3811+ signature = subSGF.F .getLoweredFunctionTypeInContext (
3812+ subSGF.F .getTypeExpansionContext ());
3813+ auto resultArgTy =
3814+ subSGF.silConv .getSILType (signature->getSingleResult (), signature,
3815+ subSGF.F .getTypeExpansionContext ());
3816+ auto baseArgTy =
3817+ subSGF.silConv .getSILType (signature->getParameters ()[0 ], signature,
3818+ subSGF.F .getTypeExpansionContext ());
3819+ SILFunctionArgument *resultArg = nullptr ;
3820+ SILFunctionArgument *baseArg = nullptr ;
3821+ SILValue argPtr;
3822+ emitKeyPathThunk (SGM, subSGF, genericEnv, signature, thunk, args, resultArg,
3823+ resultArgTy, baseArg, baseArgTy, argPtr,
3824+ !args.empty () ? signature->getParameters ()[1 ]
3825+ : SILParameterInfo ());
3826+
3827+ ArgumentScope scope (subSGF, loc);
3828+ auto baseSubstValue =
3829+ emitKeyPathRValueBase (subSGF, method, loc, baseArg, baseType, subs);
3830+ auto preparedArgs =
3831+ loadIndexValuesForKeyPathComponent (subSGF, loc, method, args, argPtr);
3832+
3833+ ManagedValue resultSubst;
3834+ {
3835+ RValue resultRValue = subSGF.emitUnappliedKeyPathMethod (
3836+ loc, baseSubstValue, baseType, method, methodType,
3837+ std::move (preparedArgs), subs, SGFContext ());
3838+
3839+ resultSubst = std::move (resultRValue).getAsSingleValue (subSGF, loc);
3840+ }
3841+
3842+ emitReturn (subSGF, methodType, resultSubst, resultArgTy, resultArg, scope,
3843+ loc);
3844+ SGM.emitLazyConformancesForFunction (thunk);
3845+ return thunk;
3846+ }
3847+
37583848static void
37593849getOrCreateKeyPathEqualsAndHash (SILGenModule &SGM,
37603850 SILLocation loc,
@@ -4211,7 +4301,7 @@ KeyPathPatternComponent SILGenModule::emitKeyPathComponentForDecl(
42114301 ResilienceExpansion expansion, unsigned &baseOperand,
42124302 bool &needsGenericContext, SubstitutionMap subs, ValueDecl *decl,
42134303 ArrayRef<ProtocolConformanceRef> indexHashables, CanType baseTy,
4214- DeclContext *useDC, bool forPropertyDescriptor) {
4304+ DeclContext *useDC, bool forPropertyDescriptor, bool isApplied ) {
42154305 if (auto *storage = dyn_cast<AbstractFunctionDecl>(decl)) {
42164306 // ABI-compatible overrides do not have property descriptors, so we need
42174307 // to reference the overridden declaration instead.
@@ -4225,34 +4315,55 @@ KeyPathPatternComponent SILGenModule::emitKeyPathComponentForDecl(
42254315 SubstitutionMap externalSubs;
42264316 CanType componentTy;
42274317 auto methodTy = decl->getInterfaceType ()->castTo <AnyFunctionType>();
4228- // Otherwise, component type is method type without Self.
4229- auto methodResTy = decl->getInterfaceType ()->castTo <AnyFunctionType>();
4230- if (auto genMethodTy = methodResTy->getAs <GenericFunctionType>())
4231- methodResTy = genMethodTy->substGenericArgs (subs);
4232- auto methodInterfaceTy = cast<AnyFunctionType>(
4233- methodResTy->mapTypeOutOfContext ()->getCanonicalType ());
4234- componentTy = methodInterfaceTy.getResult ();
4318+ if (isApplied) {
4319+ // If method is applied, set component type to method result type.
4320+ auto methodResultTy =
4321+ methodTy->getResult ()->castTo <AnyFunctionType>()->getResult ();
4322+ if (auto genMethodTy = methodResultTy->getAs <GenericFunctionType>())
4323+ methodResultTy = genMethodTy->substGenericArgs (subs);
4324+ componentTy = methodResultTy->mapTypeOutOfContext ()->getCanonicalType ();
4325+ } else {
4326+ // Otherwise, component type is method type without Self.
4327+ if (auto genMethodTy = methodTy->getAs <GenericFunctionType>())
4328+ methodTy = genMethodTy->substGenericArgs (subs);
4329+ auto methodInterfaceTy = cast<AnyFunctionType>(
4330+ methodTy->mapTypeOutOfContext ()->getCanonicalType ());
4331+ componentTy = methodInterfaceTy.getResult ();
4332+ }
42354333
4236- SmallVector<IndexTypePair, 4 > argTypes;
4237- lowerKeyPathMemberIndexTypes (*this , argTypes, decl, subs,
4238- needsGenericContext);
4334+ if (decl->getAttrs ().hasAttribute <OptionalAttr>()) {
4335+ // The component type for an @objc optional requirement needs to be
4336+ // wrapped in an optional
4337+ componentTy = OptionalType::get (componentTy)->getCanonicalType ();
4338+ }
42394339
4340+ SmallVector<IndexTypePair, 4 > argTypes;
42404341 SmallVector<KeyPathPatternComponent::Index, 4 > argPatterns;
42414342 SILFunction *argEquals = nullptr , *argHash = nullptr ;
4242- lowerKeyPathMemberIndexPatterns (argPatterns, argTypes, indexHashables,
4243- baseOperand);
4244-
4245- getOrCreateKeyPathEqualsAndHash (*this , loc,
4246- needsGenericContext ? genericEnv : nullptr ,
4247- expansion, argPatterns, argEquals, argHash);
4343+ if (isApplied) {
4344+ lowerKeyPathMemberIndexTypes (*this , argTypes, decl, subs,
4345+ needsGenericContext);
4346+ lowerKeyPathMemberIndexPatterns (argPatterns, argTypes, indexHashables,
4347+ baseOperand);
4348+ getOrCreateKeyPathEqualsAndHash (
4349+ *this , loc, needsGenericContext ? genericEnv : nullptr , expansion,
4350+ argPatterns, argEquals, argHash);
4351+ }
42484352
42494353 auto representative = SILDeclRef (storage, SILDeclRef::Kind::Func,
42504354 /* isForeign*/ storage->isImportAsMember ());
42514355 auto id = getFunction (representative, NotForDefinition);
42524356
4253- auto func = getOrCreateKeyPathAppliedMethod (
4254- *this , storage, subs, needsGenericContext ? genericEnv : nullptr ,
4255- expansion, argTypes, baseTy, componentTy);
4357+ SILFunction *func = nullptr ;
4358+ if (isApplied) {
4359+ func = getOrCreateKeyPathAppliedMethod (
4360+ *this , storage, subs, needsGenericContext ? genericEnv : nullptr ,
4361+ expansion, argTypes, baseTy, componentTy);
4362+ } else {
4363+ func = getOrCreateUnappliedKeypathMethod (
4364+ *this , storage, subs, needsGenericContext ? genericEnv : nullptr ,
4365+ expansion, argTypes, baseTy, componentTy);
4366+ }
42564367
42574368 auto argPatternsCopy = getASTContext ().AllocateCopy (argPatterns);
42584369 return KeyPathPatternComponent::forMethod (id, func, argPatternsCopy,
@@ -4517,11 +4628,13 @@ RValue RValueEmitter::visitKeyPathExpr(KeyPathExpr *E, SGFContext C) {
45174628 auto decl = component.getDeclRef ().getDecl ();
45184629
45194630 // If method is applied, get args from subsequent Apply component.
4631+ bool isApplied = false ;
45204632 auto argComponent = components[i];
4521- if (auto func = dyn_cast<FuncDecl >(decl);
4633+ if (auto func = dyn_cast<AbstractFunctionDecl >(decl);
45224634 func && i + 1 < components.size () &&
45234635 components[i + 1 ].getKind () == KeyPathExpr::Component::Kind::Apply) {
45244636 argComponent = components[i + 1 ];
4637+ isApplied = true ;
45254638 }
45264639
45274640 unsigned numOperands = operands.size ();
@@ -4530,10 +4643,11 @@ RValue RValueEmitter::visitKeyPathExpr(KeyPathExpr *E, SGFContext C) {
45304643 SGF.F .getResilienceExpansion (), numOperands, needsGenericContext,
45314644 component.getDeclRef ().getSubstitutions (), decl,
45324645 argComponent.getIndexHashableConformances (), baseTy, SGF.FunctionDC ,
4533- /* for descriptor*/ false ));
4646+ /* for descriptor*/ false , /* is applied func */ isApplied ));
45344647 baseTy = loweredComponents.back ().getComponentType ();
4535- if (kind == KeyPathExpr::Component::Kind::Member &&
4536- !dyn_cast<FuncDecl>(decl))
4648+ if ((kind == KeyPathExpr::Component::Kind::Member &&
4649+ !dyn_cast<FuncDecl>(decl)) ||
4650+ (dyn_cast<FuncDecl>(decl) && !isApplied))
45374651 break ;
45384652
45394653 auto loweredArgs = SGF.emitKeyPathOperands (
0 commit comments