Skip to content

Commit 000572d

Browse files
authored
Merge pull request swiftlang#30371 from hamishknight/insider-information
[CS] Use getParameterType for KeyPath as function
2 parents 1a3c582 + b62c9b6 commit 000572d

File tree

4 files changed

+46
-21
lines changed

4 files changed

+46
-21
lines changed

lib/Sema/CSApply.cpp

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4219,7 +4219,7 @@ namespace {
42194219
Type baseTy, leafTy;
42204220
Type exprType = cs.getType(E);
42214221
if (auto fnTy = exprType->getAs<FunctionType>()) {
4222-
baseTy = fnTy->getParams()[0].getPlainType();
4222+
baseTy = fnTy->getParams()[0].getParameterType();
42234223
leafTy = fnTy->getResult();
42244224
isFunctionType = true;
42254225
} else {
@@ -4228,12 +4228,15 @@ namespace {
42284228
leafTy = keyPathTy->getGenericArgs()[1];
42294229
}
42304230

4231+
// Track the type of the current component. Once we finish projecting
4232+
// through each component of the key path, we should reach the leafTy.
4233+
auto componentTy = baseTy;
42314234
for (unsigned i : indices(E->getComponents())) {
42324235
auto &origComponent = E->getMutableComponents()[i];
42334236

42344237
// If there were unresolved types, we may end up with a null base for
42354238
// following components.
4236-
if (!baseTy) {
4239+
if (!componentTy) {
42374240
resolvedComponents.push_back(origComponent);
42384241
continue;
42394242
}
@@ -4255,7 +4258,7 @@ namespace {
42554258
if (!foundDecl) {
42564259
// If we couldn't resolve the component, leave it alone.
42574260
resolvedComponents.push_back(origComponent);
4258-
baseTy = origComponent.getComponentType();
4261+
componentTy = origComponent.getComponentType();
42594262
continue;
42604263
}
42614264

@@ -4294,9 +4297,9 @@ namespace {
42944297
didOptionalChain = true;
42954298
// Chaining always forces the element to be an rvalue.
42964299
auto objectTy =
4297-
baseTy->getWithoutSpecifierType()->getOptionalObjectType();
4298-
if (baseTy->hasUnresolvedType() && !objectTy) {
4299-
objectTy = baseTy;
4300+
componentTy->getWithoutSpecifierType()->getOptionalObjectType();
4301+
if (componentTy->hasUnresolvedType() && !objectTy) {
4302+
objectTy = componentTy;
43004303
}
43014304
assert(objectTy);
43024305

@@ -4316,7 +4319,7 @@ namespace {
43164319
}
43174320
case KeyPathExpr::Component::Kind::Identity: {
43184321
auto component = origComponent;
4319-
component.setComponentType(baseTy);
4322+
component.setComponentType(componentTy);
43204323
resolvedComponents.push_back(component);
43214324
break;
43224325
}
@@ -4327,21 +4330,20 @@ namespace {
43274330
llvm_unreachable("already resolved");
43284331
}
43294332

4330-
// Update "baseTy" with the result type of the last component.
4333+
// Update "componentTy" with the result type of the last component.
43314334
assert(!resolvedComponents.empty());
4332-
baseTy = resolvedComponents.back().getComponentType();
4335+
componentTy = resolvedComponents.back().getComponentType();
43334336
}
43344337

43354338
// Wrap a non-optional result if there was chaining involved.
4336-
if (didOptionalChain &&
4337-
baseTy &&
4338-
!baseTy->hasUnresolvedType() &&
4339-
!baseTy->getWithoutSpecifierType()->isEqual(leafTy)) {
4339+
if (didOptionalChain && componentTy &&
4340+
!componentTy->hasUnresolvedType() &&
4341+
!componentTy->getWithoutSpecifierType()->isEqual(leafTy)) {
43404342
assert(leafTy->getOptionalObjectType()->isEqual(
4341-
baseTy->getWithoutSpecifierType()));
4343+
componentTy->getWithoutSpecifierType()));
43424344
auto component = KeyPathExpr::Component::forOptionalWrap(leafTy);
43434345
resolvedComponents.push_back(component);
4344-
baseTy = leafTy;
4346+
componentTy = leafTy;
43454347
}
43464348

43474349
// Set the resolved components, and cache their types.
@@ -4367,8 +4369,8 @@ namespace {
43674369

43684370
// The final component type ought to line up with the leaf type of the
43694371
// key path.
4370-
assert(!baseTy || baseTy->hasUnresolvedType()
4371-
|| baseTy->getWithoutSpecifierType()->isEqual(leafTy));
4372+
assert(!componentTy || componentTy->hasUnresolvedType()
4373+
|| componentTy->getWithoutSpecifierType()->isEqual(leafTy));
43724374

43734375
if (!isFunctionType)
43744376
return E;
@@ -4378,9 +4380,6 @@ namespace {
43784380
// this; we're going to change E's type to KeyPath<baseTy, leafTy> and
43794381
// then wrap it in a larger closure expression with the appropriate type.
43804382

4381-
// baseTy has been overwritten by the loop above; restore it.
4382-
baseTy = exprType->getAs<FunctionType>()->getParams()[0].getPlainType();
4383-
43844383
// Compute KeyPath<baseTy, leafTy> and set E's type back to it.
43854384
auto kpDecl = cs.getASTContext().getKeyPathDecl();
43864385
auto keyPathTy =

lib/Sema/CSSimplify.cpp

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

7422-
boundRoot = fnTy->getParams()[0].getPlainType();
7422+
// Match up the root and value types to the function's param and return
7423+
// types. Note that we're using the type of the parameter as referenced
7424+
// from inside the function body as we'll be transforming the code into:
7425+
// { root in root[keyPath: kp] }.
7426+
boundRoot = fnTy->getParams()[0].getParameterType();
74237427
boundValue = fnTy->getResult();
74247428
}
74257429

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)