Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-6502] WritableKeyPath allows writing to immutable properties #49052

Closed
swift-ci opened this issue Nov 29, 2017 · 5 comments
Closed

[SR-6502] WritableKeyPath allows writing to immutable properties #49052

swift-ci opened this issue Nov 29, 2017 · 5 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself key paths Feature: key paths (both native and Objective-C)

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-6502
Radar rdar://problem/35773760
Original Reporter pritesh-eb (JIRA User)
Type Bug
Status Resolved
Resolution Done
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, KeyPaths
Assignee pritesh-eb (JIRA)
Priority Medium

md5: 9167219e12ed0523b5aef349c7018e24

is duplicated by:

  • SR-9452 KeyPaths allow mutating a "let" constant
  • SR-10001 Swift 4.0 WritableKeyPath change Immutable value

relates to:

  • SR-6301 Creating a read-only KeyPath creates a WritableKeyPath (but still read-only)

Issue Description:

struct User {
    let firstName: String
    let lastName: String
    
    func changed<A>(keyPath readOnlyKeyPath: KeyPath<User, A>, newValue: A) -> User {
        guard let writeableKeyPath = readOnlyKeyPath as? WritableKeyPath<User, A> else { return self }
        var modified = self
        modified[keyPath: writeableKeyPath] = newValue
        
        return modified
    }
}

let jane = User(firstName: "Jane", lastName: "Doe")
jane.changed(keyPath: \.firstName, newValue: "Stacy").firstName // returns "Stacy"

// More generally

let firstNameKP = \User.firstName
if let writeableFirstNameKP = firstNameKP as? WritableKeyPath<User, String> {
    print(writeableFirstNameKP) // the cast always succeeds and this print statement always gets executed
}

I was expecting the guard statement to fail and prevent me from writing to the immutable property, but it doesn't.

Is this a bug or the intended behavior? I was skeptical of using this approach as if it's a bug it might break my code in future versions of Swift.

@belkadan
Copy link
Contributor

Definitely a bug. A property declared with let should not get a WritableKeyPath; you have to replace the whole value.

@swift-ci create

@swift-ci
Copy link
Collaborator Author

Comment by Jonathan Gilbert (JIRA)

@belkadan a `let` should get a WritableKeyPath during initialization, inside the init method, but not anytime else. Please don't break that behavior at least.

@jckarter
Copy link
Member

Fix for master: #18768

jonathan.gilbert (JIRA User) there's no way to prevent a key path taken in an initialization context from being passed out and used later, and key paths can only even be applied to objects that are already fully initialized, since initialization checking does not dynamic modifications such as those through key paths.

@jckarter
Copy link
Member

Merged. Should be fixed in future master snapshots.

@AnnaZaks
Copy link
Mannequin

AnnaZaks mannequin commented Jul 23, 2019

pritesh-eb (JIRA User), Could you verify if the problem is fixed and if so move the JIRA to "Closed"?

Thanks!
Anna

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself key paths Feature: key paths (both native and Objective-C)
Projects
None yet
Development

No branches or pull requests

3 participants