@@ -2218,23 +2218,31 @@ namespace {
2218
2218
Expr *buildKeyPathDynamicMemberArgExpr (BoundGenericType *keyPathTy,
2219
2219
SourceLoc dotLoc,
2220
2220
ConstraintLocator *memberLoc) {
2221
+ using Component = KeyPathExpr::Component;
2221
2222
auto &ctx = cs.getASTContext ();
2222
2223
auto *anchor = getAsExpr (memberLoc->getAnchor ());
2223
2224
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
+ };
2237
2244
2245
+ SmallVector<Component, 2 > components;
2238
2246
auto *componentLoc = cs.getConstraintLocator (
2239
2247
memberLoc,
2240
2248
LocatorPathElt::KeyPathDynamicMember (keyPathTy->getAnyNominal ()));
@@ -2247,95 +2255,44 @@ namespace {
2247
2255
case OverloadChoiceKind::KeyPathDynamicMemberLookup: {
2248
2256
buildKeyPathSubscriptComponent (overload, dotLoc, /* args=*/ nullptr ,
2249
2257
componentLoc, components);
2250
- keyPath->setComponents (ctx, components);
2251
- cs.cacheExprTypes (keyPath);
2252
- return keyPath;
2258
+ return makeKeyPath (components);
2253
2259
}
2254
2260
2255
2261
default :
2256
2262
break ;
2257
2263
}
2258
2264
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.
2271
2265
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.
2272
2269
auto kpElt = memberLoc->findFirst <LocatorPathElt::KeyPathComponent>();
2273
2270
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);
2287
2280
} else {
2288
2281
return nullptr ;
2289
2282
}
2290
-
2291
- anchor->setType (simplifyType (overload.openedType ));
2292
- cs.cacheType (anchor);
2293
- forKeyPathComponent = true ;
2283
+ return makeKeyPath (components);
2294
2284
}
2295
2285
2296
2286
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
-
2304
2287
buildKeyPathPropertyComponent (overload, UDE->getLoc (), componentLoc,
2305
2288
components);
2306
2289
} 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
-
2319
2290
buildKeyPathSubscriptComponent (overload, SE->getLoc (), SE->getArgs (),
2320
2291
componentLoc, components);
2321
2292
} else {
2322
2293
return nullptr ;
2323
2294
}
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);
2339
2296
}
2340
2297
2341
2298
// / Bridge the given value (which is an error type) to NSError.
0 commit comments