Skip to content

Commit 88d727d

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-rebranch
2 parents ac53a28 + c234b09 commit 88d727d

File tree

6 files changed

+78
-27
lines changed

6 files changed

+78
-27
lines changed

lib/Sema/CSGen.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -980,9 +980,11 @@ namespace {
980980
}
981981

982982
/// Add constraints for a subscript operation.
983-
Type addSubscriptConstraints(Expr *anchor, Type baseTy, Expr *index,
984-
ValueDecl *declOrNull,
985-
ConstraintLocator *locator = nullptr) {
983+
Type addSubscriptConstraints(
984+
Expr *anchor, Type baseTy, Expr *index,
985+
ValueDecl *declOrNull,
986+
ConstraintLocator *locator = nullptr,
987+
SmallVectorImpl<TypeVariableType *> *addedTypeVars = nullptr) {
986988
// Locators used in this expression.
987989
if (locator == nullptr)
988990
locator = CS.getConstraintLocator(anchor);
@@ -1002,7 +1004,7 @@ namespace {
10021004
// For an integer subscript expression on an array slice type, instead of
10031005
// introducing a new type variable we can easily obtain the element type.
10041006
if (isa<SubscriptExpr>(anchor)) {
1005-
1007+
10061008
auto isLValueBase = false;
10071009
auto baseObjTy = baseTy;
10081010
if (baseObjTy->is<LValueType>()) {
@@ -1046,6 +1048,8 @@ namespace {
10461048
if (outputTy.isNull()) {
10471049
outputTy = CS.createTypeVariable(resultLocator,
10481050
TVO_CanBindToLValue | TVO_CanBindToNoEscape);
1051+
if (addedTypeVars)
1052+
addedTypeVars->push_back(outputTy->castTo<TypeVariableType>());
10491053
}
10501054

10511055
// FIXME: This can only happen when diagnostics successfully type-checked
@@ -1062,6 +1066,8 @@ namespace {
10621066
// FIXME: weak name!
10631067
auto memberTy = CS.createTypeVariable(
10641068
memberLocator, TVO_CanBindToLValue | TVO_CanBindToNoEscape);
1069+
if (addedTypeVars)
1070+
addedTypeVars->push_back(memberTy);
10651071

10661072
// FIXME: synthesizeMaterializeForSet() wants to statically dispatch to
10671073
// a known subscript here. This might be cleaner if we split off a new
@@ -2958,7 +2964,8 @@ namespace {
29582964
bool didOptionalChain = false;
29592965
// We start optimistically from an lvalue base.
29602966
Type base = LValueType::get(root);
2961-
2967+
2968+
SmallVector<TypeVariableType *, 2> componentTypeVars;
29622969
for (unsigned i : indices(E->getComponents())) {
29632970
auto &component = E->getComponents()[i];
29642971
auto memberLocator = CS.getConstraintLocator(
@@ -2977,6 +2984,7 @@ namespace {
29772984
auto memberTy = CS.createTypeVariable(resultLocator,
29782985
TVO_CanBindToLValue |
29792986
TVO_CanBindToNoEscape);
2987+
componentTypeVars.push_back(memberTy);
29802988
auto lookupName = kind == KeyPathExpr::Component::Kind::UnresolvedProperty
29812989
? component.getUnresolvedDeclName()
29822990
: component.getDeclRef().getDecl()->getFullName();
@@ -2999,7 +3007,8 @@ namespace {
29993007
// re-type-check the constraints during failure diagnosis.
30003008
case KeyPathExpr::Component::Kind::Subscript: {
30013009
base = addSubscriptConstraints(E, base, component.getIndexExpr(),
3002-
/*decl*/ nullptr, memberLocator);
3010+
/*decl*/ nullptr, memberLocator,
3011+
&componentTypeVars);
30033012
break;
30043013
}
30053014

@@ -3015,15 +3024,18 @@ namespace {
30153024
// today. Force the base to an rvalue.
30163025
auto rvalueTy = CS.createTypeVariable(resultLocator,
30173026
TVO_CanBindToNoEscape);
3027+
componentTypeVars.push_back(rvalueTy);
30183028
CS.addConstraint(ConstraintKind::Equal, base, rvalueTy,
30193029
resultLocator);
3030+
30203031
base = rvalueTy;
30213032
LLVM_FALLTHROUGH;
30223033
}
30233034
case KeyPathExpr::Component::Kind::OptionalForce: {
30243035
auto optionalObjTy = CS.createTypeVariable(resultLocator,
30253036
TVO_CanBindToLValue |
30263037
TVO_CanBindToNoEscape);
3038+
componentTypeVars.push_back(optionalObjTy);
30273039

30283040
CS.addConstraint(ConstraintKind::OptionalObject, base, optionalObjTy,
30293041
resultLocator);
@@ -3050,6 +3062,8 @@ namespace {
30503062
// optional.
30513063
if (didOptionalChain) {
30523064
auto objTy = CS.createTypeVariable(locator, TVO_CanBindToNoEscape);
3065+
componentTypeVars.push_back(objTy);
3066+
30533067
auto optTy = OptionalType::get(objTy);
30543068
CS.addConstraint(ConstraintKind::Conversion, base, optTy,
30553069
locator);
@@ -3068,7 +3082,8 @@ namespace {
30683082
auto typeLoc =
30693083
CS.getConstraintLocator(locator, ConstraintLocator::KeyPathType);
30703084
Type kpTy = CS.createTypeVariable(typeLoc, TVO_CanBindToNoEscape);
3071-
CS.addKeyPathConstraint(kpTy, root, rvalueBase, locator);
3085+
CS.addKeyPathConstraint(kpTy, root, rvalueBase, componentTypeVars,
3086+
locator);
30723087
return kpTy;
30733088
}
30743089

lib/Sema/CSSimplify.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5714,11 +5714,13 @@ ConstraintSystem::simplifyOpenedExistentialOfConstraint(
57145714
}
57155715

57165716
ConstraintSystem::SolutionKind
5717-
ConstraintSystem::simplifyKeyPathConstraint(Type keyPathTy,
5718-
Type rootTy,
5719-
Type valueTy,
5720-
TypeMatchOptions flags,
5721-
ConstraintLocatorBuilder locator) {
5717+
ConstraintSystem::simplifyKeyPathConstraint(
5718+
Type keyPathTy,
5719+
Type rootTy,
5720+
Type valueTy,
5721+
ArrayRef<TypeVariableType *> componentTypeVars,
5722+
TypeMatchOptions flags,
5723+
ConstraintLocatorBuilder locator) {
57225724
auto subflags = getDefaultDecompositionOptions(flags);
57235725
// The constraint ought to have been anchored on a KeyPathExpr.
57245726
auto keyPath = cast<KeyPathExpr>(locator.getBaseLocator()->getAnchor());
@@ -5940,7 +5942,8 @@ ConstraintSystem::simplifyKeyPathConstraint(Type keyPathTy,
59405942
} else {
59415943
addUnsolvedConstraint(Constraint::create(*this, ConstraintKind::KeyPath,
59425944
keyPathTy, rootTy, valueTy,
5943-
locator.getBaseLocator()));
5945+
locator.getBaseLocator(),
5946+
componentTypeVars));
59445947
}
59455948
return SolutionKind::Solved;
59465949
}
@@ -7448,18 +7451,22 @@ ConstraintSystem::addKeyPathApplicationConstraint(Type keypath,
74487451
}
74497452

74507453
void
7451-
ConstraintSystem::addKeyPathConstraint(Type keypath,
7452-
Type root, Type value,
7453-
ConstraintLocatorBuilder locator,
7454-
bool isFavored) {
7454+
ConstraintSystem::addKeyPathConstraint(
7455+
Type keypath,
7456+
Type root, Type value,
7457+
ArrayRef<TypeVariableType *> componentTypeVars,
7458+
ConstraintLocatorBuilder locator,
7459+
bool isFavored) {
74557460
switch (simplifyKeyPathConstraint(keypath, root, value,
7461+
componentTypeVars,
74567462
TMF_GenerateConstraints,
74577463
locator)) {
74587464
case SolutionKind::Error:
74597465
if (shouldAddNewFailingConstraint()) {
74607466
auto c = Constraint::create(*this, ConstraintKind::KeyPath,
74617467
keypath, root, value,
7462-
getConstraintLocator(locator));
7468+
getConstraintLocator(locator),
7469+
componentTypeVars);
74637470
if (isFavored) c->setFavored();
74647471
addNewFailingConstraint(c);
74657472
}
@@ -7640,7 +7647,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
76407647
case ConstraintKind::KeyPath:
76417648
return simplifyKeyPathConstraint(
76427649
constraint.getFirstType(), constraint.getSecondType(),
7643-
constraint.getThirdType(),
7650+
constraint.getThirdType(), constraint.getTypeVariables(),
76447651
None, constraint.getLocator());
76457652

76467653
case ConstraintKind::KeyPathApplication:

lib/Sema/Constraint.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,9 +588,11 @@ Constraint *Constraint::create(ConstraintSystem &cs, ConstraintKind kind,
588588

589589
Constraint *Constraint::create(ConstraintSystem &cs, ConstraintKind kind,
590590
Type first, Type second, Type third,
591-
ConstraintLocator *locator) {
591+
ConstraintLocator *locator,
592+
ArrayRef<TypeVariableType *> extraTypeVars) {
592593
// Collect type variables.
593-
SmallVector<TypeVariableType *, 4> typeVars;
594+
SmallVector<TypeVariableType *, 4> typeVars(extraTypeVars.begin(),
595+
extraTypeVars.end());
594596
if (first->hasTypeVariable())
595597
first->getTypeVariables(typeVars);
596598
if (second->hasTypeVariable())

lib/Sema/Constraint.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,8 @@ class Constraint final : public llvm::ilist_node<Constraint>,
376376
/// Create a new constraint.
377377
static Constraint *create(ConstraintSystem &cs, ConstraintKind Kind,
378378
Type First, Type Second, Type Third,
379-
ConstraintLocator *locator);
379+
ConstraintLocator *locator,
380+
ArrayRef<TypeVariableType *> extraTypeVars = { });
380381

381382
/// Create a new member constraint, or a disjunction of that with the outer
382383
/// alternatives.

lib/Sema/ConstraintSystem.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,6 +2096,7 @@ class ConstraintSystem {
20962096

20972097
/// Add a key path constraint to the constraint system.
20982098
void addKeyPathConstraint(Type keypath, Type root, Type value,
2099+
ArrayRef<TypeVariableType *> componentTypeVars,
20992100
ConstraintLocatorBuilder locator,
21002101
bool isFavored = false);
21012102

@@ -3109,11 +3110,13 @@ class ConstraintSystem {
31093110
ConstraintLocatorBuilder locator);
31103111

31113112
/// Attempt to simplify the given KeyPath constraint.
3112-
SolutionKind simplifyKeyPathConstraint(Type keyPath,
3113-
Type root,
3114-
Type value,
3115-
TypeMatchOptions flags,
3116-
ConstraintLocatorBuilder locator);
3113+
SolutionKind simplifyKeyPathConstraint(
3114+
Type keyPath,
3115+
Type root,
3116+
Type value,
3117+
ArrayRef<TypeVariableType *> componentTypeVars,
3118+
TypeMatchOptions flags,
3119+
ConstraintLocatorBuilder locator);
31173120

31183121
/// Attempt to simplify the given defaultable constraint.
31193122
SolutionKind simplifyDefaultableConstraint(Type first, Type second,

test/Constraints/keypath.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,33 @@ func testFunc() {
5252
let _: (S) -> Int = f // expected-error {{cannot convert value of type 'KeyPath<S, Int>' to specified type '(S) -> Int'}}
5353
}
5454

55+
5556
// SR-11234
5657
public extension Array {
5758
func sorted<C: Comparable, K: KeyPath<Element, C>>(by keyPath: K) -> Array<Element> {
5859
let sortedA = self.sorted(by: { $0[keyPath: keyPath] < $1[keyPath: keyPath] })
5960
return sortedA
6061
}
6162
}
63+
64+
// rdar://problem/54322807
65+
struct X<T> {
66+
init(foo: KeyPath<T, Bool>) { }
67+
init(foo: KeyPath<T, Bool?>) { }
68+
}
69+
70+
struct Wibble {
71+
var boolProperty = false
72+
}
73+
74+
struct Bar {
75+
var optWibble: Wibble? = nil
76+
}
77+
78+
class Foo {
79+
var optBar: Bar? = nil
80+
}
81+
82+
func testFoo<T: Foo>(_: T) {
83+
let _: X<T> = .init(foo: \.optBar!.optWibble?.boolProperty)
84+
}

0 commit comments

Comments
 (0)