@@ -1545,12 +1545,44 @@ namespace {
15451545 /* parsedRoot=*/ nullptr ,
15461546 /* parsedPath=*/ anchor,
15471547 /* isImplicit=*/ true );
1548+ // Type of the keypath expression we are forming is known
1549+ // in advance, so let's set it right away.
1550+ keyPath->setType (keyPathTy);
1551+ cs.cacheType (keyPath);
15481552
15491553 auto *componentLoc = cs.getConstraintLocator (
15501554 memberLoc,
15511555 LocatorPathElt::getKeyPathDynamicMember (keyPathTy->getAnyNominal ()));
15521556 auto overload = solution.getOverloadChoice (componentLoc);
15531557
1558+ auto buildSubscriptComponent = [&](SourceLoc loc, Expr *indexExpr,
1559+ ArrayRef<Identifier> labels) {
1560+ // Save a reference to the component so we can do a post-pass to check
1561+ // the Hashable conformance of the indexes.
1562+ KeyPathSubscriptComponents.push_back ({keyPath, 0 });
1563+ return buildKeyPathSubscriptComponent (overload, loc, indexExpr, labels,
1564+ componentLoc);
1565+ };
1566+
1567+ auto getKeyPathComponentIndex =
1568+ [](ConstraintLocator *locator) -> unsigned {
1569+ for (const auto &elt : locator->getPath ()) {
1570+ if (elt.getKind () == ConstraintLocator::KeyPathComponent)
1571+ return elt.getValue ();
1572+ }
1573+ llvm_unreachable (" no keypath component node" );
1574+ };
1575+
1576+ // Looks like there is a chain of implicit `subscript(dynamicMember:)`
1577+ // calls necessary to resolve a member reference.
1578+ if (overload.choice .getKind () ==
1579+ OverloadChoiceKind::KeyPathDynamicMemberLookup) {
1580+ keyPath->resolveComponents (
1581+ ctx, buildSubscriptComponent (dotLoc, /* indexExpr=*/ nullptr ,
1582+ ctx.Id_dynamicMember ));
1583+ return keyPath;
1584+ }
1585+
15541586 // We can't reuse existing expression because type-check
15551587 // based diagnostics could hold the reference to original AST.
15561588 Expr *componentExpr = nullptr ;
@@ -1564,13 +1596,8 @@ namespace {
15641596 // of a keypath expression e.g. `\Lens<[Int]>.count` where
15651597 // `count` is referenced using dynamic lookup.
15661598 if (auto *KPE = dyn_cast<KeyPathExpr>(anchor)) {
1567- auto path = memberLoc->getPath ();
1568- if (memberLoc->isSubscriptMemberRef ())
1569- path = path.drop_back ();
1570-
1571- auto &componentIdx = path.back ();
1572- assert (componentIdx.getKind () == ConstraintLocator::KeyPathComponent);
1573- auto &origComponent = KPE->getComponents ()[componentIdx.getValue ()];
1599+ auto componentIdx = getKeyPathComponentIndex (memberLoc);
1600+ auto &origComponent = KPE->getComponents ()[componentIdx];
15741601
15751602 using ComponentKind = KeyPathExpr::Component::Kind;
15761603 if (origComponent.getKind () == ComponentKind::UnresolvedProperty) {
@@ -1630,12 +1657,8 @@ namespace {
16301657 /* implicit=*/ true , SE->getAccessSemantics ());
16311658 }
16321659
1633- component = buildKeyPathSubscriptComponent (
1634- overload, SE->getLoc (), SE->getIndex (), SE->getArgumentLabels (),
1635- componentLoc);
1636- // Save a reference to the component so we can do a post-pass to check
1637- // the Hashable conformance of the indexes.
1638- KeyPathSubscriptComponents.push_back ({keyPath, 0 });
1660+ component = buildSubscriptComponent (SE->getLoc (), SE->getIndex (),
1661+ SE->getArgumentLabels ());
16391662 } else {
16401663 return nullptr ;
16411664 }
@@ -1646,8 +1669,6 @@ namespace {
16461669
16471670 keyPath->setParsedPath (componentExpr);
16481671 keyPath->resolveComponents (ctx, {component});
1649- keyPath->setType (keyPathTy);
1650- cs.cacheType (keyPath);
16511672 return keyPath;
16521673 }
16531674
@@ -2815,12 +2836,7 @@ namespace {
28152836 // Figure out the expected type of the lookup parameter. We know the
28162837 // openedFullType will be "xType -> indexType -> resultType". Dig out
28172838 // its index type.
2818- auto declTy = solution.simplifyType (overload.openedFullType );
2819- auto subscriptTy = declTy->castTo <FunctionType>()->getResult ();
2820- auto refFnType = subscriptTy->castTo <FunctionType>();
2821- assert (refFnType->getParams ().size () == 1 &&
2822- " subscript always has one arg" );
2823- auto paramTy = refFnType->getParams ()[0 ].getPlainType ();
2839+ auto paramTy = getTypeOfDynamicMemberIndex (overload);
28242840
28252841 Expr *argExpr = nullptr ;
28262842 if (overload.choice .getKind () ==
@@ -2855,6 +2871,20 @@ namespace {
28552871 /* isImplicit*/ false , AccessSemantics::Ordinary, overload);
28562872 }
28572873
2874+ Type getTypeOfDynamicMemberIndex (const SelectedOverload &overload) {
2875+ assert (overload.choice .getKind () ==
2876+ OverloadChoiceKind::DynamicMemberLookup ||
2877+ overload.choice .getKind () ==
2878+ OverloadChoiceKind::KeyPathDynamicMemberLookup);
2879+
2880+ auto declTy = solution.simplifyType (overload.openedFullType );
2881+ auto subscriptTy = declTy->castTo <FunctionType>()->getResult ();
2882+ auto refFnType = subscriptTy->castTo <FunctionType>();
2883+ assert (refFnType->getParams ().size () == 1 &&
2884+ " subscript always has one arg" );
2885+ return refFnType->getParams ()[0 ].getPlainType ();
2886+ }
2887+
28582888 public:
28592889 Expr *visitUnresolvedDotExpr (UnresolvedDotExpr *expr) {
28602890 return applyMemberRefExpr (expr, expr->getBase (), expr->getDotLoc (),
@@ -4599,10 +4629,9 @@ namespace {
45994629
46004630 if (overload.choice .getKind () ==
46014631 OverloadChoiceKind::KeyPathDynamicMemberLookup) {
4602- auto fnType = overload.openedType ->castTo <FunctionType>();
4603- auto keyPathTy = simplifyType (fnType->getParams ()[0 ].getPlainType ());
4632+ auto indexType = getTypeOfDynamicMemberIndex (overload);
46044633 indexExpr = buildKeyPathDynamicMemberIndexExpr (
4605- keyPathTy ->castTo <BoundGenericType>(), componentLoc, locator);
4634+ indexType ->castTo <BoundGenericType>(), componentLoc, locator);
46064635 } else {
46074636 auto fieldName = overload.choice .getName ().getBaseIdentifier ().str ();
46084637 indexExpr = buildDynamicMemberLookupIndexExpr (fieldName, componentLoc,
0 commit comments