mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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
This commit is contained in:
@@ -4036,8 +4036,19 @@ ConstraintSystem::simplifyKeyPathConstraint(Type keyPathTy,
|
||||
// get any special power from being formed in certain contexts, such
|
||||
// as the ability to assign to `let`s in initialization contexts, so
|
||||
// we pass null for the DC to `isSettable` here.)
|
||||
if (!storage->isSettable(nullptr)
|
||||
|| !storage->isSetterAccessibleFrom(DC)) {
|
||||
if (!getASTContext().isSwiftVersionAtLeast(5)) {
|
||||
// As a source-compatibility measure, continue to allow
|
||||
// WritableKeyPaths to be formed in the same conditions we did
|
||||
// in previous releases even if we should not be able to set
|
||||
// the value in this context.
|
||||
if (!storage->isSettable(DC)) {
|
||||
// A non-settable component makes the key path read-only, unless
|
||||
// a reference-writable component shows up later.
|
||||
capability = ReadOnly;
|
||||
continue;
|
||||
}
|
||||
} else if (!storage->isSettable(nullptr)
|
||||
|| !storage->isSetterAccessibleFrom(DC)) {
|
||||
// A non-settable component makes the key path read-only, unless
|
||||
// a reference-writable component shows up later.
|
||||
capability = ReadOnly;
|
||||
|
||||
3
test/Constraints/Inputs/keypath.swift
Normal file
3
test/Constraints/Inputs/keypath.swift
Normal file
@@ -0,0 +1,3 @@
|
||||
class C {
|
||||
fileprivate(set) var i = 0
|
||||
}
|
||||
13
test/Constraints/keypath.swift
Normal file
13
test/Constraints/keypath.swift
Normal file
@@ -0,0 +1,13 @@
|
||||
// RUN: %target-typecheck-verify-swift %S/Inputs/keypath.swift -primary-file %s
|
||||
|
||||
struct S {
|
||||
let i: Int
|
||||
|
||||
init() {
|
||||
let _: WritableKeyPath<S, Int> = \.i // no error for Swift 3/4
|
||||
}
|
||||
}
|
||||
|
||||
func test() {
|
||||
let _: WritableKeyPath<C, Int> = \.i // no error for Swift 3/4
|
||||
}
|
||||
13
test/Constraints/keypath_swift_5.swift
Normal file
13
test/Constraints/keypath_swift_5.swift
Normal file
@@ -0,0 +1,13 @@
|
||||
// RUN: %target-typecheck-verify-swift %S/Inputs/keypath.swift -primary-file %s -swift-version 5
|
||||
|
||||
struct S {
|
||||
let i: Int
|
||||
|
||||
init() {
|
||||
let _: WritableKeyPath<S, Int> = \.i // expected-error {{type of expression is ambiguous without more context}}
|
||||
}
|
||||
}
|
||||
|
||||
func test() {
|
||||
let _: WritableKeyPath<C, Int> = \.i // expected-error {{type of expression is ambiguous without more context}}
|
||||
}
|
||||
@@ -514,8 +514,9 @@ struct VisibilityTesting {
|
||||
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
|
||||
expect(&yRef,
|
||||
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
|
||||
// Allow WritableKeyPath for Swift 3/4 only.
|
||||
expect(&zRef,
|
||||
toHaveType: Exactly<KeyPath<VisibilityTesting, Int>>.self)
|
||||
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
|
||||
}
|
||||
|
||||
func inPrivateContext() {
|
||||
@@ -536,8 +537,9 @@ struct VisibilityTesting2 {
|
||||
var xRef = \VisibilityTesting.x
|
||||
var yRef = \VisibilityTesting.y
|
||||
var zRef = \VisibilityTesting.z
|
||||
// Allow WritableKeyPath for Swift 3/4 only.
|
||||
expect(&xRef,
|
||||
toHaveType: Exactly<KeyPath<VisibilityTesting, Int>>.self)
|
||||
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
|
||||
expect(&yRef,
|
||||
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
|
||||
expect(&zRef,
|
||||
|
||||
Reference in New Issue
Block a user