Skip to content

Commit 2aede97

Browse files
authored
Merge pull request #30773 from hamishknight/insider-information-5.2
[5.2][CS] Use getParameterType for KeyPath as function
2 parents b4a65a4 + 560b596 commit 2aede97

File tree

4 files changed

+45
-20
lines changed

4 files changed

+45
-20
lines changed

lib/Sema/CSApply.cpp

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4175,7 +4175,7 @@ namespace {
41754175
Type baseTy, leafTy;
41764176
Type exprType = cs.getType(E);
41774177
if (auto fnTy = exprType->getAs<FunctionType>()) {
4178-
baseTy = fnTy->getParams()[0].getPlainType();
4178+
baseTy = fnTy->getParams()[0].getParameterType();
41794179
leafTy = fnTy->getResult();
41804180
isFunctionType = true;
41814181
} else {
@@ -4184,12 +4184,15 @@ namespace {
41844184
leafTy = keyPathTy->getGenericArgs()[1];
41854185
}
41864186

4187+
// Track the type of the current component. Once we finish projecting
4188+
// through each component of the key path, we should reach the leafTy.
4189+
auto componentTy = baseTy;
41874190
for (unsigned i : indices(E->getComponents())) {
41884191
auto &origComponent = E->getMutableComponents()[i];
41894192

41904193
// If there were unresolved types, we may end up with a null base for
41914194
// following components.
4192-
if (!baseTy) {
4195+
if (!componentTy) {
41934196
resolvedComponents.push_back(origComponent);
41944197
continue;
41954198
}
@@ -4258,9 +4261,9 @@ namespace {
42584261
didOptionalChain = true;
42594262
// Chaining always forces the element to be an rvalue.
42604263
auto objectTy =
4261-
baseTy->getWithoutSpecifierType()->getOptionalObjectType();
4262-
if (baseTy->hasUnresolvedType() && !objectTy) {
4263-
objectTy = baseTy;
4264+
componentTy->getWithoutSpecifierType()->getOptionalObjectType();
4265+
if (componentTy->hasUnresolvedType() && !objectTy) {
4266+
objectTy = componentTy;
42644267
}
42654268
assert(objectTy);
42664269

@@ -4280,7 +4283,7 @@ namespace {
42804283
}
42814284
case KeyPathExpr::Component::Kind::Identity: {
42824285
auto component = origComponent;
4283-
component.setComponentType(baseTy);
4286+
component.setComponentType(componentTy);
42844287
resolvedComponents.push_back(component);
42854288
break;
42864289
}
@@ -4291,21 +4294,20 @@ namespace {
42914294
llvm_unreachable("already resolved");
42924295
}
42934296

4294-
// Update "baseTy" with the result type of the last component.
4297+
// Update "componentTy" with the result type of the last component.
42954298
assert(!resolvedComponents.empty());
4296-
baseTy = resolvedComponents.back().getComponentType();
4299+
componentTy = resolvedComponents.back().getComponentType();
42974300
}
42984301

42994302
// Wrap a non-optional result if there was chaining involved.
4300-
if (didOptionalChain &&
4301-
baseTy &&
4302-
!baseTy->hasUnresolvedType() &&
4303-
!baseTy->getWithoutSpecifierType()->isEqual(leafTy)) {
4303+
if (didOptionalChain && componentTy &&
4304+
!componentTy->hasUnresolvedType() &&
4305+
!componentTy->getWithoutSpecifierType()->isEqual(leafTy)) {
43044306
assert(leafTy->getOptionalObjectType()->isEqual(
4305-
baseTy->getWithoutSpecifierType()));
4307+
componentTy->getWithoutSpecifierType()));
43064308
auto component = KeyPathExpr::Component::forOptionalWrap(leafTy);
43074309
resolvedComponents.push_back(component);
4308-
baseTy = leafTy;
4310+
componentTy = leafTy;
43094311
}
43104312

43114313
// Set the resolved components, and cache their types.
@@ -4331,8 +4333,8 @@ namespace {
43314333

43324334
// The final component type ought to line up with the leaf type of the
43334335
// key path.
4334-
assert(!baseTy || baseTy->hasUnresolvedType()
4335-
|| baseTy->getWithoutSpecifierType()->isEqual(leafTy));
4336+
assert(!componentTy || componentTy->hasUnresolvedType()
4337+
|| componentTy->getWithoutSpecifierType()->isEqual(leafTy));
43364338

43374339
if (!isFunctionType)
43384340
return E;
@@ -4342,9 +4344,6 @@ namespace {
43424344
// this; we're going to change E's type to KeyPath<baseTy, leafTy> and
43434345
// then wrap it in a larger closure expression with the appropriate type.
43444346

4345-
// baseTy has been overwritten by the loop above; restore it.
4346-
baseTy = exprType->getAs<FunctionType>()->getParams()[0].getPlainType();
4347-
43484347
// Compute KeyPath<baseTy, leafTy> and set E's type back to it.
43494348
auto kpDecl = cs.getASTContext().getKeyPathDecl();
43504349
auto keyPathTy =

lib/Sema/CSSimplify.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6905,7 +6905,11 @@ ConstraintSystem::simplifyKeyPathConstraint(
69056905
if (fnTy->getParams().size() != 1)
69066906
return false;
69076907

6908-
boundRoot = fnTy->getParams()[0].getPlainType();
6908+
// Match up the root and value types to the function's param and return
6909+
// types. Note that we're using the type of the parameter as referenced
6910+
// from inside the function body as we'll be transforming the code into:
6911+
// { root in root[keyPath: kp] }.
6912+
boundRoot = fnTy->getParams()[0].getParameterType();
69096913
boundValue = fnTy->getResult();
69106914
}
69116915

test/Constraints/keypath.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,24 @@ public extension Array {
5959
let sortedA = self.sorted(by: { $0[keyPath: keyPath] < $1[keyPath: keyPath] })
6060
return sortedA
6161
}
62+
63+
var i: Int { 0 }
64+
}
65+
66+
func takesVariadicFnWithGenericRet<T>(_ fn: (S...) -> T) {}
67+
68+
// rdar://problem/59445486
69+
func testVariadicKeypathAsFunc() {
70+
// These are okay, the base type of the KeyPath is inferred to be [S].
71+
let _: (S...) -> Int = \.i
72+
let _: (S...) -> Int = \Array.i
73+
takesVariadicFnWithGenericRet(\.i)
74+
takesVariadicFnWithGenericRet(\Array.i)
75+
76+
// These are not okay, the KeyPath should have a base that matches the
77+
// internal parameter type of the function, i.e [S].
78+
let _: (S...) -> Int = \S.i // expected-error {{key path value type 'S' cannot be converted to contextual type '[S]'}}
79+
takesVariadicFnWithGenericRet(\S.i) // expected-error {{key path value type 'S' cannot be converted to contextual type '[S]'}}
6280
}
6381

6482
// rdar://problem/54322807

test/stdlib/KeyPath.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,10 @@ keyPath.test("key path literal closures") {
968968
// Did we compute the indices once per closure construction, or once per
969969
// closure application?
970970
expectEqual(2, callsToComputeIndex)
971+
972+
// rdar://problem/59445486
973+
let variadicFn: (String...) -> Int = \.count
974+
expectEqual(3, variadicFn("a", "b", "c"))
971975
}
972976

973977
// SR-6096

0 commit comments

Comments
 (0)