@@ -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,10 @@ 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
1553
return keyPath;
1554
1554
}
1555
1555
@@ -1599,8 +1599,8 @@ namespace {
1599
1599
UDE->getNameLoc (),
1600
1600
/* Implicit=*/ true );
1601
1601
1602
- component = buildKeyPathPropertyComponent (overload, UDE->getLoc (),
1603
- componentLoc );
1602
+ buildKeyPathPropertyComponent (overload, UDE->getLoc (), componentLoc ,
1603
+ components );
1604
1604
} else if (auto *SE = dyn_cast<SubscriptExpr>(anchor)) {
1605
1605
componentExpr = SE;
1606
1606
// If this is not for a keypath component, we have to copy
@@ -1628,9 +1628,9 @@ namespace {
1628
1628
/* implicit=*/ true , SE->getAccessSemantics ());
1629
1629
}
1630
1630
1631
- component = buildKeyPathSubscriptComponent (
1632
- overload, SE-> getLoc (), SE-> getIndex (), SE->getArgumentLabels (),
1633
- componentLoc );
1631
+ buildKeyPathSubscriptComponent (overload, SE-> getLoc (), SE-> getIndex (),
1632
+ SE->getArgumentLabels (), componentLoc ,
1633
+ components );
1634
1634
} else {
1635
1635
return nullptr ;
1636
1636
}
@@ -1643,7 +1643,7 @@ namespace {
1643
1643
cs.setType (keyPath, 0 , ty);
1644
1644
1645
1645
keyPath->setParsedPath (componentExpr);
1646
- keyPath->resolveComponents (ctx, {component} );
1646
+ keyPath->resolveComponents (ctx, components );
1647
1647
return keyPath;
1648
1648
}
1649
1649
@@ -4190,24 +4190,6 @@ namespace {
4190
4190
resolvedComponents.push_back (origComponent);
4191
4191
continue ;
4192
4192
}
4193
-
4194
- auto getObjectType = [](Type optionalTy) -> Type {
4195
- Type objectTy;
4196
- if (auto lvalue = optionalTy->getAs <LValueType>()) {
4197
- objectTy = lvalue->getObjectType ()->getOptionalObjectType ();
4198
- if (optionalTy->hasUnresolvedType () && !objectTy) {
4199
- objectTy = optionalTy;
4200
- }
4201
- objectTy = LValueType::get (objectTy);
4202
- } else {
4203
- objectTy = optionalTy->getOptionalObjectType ();
4204
- if (optionalTy->hasUnresolvedType () && !objectTy) {
4205
- objectTy = optionalTy;
4206
- }
4207
- }
4208
- assert (objectTy);
4209
- return objectTy;
4210
- };
4211
4193
4212
4194
auto kind = origComponent.getKind ();
4213
4195
Optional<SelectedOverload> foundDecl;
@@ -4249,17 +4231,8 @@ namespace {
4249
4231
break ;
4250
4232
}
4251
4233
4252
- auto component = buildKeyPathPropertyComponent (
4253
- *foundDecl, origComponent.getLoc (), locator);
4254
-
4255
- resolvedComponents.push_back (component);
4256
-
4257
- if (shouldForceUnwrapResult (foundDecl->choice , locator)) {
4258
- auto objectTy = getObjectType (baseTy);
4259
- auto loc = origComponent.getLoc ();
4260
- resolvedComponents.push_back (
4261
- KeyPathExpr::Component::forOptionalForce (objectTy, loc));
4262
- }
4234
+ buildKeyPathPropertyComponent (*foundDecl, origComponent.getLoc (),
4235
+ locator, resolvedComponents);
4263
4236
break ;
4264
4237
}
4265
4238
case KeyPathExpr::Component::Kind::UnresolvedSubscript: {
@@ -4273,17 +4246,9 @@ namespace {
4273
4246
if (!isDynamicMember)
4274
4247
subscriptLabels = origComponent.getSubscriptLabels ();
4275
4248
4276
- auto component = buildKeyPathSubscriptComponent (
4249
+ buildKeyPathSubscriptComponent (
4277
4250
*foundDecl, origComponent.getLoc (), origComponent.getIndexExpr (),
4278
- subscriptLabels, locator);
4279
- resolvedComponents.push_back (component);
4280
-
4281
- if (shouldForceUnwrapResult (foundDecl->choice , locator)) {
4282
- auto objectTy = getObjectType (baseTy);
4283
- auto loc = origComponent.getLoc ();
4284
- resolvedComponents.push_back (
4285
- KeyPathExpr::Component::forOptionalForce (objectTy, loc));
4286
- }
4251
+ subscriptLabels, locator, resolvedComponents);
4287
4252
break ;
4288
4253
}
4289
4254
case KeyPathExpr::Component::Kind::OptionalChain: {
@@ -4301,13 +4266,9 @@ namespace {
4301
4266
KeyPathExpr::Component::forOptionalChain (objectTy, loc));
4302
4267
break ;
4303
4268
}
4304
- case KeyPathExpr::Component::Kind::OptionalForce: {
4305
- auto objectTy = getObjectType (baseTy);
4306
- auto loc = origComponent.getLoc ();
4307
- resolvedComponents.push_back (
4308
- KeyPathExpr::Component::forOptionalForce (objectTy, loc));
4269
+ case KeyPathExpr::Component::Kind::OptionalForce:
4270
+ buildKeyPathOptionalForceComponent (resolvedComponents);
4309
4271
break ;
4310
- }
4311
4272
case KeyPathExpr::Component::Kind::Invalid: {
4312
4273
auto component = origComponent;
4313
4274
component.setComponentType (leafTy);
@@ -4466,10 +4427,37 @@ namespace {
4466
4427
return coerceToType (outerApply, exprType, cs.getConstraintLocator (E));
4467
4428
}
4468
4429
4469
- KeyPathExpr::Component
4470
- buildKeyPathPropertyComponent (const SelectedOverload &overload,
4471
- SourceLoc componentLoc,
4472
- 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 );
4473
4461
if (auto *property = overload.choice .getDeclOrNull ()) {
4474
4462
// Key paths can only refer to properties currently.
4475
4463
auto varDecl = cast<VarDecl>(property);
@@ -4479,26 +4467,24 @@ namespace {
4479
4467
// There is a fix which diagnoses such situation already.
4480
4468
assert (!varDecl->isStatic ());
4481
4469
4482
- auto resolvedTy = overload.openedType ;
4483
- resolvedTy = simplifyType (resolvedTy);
4484
-
4485
4470
// Compute the concrete reference to the member.
4486
4471
auto ref = resolveConcreteDeclRef (property, locator);
4487
- return KeyPathExpr::Component::forProperty (ref, resolvedTy,
4488
- 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));
4489
4478
}
4490
4479
4491
- auto fieldIndex = overload.choice .getTupleIndex ();
4492
- auto resolvedTy = overload.openedType ;
4493
- resolvedTy = simplifyType (resolvedTy);
4494
-
4495
- return KeyPathExpr::Component::forTupleElement (fieldIndex, resolvedTy,
4496
- componentLoc);
4480
+ if (shouldForceUnwrapResult (overload.choice , locator))
4481
+ buildKeyPathOptionalForceComponent (components);
4497
4482
}
4498
4483
4499
- KeyPathExpr::Component buildKeyPathSubscriptComponent (
4484
+ void buildKeyPathSubscriptComponent (
4500
4485
SelectedOverload &overload, SourceLoc componentLoc, Expr *indexExpr,
4501
- ArrayRef<Identifier> labels, ConstraintLocator *locator) {
4486
+ ArrayRef<Identifier> labels, ConstraintLocator *locator,
4487
+ SmallVectorImpl<KeyPathExpr::Component> &components) {
4502
4488
auto subscript = cast<SubscriptDecl>(overload.choice .getDecl ());
4503
4489
assert (!subscript->isGetterMutating ());
4504
4490
@@ -4568,10 +4554,14 @@ namespace {
4568
4554
conformances.push_back (hashableConformance);
4569
4555
}
4570
4556
4571
- return KeyPathExpr::Component::forSubscriptWithPrebuiltIndexExpr (
4557
+ auto comp = KeyPathExpr::Component::forSubscriptWithPrebuiltIndexExpr (
4572
4558
ref, newIndexExpr, cs.getASTContext ().AllocateCopy (newLabels),
4573
4559
resolvedTy, componentLoc,
4574
4560
cs.getASTContext ().AllocateCopy (conformances));
4561
+ components.push_back (comp);
4562
+
4563
+ if (shouldForceUnwrapResult (overload.choice , locator))
4564
+ buildKeyPathOptionalForceComponent (components);
4575
4565
}
4576
4566
4577
4567
Expr *visitKeyPathDotExpr (KeyPathDotExpr *E) {
0 commit comments