Skip to content

Commit 5207b0e

Browse files
authored
Merge pull request #84287 from xedin/issue-84150
[CSSimplify] Fix key path to function conversion to check key path re…
2 parents cfe9f90 + ac27f53 commit 5207b0e

File tree

3 files changed

+46
-4
lines changed

3 files changed

+46
-4
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,14 @@ ValueDecl *RequirementFailure::getDeclRef() const {
411411
}
412412
}
413413

414+
// If this is a key path to function conversion, the requirements come
415+
// from a key path type implicitly formed by the solver.
416+
if (isExpr<KeyPathExpr>(getRawAnchor()) &&
417+
getLocator()->isFirstElement<LocatorPathElt::KeyPathType>() &&
418+
getOwnerType()->is<FunctionType>()) {
419+
return getASTContext().getKeyPathDecl();
420+
}
421+
414422
return getAffectedDeclFromType(getOwnerType());
415423
}
416424

lib/Sema/CSSimplify.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12982,8 +12982,29 @@ ConstraintSystem::simplifyKeyPathConstraint(
1298212982
auto paramFnTy = FunctionType::get(paramParam, fnTy->getResult(),
1298312983
fnTy->getExtInfo());
1298412984

12985+
// Form a key path type as well to make sure that root and value
12986+
// types satisfy all of its requirements.
12987+
// Note that `KeyPath` types used to have no requirements but now
12988+
// they do require `Root` and `Value` to be `Copyable` and `Escapable`.
12989+
{
12990+
auto keyPathTy =
12991+
openUnboundGenericType(
12992+
getASTContext().getKeyPathDecl(),
12993+
/*parent=*/Type(),
12994+
locator.withPathElement(LocatorPathElt::KeyPathType()),
12995+
/*isTypeResolution=*/false)
12996+
->castTo<BoundGenericType>();
12997+
addConstraint(ConstraintKind::Bind, keyPathTy->getGenericArgs()[0],
12998+
rootTy,
12999+
locator.withPathElement(LocatorPathElt::KeyPathRoot()));
13000+
addConstraint(ConstraintKind::Bind, keyPathTy->getGenericArgs()[1],
13001+
valueTy,
13002+
locator.withPathElement(LocatorPathElt::KeyPathValue()));
13003+
}
13004+
1298513005
return !matchTypes(kpFnTy, paramFnTy, ConstraintKind::Conversion,
12986-
subflags, locator).isFailure();
13006+
subflags, locator)
13007+
.isFailure();
1298713008
}
1298813009

1298913010
assert(contextualRootTy && contextualValueTy);

test/Sema/keypaths_noncopyable.swift

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ public func testKeypath<V: ~Copyable>(m: consuming M<V>) {
5353
// expected-error@-1 {{key path cannot refer to noncopyable type 'M<V>'}}
5454

5555
let b = Box(NC())
56-
_ = b.with(\.data)
57-
_ = b.with(\.next)
58-
_ = b.with(\.next?.wrapped) // expected-error {{key path cannot refer to noncopyable type 'NC'}}
56+
_ = b.with(\.data) // expected-error {{key path cannot refer to noncopyable type 'NC'}}
57+
_ = b.with(\.next) // expected-error {{key path cannot refer to noncopyable type 'NC'}}
58+
_ = b.with(\.next?.wrapped) // expected-error 2 {{key path cannot refer to noncopyable type 'NC'}}
5959
_ = b.with(\.next!.wrapped.data) // expected-error {{key path cannot refer to noncopyable type 'NC'}}
6060
}
6161

@@ -68,3 +68,16 @@ func testAsFunc(_ someA: A) -> Int {
6868
let fn: (A) -> Int = \A.b.c.d // expected-error {{key path cannot refer to noncopyable type 'B'}}
6969
return fn(someA)
7070
}
71+
72+
// https://github.com/swiftlang/swift/issues/84150
73+
func testKeyPathToFunctionConversion() {
74+
struct HasID: ~Copyable {
75+
let id: Int
76+
}
77+
78+
func map(_ operation: (consuming HasID) -> Int) {}
79+
80+
map(\.id) // expected-error {{key path cannot refer to noncopyable type 'HasID'}}
81+
82+
let _: (consuming HasID) -> Int = \.id // expected-error {{key path cannot refer to noncopyable type 'HasID'}}
83+
}

0 commit comments

Comments
 (0)