@@ -2218,23 +2218,31 @@ namespace {
22182218 Expr *buildKeyPathDynamicMemberArgExpr (BoundGenericType *keyPathTy,
22192219 SourceLoc dotLoc,
22202220 ConstraintLocator *memberLoc) {
2221+ using Component = KeyPathExpr::Component;
22212222 auto &ctx = cs.getASTContext ();
22222223 auto *anchor = getAsExpr (memberLoc->getAnchor ());
22232224
2224- SmallVector<KeyPathExpr::Component, 2 > components;
2225-
2226- // Let's create a KeyPath expression and fill in "parsed path"
2227- // after component is built.
2228- auto *keyPath = new (ctx) KeyPathExpr (/* backslashLoc=*/ dotLoc,
2229- /* parsedRoot=*/ nullptr ,
2230- /* parsedPath=*/ anchor,
2231- /* hasLeadingDot=*/ false ,
2232- /* isImplicit=*/ true );
2233- // Type of the keypath expression we are forming is known
2234- // in advance, so let's set it right away.
2235- keyPath->setType (keyPathTy);
2236- cs.cacheType (keyPath);
2225+ auto makeKeyPath = [&](ArrayRef<Component> components) -> Expr * {
2226+ // Create a new implicit key path. We pass in anchor as the parsed path
2227+ // to set the end loc, but don't want to keep it as the parsed path,
2228+ // so clear it out after.
2229+ auto *kp = new (ctx) KeyPathExpr (/* backslashLoc*/ dotLoc,
2230+ /* parsedRoot*/ nullptr ,
2231+ /* parsedPath*/ anchor,
2232+ /* hasLeadingDot*/ false ,
2233+ /* isImplicit*/ true );
2234+ kp->setParsedPath (nullptr );
2235+ kp->setComponents (ctx, components);
2236+ kp->setType (keyPathTy);
2237+ cs.cacheExprTypes (kp);
2238+
2239+ // See whether there's an equivalent ObjC key path string we can produce
2240+ // for interop purposes.
2241+ checkAndSetObjCKeyPathString (kp);
2242+ return kp;
2243+ };
22372244
2245+ SmallVector<Component, 2 > components;
22382246 auto *componentLoc = cs.getConstraintLocator (
22392247 memberLoc,
22402248 LocatorPathElt::KeyPathDynamicMember (keyPathTy->getAnyNominal ()));
@@ -2247,95 +2255,44 @@ namespace {
22472255 case OverloadChoiceKind::KeyPathDynamicMemberLookup: {
22482256 buildKeyPathSubscriptComponent (overload, dotLoc, /* args=*/ nullptr ,
22492257 componentLoc, components);
2250- keyPath->setComponents (ctx, components);
2251- cs.cacheExprTypes (keyPath);
2252- return keyPath;
2258+ return makeKeyPath (components);
22532259 }
22542260
22552261 default :
22562262 break ;
22572263 }
22582264
2259- // We can't reuse existing expression because type-check
2260- // based diagnostics could hold the reference to original AST.
2261- Expr *componentExpr = nullptr ;
2262- auto *dotExpr = new (ctx) KeyPathDotExpr (dotLoc);
2263-
2264- // Determines whether this index is built to be used for
2265- // one of the existing keypath components e.g. `\Lens<[Int]>.count`
2266- // instead of a regular expression e.g. `lens[0]`.
2267- bool forKeyPathComponent = false ;
2268- // Looks like keypath dynamic member lookup was used inside
2269- // of a keypath expression e.g. `\Lens<[Int]>.count` where
2270- // `count` is referenced using dynamic lookup.
22712265 if (auto *KPE = dyn_cast<KeyPathExpr>(anchor)) {
2266+ // Looks like keypath dynamic member lookup was used inside
2267+ // of a keypath expression e.g. `\Lens<[Int]>.count` where
2268+ // `count` is referenced using dynamic lookup.
22722269 auto kpElt = memberLoc->findFirst <LocatorPathElt::KeyPathComponent>();
22732270 assert (kpElt && " no keypath component node" );
2274- auto &origComponent = KPE->getComponents ()[kpElt->getIndex ()];
2275-
2276- using ComponentKind = KeyPathExpr::Component::Kind;
2277- if (origComponent.getKind () == ComponentKind::UnresolvedProperty) {
2278- anchor = new (ctx) UnresolvedDotExpr (
2279- dotExpr, dotLoc, origComponent.getUnresolvedDeclName (),
2280- DeclNameLoc (origComponent.getLoc ()),
2281- /* Implicit=*/ true );
2282- } else if (origComponent.getKind () ==
2283- ComponentKind::UnresolvedSubscript) {
2284- anchor = SubscriptExpr::create (
2285- ctx, dotExpr, origComponent.getSubscriptArgs (), ConcreteDeclRef (),
2286- /* implicit=*/ true , AccessSemantics::Ordinary);
2271+ auto &comp = KPE->getComponents ()[kpElt->getIndex ()];
2272+
2273+ if (comp.getKind () == Component::Kind::UnresolvedProperty) {
2274+ buildKeyPathPropertyComponent (overload, comp.getLoc (), componentLoc,
2275+ components);
2276+ } else if (comp.getKind () == Component::Kind::UnresolvedSubscript) {
2277+ buildKeyPathSubscriptComponent (overload, comp.getLoc (),
2278+ comp.getSubscriptArgs (), componentLoc,
2279+ components);
22872280 } else {
22882281 return nullptr ;
22892282 }
2290-
2291- anchor->setType (simplifyType (overload.openedType ));
2292- cs.cacheType (anchor);
2293- forKeyPathComponent = true ;
2283+ return makeKeyPath (components);
22942284 }
22952285
22962286 if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
2297- componentExpr =
2298- forKeyPathComponent
2299- ? UDE
2300- : new (ctx) UnresolvedDotExpr (dotExpr, dotLoc, UDE->getName (),
2301- UDE->getNameLoc (),
2302- /* Implicit=*/ true );
2303-
23042287 buildKeyPathPropertyComponent (overload, UDE->getLoc (), componentLoc,
23052288 components);
23062289 } else if (auto *SE = dyn_cast<SubscriptExpr>(anchor)) {
2307- componentExpr = SE;
2308- // If this is not for a keypath component, we have to copy
2309- // original subscript expression because expression based
2310- // diagnostics might have a reference to it, so it couldn't
2311- // be modified.
2312- if (!forKeyPathComponent) {
2313- componentExpr = SubscriptExpr::create (
2314- ctx, dotExpr, SE->getArgs (),
2315- SE->hasDecl () ? SE->getDecl () : ConcreteDeclRef (),
2316- /* implicit=*/ true , SE->getAccessSemantics ());
2317- }
2318-
23192290 buildKeyPathSubscriptComponent (overload, SE->getLoc (), SE->getArgs (),
23202291 componentLoc, components);
23212292 } else {
23222293 return nullptr ;
23232294 }
2324-
2325- assert (componentExpr);
2326- Type ty = simplifyType (cs.getType (anchor));
2327- componentExpr->setType (ty);
2328- cs.cacheType (componentExpr);
2329-
2330- keyPath->setParsedPath (componentExpr);
2331- keyPath->setComponents (ctx, components);
2332- cs.cacheExprTypes (keyPath);
2333-
2334- // See whether there's an equivalent ObjC key path string we can produce
2335- // for interop purposes.
2336- checkAndSetObjCKeyPathString (keyPath);
2337-
2338- return keyPath;
2295+ return makeKeyPath (components);
23392296 }
23402297
23412298 // / Bridge the given value (which is an error type) to NSError.
0 commit comments