@@ -1524,7 +1524,7 @@ namespace {
1524
1524
auto &ctx = cs.getASTContext ();
1525
1525
auto *anchor = memberLoc->getAnchor ();
1526
1526
1527
- KeyPathExpr::Component component ;
1527
+ SmallVector< KeyPathExpr::Component, 2 > components ;
1528
1528
1529
1529
// Let's create a KeyPath expression and fill in "parsed path"
1530
1530
// after component is built.
@@ -1546,10 +1546,11 @@ namespace {
1546
1546
// calls necessary to resolve a member reference.
1547
1547
if (overload.choice .getKind () ==
1548
1548
OverloadChoiceKind::KeyPathDynamicMemberLookup) {
1549
- keyPath->resolveComponents (ctx,
1550
- buildKeyPathSubscriptComponent (
1551
- overload, dotLoc, /* indexExpr=*/ nullptr ,
1552
- ctx.Id_dynamicMember , componentLoc));
1549
+ buildKeyPathSubscriptComponent (overload, dotLoc, /* indexExpr=*/ nullptr ,
1550
+ ctx.Id_dynamicMember , componentLoc,
1551
+ components);
1552
+ keyPath->resolveComponents (ctx, components);
1553
+ cs.cacheExprTypes (keyPath);
1553
1554
return keyPath;
1554
1555
}
1555
1556
@@ -1599,8 +1600,8 @@ namespace {
1599
1600
UDE->getNameLoc (),
1600
1601
/* Implicit=*/ true );
1601
1602
1602
- component = buildKeyPathPropertyComponent (overload, UDE->getLoc (),
1603
- componentLoc );
1603
+ buildKeyPathPropertyComponent (overload, UDE->getLoc (), componentLoc ,
1604
+ components );
1604
1605
} else if (auto *SE = dyn_cast<SubscriptExpr>(anchor)) {
1605
1606
componentExpr = SE;
1606
1607
// If this is not for a keypath component, we have to copy
@@ -1628,9 +1629,9 @@ namespace {
1628
1629
/* implicit=*/ true , SE->getAccessSemantics ());
1629
1630
}
1630
1631
1631
- component = buildKeyPathSubscriptComponent (
1632
- overload, SE-> getLoc (), SE-> getIndex (), SE->getArgumentLabels (),
1633
- componentLoc );
1632
+ buildKeyPathSubscriptComponent (overload, SE-> getLoc (), SE-> getIndex (),
1633
+ SE->getArgumentLabels (), componentLoc ,
1634
+ components );
1634
1635
} else {
1635
1636
return nullptr ;
1636
1637
}
@@ -1640,10 +1641,9 @@ namespace {
1640
1641
componentExpr->setType (ty);
1641
1642
cs.cacheType (componentExpr);
1642
1643
1643
- cs.setType (keyPath, 0 , ty);
1644
-
1645
1644
keyPath->setParsedPath (componentExpr);
1646
- keyPath->resolveComponents (ctx, {component});
1645
+ keyPath->resolveComponents (ctx, components);
1646
+ cs.cacheExprTypes (keyPath);
1647
1647
return keyPath;
1648
1648
}
1649
1649
@@ -4181,13 +4181,6 @@ namespace {
4181
4181
leafTy = keyPathTy->getGenericArgs ()[1 ];
4182
4182
}
4183
4183
4184
- // Updates the constraint system with the type of the last resolved
4185
- // component. We do it this way because we sometimes insert new
4186
- // components.
4187
- auto updateCSWithResolvedComponent = [&]() {
4188
- cs.setType (E, resolvedComponents.size () - 1 , baseTy);
4189
- };
4190
-
4191
4184
for (unsigned i : indices (E->getComponents ())) {
4192
4185
auto &origComponent = E->getMutableComponents ()[i];
4193
4186
@@ -4197,24 +4190,6 @@ namespace {
4197
4190
resolvedComponents.push_back (origComponent);
4198
4191
continue ;
4199
4192
}
4200
-
4201
- auto getObjectType = [](Type optionalTy) -> Type {
4202
- Type objectTy;
4203
- if (auto lvalue = optionalTy->getAs <LValueType>()) {
4204
- objectTy = lvalue->getObjectType ()->getOptionalObjectType ();
4205
- if (optionalTy->hasUnresolvedType () && !objectTy) {
4206
- objectTy = optionalTy;
4207
- }
4208
- objectTy = LValueType::get (objectTy);
4209
- } else {
4210
- objectTy = optionalTy->getOptionalObjectType ();
4211
- if (optionalTy->hasUnresolvedType () && !objectTy) {
4212
- objectTy = optionalTy;
4213
- }
4214
- }
4215
- assert (objectTy);
4216
- return objectTy;
4217
- };
4218
4193
4219
4194
auto kind = origComponent.getKind ();
4220
4195
Optional<SelectedOverload> foundDecl;
@@ -4248,57 +4223,32 @@ namespace {
4248
4223
}
4249
4224
}
4250
4225
4251
- KeyPathExpr::Component component;
4252
4226
switch (kind) {
4253
4227
case KeyPathExpr::Component::Kind::UnresolvedProperty: {
4254
4228
// If we couldn't resolve the component, leave it alone.
4255
4229
if (!foundDecl) {
4256
- component = origComponent;
4230
+ resolvedComponents. push_back ( origComponent) ;
4257
4231
break ;
4258
4232
}
4259
4233
4260
- component = buildKeyPathPropertyComponent (
4261
- *foundDecl, origComponent.getLoc (), locator);
4262
-
4263
- baseTy = component.getComponentType ();
4264
- resolvedComponents.push_back (component);
4265
-
4266
- if (shouldForceUnwrapResult (foundDecl->choice , locator)) {
4267
- updateCSWithResolvedComponent ();
4268
- auto objectTy = getObjectType (baseTy);
4269
- auto loc = origComponent.getLoc ();
4270
- component = KeyPathExpr::Component::forOptionalForce (objectTy, loc);
4271
- baseTy = component.getComponentType ();
4272
- resolvedComponents.push_back (component);
4273
- }
4234
+ buildKeyPathPropertyComponent (*foundDecl, origComponent.getLoc (),
4235
+ locator, resolvedComponents);
4274
4236
break ;
4275
4237
}
4276
4238
case KeyPathExpr::Component::Kind::UnresolvedSubscript: {
4277
4239
// Leave the component unresolved if the overload was not resolved.
4278
4240
if (!foundDecl) {
4279
- component = origComponent;
4241
+ resolvedComponents. push_back ( origComponent) ;
4280
4242
break ;
4281
4243
}
4282
4244
4283
4245
ArrayRef<Identifier> subscriptLabels;
4284
4246
if (!isDynamicMember)
4285
4247
subscriptLabels = origComponent.getSubscriptLabels ();
4286
4248
4287
- component = buildKeyPathSubscriptComponent (
4249
+ buildKeyPathSubscriptComponent (
4288
4250
*foundDecl, origComponent.getLoc (), origComponent.getIndexExpr (),
4289
- subscriptLabels, locator);
4290
-
4291
- baseTy = component.getComponentType ();
4292
- resolvedComponents.push_back (component);
4293
-
4294
- if (shouldForceUnwrapResult (foundDecl->choice , locator)) {
4295
- updateCSWithResolvedComponent ();
4296
- auto objectTy = getObjectType (baseTy);
4297
- auto loc = origComponent.getLoc ();
4298
- component = KeyPathExpr::Component::forOptionalForce (objectTy, loc);
4299
- baseTy = component.getComponentType ();
4300
- resolvedComponents.push_back (component);
4301
- }
4251
+ subscriptLabels, locator, resolvedComponents);
4302
4252
break ;
4303
4253
}
4304
4254
case KeyPathExpr::Component::Kind::OptionalChain: {
@@ -4312,41 +4262,35 @@ namespace {
4312
4262
assert (objectTy);
4313
4263
4314
4264
auto loc = origComponent.getLoc ();
4315
- component = KeyPathExpr::Component::forOptionalChain (objectTy, loc);
4316
-
4317
- baseTy = component.getComponentType ();
4318
- resolvedComponents.push_back (component);
4265
+ resolvedComponents.push_back (
4266
+ KeyPathExpr::Component::forOptionalChain (objectTy, loc));
4319
4267
break ;
4320
4268
}
4321
- case KeyPathExpr::Component::Kind::OptionalForce: {
4322
- auto objectTy = getObjectType (baseTy);
4323
- auto loc = origComponent.getLoc ();
4324
- component = KeyPathExpr::Component::forOptionalForce (objectTy, loc);
4325
- baseTy = component.getComponentType ();
4326
- resolvedComponents.push_back (component);
4269
+ case KeyPathExpr::Component::Kind::OptionalForce:
4270
+ buildKeyPathOptionalForceComponent (resolvedComponents);
4327
4271
break ;
4328
- }
4329
- case KeyPathExpr::Component::Kind::Invalid:
4330
- component = origComponent;
4272
+ case KeyPathExpr::Component::Kind::Invalid: {
4273
+ auto component = origComponent;
4331
4274
component.setComponentType (leafTy);
4332
-
4333
- baseTy = component.getComponentType ();
4334
4275
resolvedComponents.push_back (component);
4335
4276
break ;
4336
- case KeyPathExpr::Component::Kind::Identity:
4337
- component = origComponent;
4277
+ }
4278
+ case KeyPathExpr::Component::Kind::Identity: {
4279
+ auto component = origComponent;
4338
4280
component.setComponentType (baseTy);
4339
4281
resolvedComponents.push_back (component);
4340
4282
break ;
4283
+ }
4341
4284
case KeyPathExpr::Component::Kind::Property:
4342
4285
case KeyPathExpr::Component::Kind::Subscript:
4343
4286
case KeyPathExpr::Component::Kind::OptionalWrap:
4344
4287
case KeyPathExpr::Component::Kind::TupleElement:
4345
4288
llvm_unreachable (" already resolved" );
4346
4289
}
4347
4290
4348
- // By now, "baseTy" is the result type of this component.
4349
- updateCSWithResolvedComponent ();
4291
+ // Update "baseTy" with the result type of the last component.
4292
+ assert (!resolvedComponents.empty ());
4293
+ baseTy = resolvedComponents.back ().getComponentType ();
4350
4294
}
4351
4295
4352
4296
// Wrap a non-optional result if there was chaining involved.
@@ -4359,10 +4303,12 @@ namespace {
4359
4303
auto component = KeyPathExpr::Component::forOptionalWrap (leafTy);
4360
4304
resolvedComponents.push_back (component);
4361
4305
baseTy = leafTy;
4362
- updateCSWithResolvedComponent ();
4363
4306
}
4307
+
4308
+ // Set the resolved components, and cache their types.
4364
4309
E->resolveComponents (cs.getASTContext (), resolvedComponents);
4365
-
4310
+ cs.cacheExprTypes (E);
4311
+
4366
4312
// See whether there's an equivalent ObjC key path string we can produce
4367
4313
// for interop purposes.
4368
4314
if (cs.getASTContext ().LangOpts .EnableObjCInterop ) {
@@ -4481,10 +4427,37 @@ namespace {
4481
4427
return coerceToType (outerApply, exprType, cs.getConstraintLocator (E));
4482
4428
}
4483
4429
4484
- KeyPathExpr::Component
4485
- buildKeyPathPropertyComponent (const SelectedOverload &overload,
4486
- SourceLoc componentLoc,
4487
- ConstraintLocator *locator) {
4430
+ void buildKeyPathOptionalForceComponent (
4431
+ SmallVectorImpl<KeyPathExpr::Component> &components) {
4432
+ assert (!components.empty ());
4433
+
4434
+ // Unwrap the last component type, preserving @lvalue-ness.
4435
+ auto optionalTy = components.back ().getComponentType ();
4436
+ Type objectTy;
4437
+ if (auto lvalue = optionalTy->getAs <LValueType>()) {
4438
+ objectTy = lvalue->getObjectType ()->getOptionalObjectType ();
4439
+ if (optionalTy->hasUnresolvedType () && !objectTy) {
4440
+ objectTy = optionalTy;
4441
+ }
4442
+ objectTy = LValueType::get (objectTy);
4443
+ } else {
4444
+ objectTy = optionalTy->getOptionalObjectType ();
4445
+ if (optionalTy->hasUnresolvedType () && !objectTy) {
4446
+ objectTy = optionalTy;
4447
+ }
4448
+ }
4449
+ assert (objectTy);
4450
+
4451
+ auto loc = components.back ().getLoc ();
4452
+ components.push_back (
4453
+ KeyPathExpr::Component::forOptionalForce (objectTy, loc));
4454
+ }
4455
+
4456
+ void buildKeyPathPropertyComponent (
4457
+ const SelectedOverload &overload, SourceLoc componentLoc,
4458
+ ConstraintLocator *locator,
4459
+ SmallVectorImpl<KeyPathExpr::Component> &components) {
4460
+ auto resolvedTy = simplifyType (overload.openedType );
4488
4461
if (auto *property = overload.choice .getDeclOrNull ()) {
4489
4462
// Key paths can only refer to properties currently.
4490
4463
auto varDecl = cast<VarDecl>(property);
@@ -4494,26 +4467,24 @@ namespace {
4494
4467
// There is a fix which diagnoses such situation already.
4495
4468
assert (!varDecl->isStatic ());
4496
4469
4497
- auto resolvedTy = overload.openedType ;
4498
- resolvedTy = simplifyType (resolvedTy);
4499
-
4500
4470
// Compute the concrete reference to the member.
4501
4471
auto ref = resolveConcreteDeclRef (property, locator);
4502
- return KeyPathExpr::Component::forProperty (ref, resolvedTy,
4503
- componentLoc);
4472
+ components.push_back (
4473
+ KeyPathExpr::Component::forProperty (ref, resolvedTy, componentLoc));
4474
+ } else {
4475
+ auto fieldIndex = overload.choice .getTupleIndex ();
4476
+ components.push_back (KeyPathExpr::Component::forTupleElement (
4477
+ fieldIndex, resolvedTy, componentLoc));
4504
4478
}
4505
4479
4506
- auto fieldIndex = overload.choice .getTupleIndex ();
4507
- auto resolvedTy = overload.openedType ;
4508
- resolvedTy = simplifyType (resolvedTy);
4509
-
4510
- return KeyPathExpr::Component::forTupleElement (fieldIndex, resolvedTy,
4511
- componentLoc);
4480
+ if (shouldForceUnwrapResult (overload.choice , locator))
4481
+ buildKeyPathOptionalForceComponent (components);
4512
4482
}
4513
4483
4514
- KeyPathExpr::Component buildKeyPathSubscriptComponent (
4484
+ void buildKeyPathSubscriptComponent (
4515
4485
SelectedOverload &overload, SourceLoc componentLoc, Expr *indexExpr,
4516
- ArrayRef<Identifier> labels, ConstraintLocator *locator) {
4486
+ ArrayRef<Identifier> labels, ConstraintLocator *locator,
4487
+ SmallVectorImpl<KeyPathExpr::Component> &components) {
4517
4488
auto subscript = cast<SubscriptDecl>(overload.choice .getDecl ());
4518
4489
assert (!subscript->isGetterMutating ());
4519
4490
@@ -4583,10 +4554,14 @@ namespace {
4583
4554
conformances.push_back (hashableConformance);
4584
4555
}
4585
4556
4586
- return KeyPathExpr::Component::forSubscriptWithPrebuiltIndexExpr (
4557
+ auto comp = KeyPathExpr::Component::forSubscriptWithPrebuiltIndexExpr (
4587
4558
ref, newIndexExpr, cs.getASTContext ().AllocateCopy (newLabels),
4588
4559
resolvedTy, componentLoc,
4589
4560
cs.getASTContext ().AllocateCopy (conformances));
4561
+ components.push_back (comp);
4562
+
4563
+ if (shouldForceUnwrapResult (overload.choice , locator))
4564
+ buildKeyPathOptionalForceComponent (components);
4590
4565
}
4591
4566
4592
4567
Expr *visitKeyPathDotExpr (KeyPathDotExpr *E) {
0 commit comments