Skip to content

Commit 83ebd71

Browse files
committed
Allowing forming WritableKeyPath to read-only value in Swift 3/4.
We inadvertantly allowed this in the past, so continue to do so when compiling in Swift 3/4 mode to avoid suddenly breaking existing code. The diagnostic here is pretty bad, and I've opened issues for that as well as providing some kind of deprecation warning for this so that even under Swift 3/4 mode we alert users that this is unsupported. rdar://problem/39802797
1 parent efa36ef commit 83ebd71

File tree

5 files changed

+46
-4
lines changed

5 files changed

+46
-4
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4036,8 +4036,19 @@ ConstraintSystem::simplifyKeyPathConstraint(Type keyPathTy,
40364036
// get any special power from being formed in certain contexts, such
40374037
// as the ability to assign to `let`s in initialization contexts, so
40384038
// we pass null for the DC to `isSettable` here.)
4039-
if (!storage->isSettable(nullptr)
4040-
|| !storage->isSetterAccessibleFrom(DC)) {
4039+
if (!getASTContext().isSwiftVersionAtLeast(5)) {
4040+
// As a source-compatibility measure, continue to allow
4041+
// WritableKeyPaths to be formed in the same conditions we did
4042+
// in previous releases even if we should not be able to set
4043+
// the value in this context.
4044+
if (!storage->isSettable(DC)) {
4045+
// A non-settable component makes the key path read-only, unless
4046+
// a reference-writable component shows up later.
4047+
capability = ReadOnly;
4048+
continue;
4049+
}
4050+
} else if (!storage->isSettable(nullptr)
4051+
|| !storage->isSetterAccessibleFrom(DC)) {
40414052
// A non-settable component makes the key path read-only, unless
40424053
// a reference-writable component shows up later.
40434054
capability = ReadOnly;

test/Constraints/Inputs/keypath.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class C {
2+
fileprivate(set) var i = 0
3+
}

test/Constraints/keypath.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-typecheck-verify-swift %S/Inputs/keypath.swift -primary-file %s
2+
3+
struct S {
4+
let i: Int
5+
6+
init() {
7+
let _: WritableKeyPath<S, Int> = \.i // no error for Swift 3/4
8+
}
9+
}
10+
11+
func test() {
12+
let _: WritableKeyPath<C, Int> = \.i // no error for Swift 3/4
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-typecheck-verify-swift %S/Inputs/keypath.swift -primary-file %s -swift-version 5
2+
3+
struct S {
4+
let i: Int
5+
6+
init() {
7+
let _: WritableKeyPath<S, Int> = \.i // expected-error {{type of expression is ambiguous without more context}}
8+
}
9+
}
10+
11+
func test() {
12+
let _: WritableKeyPath<C, Int> = \.i // expected-error {{type of expression is ambiguous without more context}}
13+
}

test/expr/unary/keypath/keypath.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,9 @@ struct VisibilityTesting {
514514
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
515515
expect(&yRef,
516516
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
517+
// Allow WritableKeyPath for Swift 3/4 only.
517518
expect(&zRef,
518-
toHaveType: Exactly<KeyPath<VisibilityTesting, Int>>.self)
519+
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
519520
}
520521

521522
func inPrivateContext() {
@@ -536,8 +537,9 @@ struct VisibilityTesting2 {
536537
var xRef = \VisibilityTesting.x
537538
var yRef = \VisibilityTesting.y
538539
var zRef = \VisibilityTesting.z
540+
// Allow WritableKeyPath for Swift 3/4 only.
539541
expect(&xRef,
540-
toHaveType: Exactly<KeyPath<VisibilityTesting, Int>>.self)
542+
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
541543
expect(&yRef,
542544
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
543545
expect(&zRef,

0 commit comments

Comments
 (0)