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-6301] Creating a read-only KeyPath creates a WritableKeyPath (but still read-only) #48851

Closed
ole opened this issue Nov 5, 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

@ole
Copy link
Contributor

ole commented Nov 5, 2017

Previous ID SR-6301
Radar rdar://problem/31768978
Original Reporter @ole
Type Bug
Status Resolved
Resolution Done
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, KeyPaths
Assignee None
Priority Medium

md5: daca61aaec27b11a3fc4299bb7b7071f

relates to:

  • SR-5218 private(set) should block WritableKeyPath
  • SR-6502 WritableKeyPath allows writing to immutable properties
  • SR-6667 Use of WritableKeyPath on self crashes inside init method unless self is already initialized

Issue Description:

Maybe I'm not understanding something, but this puzzles me (Swift 4.0, Xcode 9.1).

I'm creating a `KeyPath` in the REPL:

> swift
Welcome to Apple Swift version 4.0 (swiftlang-900.0.65.1 clang-900.0.37). Type :help for assistance.
  1> struct Person {
  2.     let name: String
  3. }

  4> let nameKeyPath = \Person.name
nameKeyPath: WritableKeyPath<Person, String> = {
  Swift.KeyPath = {
    Swift.PartialKeyPath = {
      Swift.AnyKeyPath = {
        _kvcKeyPathStringPtr = nil
      }
    }
  }
}

  5> type(of: nameKeyPath)
$R0: KeyPath<Person, String>.Type = WritableKeyPath<Person, String>

  6> String(describing: nameKeyPath)
$R1: String = "Swift.WritableKeyPath<__lldb_expr_1.Person, Swift.String>"

Person.name is a constant, so I'd assume that \Person.name produces a `KeyPath`. And this is indeed what happens, but when I print the key path's description or dump it, the word "WritableKeyPath" appears in several places.

What's the relationship between WritableKeyPath and KeyPath? Why does String(describing: nameKeyPath) say it's a "WritableKeyPath"?

Here's my environment:

> radar-version.sh
ProductName:    Mac OS X
ProductVersion: 10.13
BuildVersion:   17A405
---
Xcode 9.1
Build version 9B55
---
Apple Swift version 4.0 (swiftlang-900.0.65.2 clang-900.0.37)
Target: x86_64-apple-macosx10.9
@belkadan
Copy link
Contributor

belkadan commented Nov 6, 2017

Static type, dynamic type, but since you're in the REPL you can see both. FWIW I'm still uncomfortable with this as well.

cc @jckarter

@jckarter
Copy link
Member

jckarter commented Nov 6, 2017

We don't have any runtime information that distinguishes `let` properties from `var` properties yet, so the key path runtime always produces a WritableKeyPath dynamically.

@ole
Copy link
Contributor Author

ole commented Nov 6, 2017

Thanks for the explanation, I didn't know that.

@ole
Copy link
Contributor Author

ole commented Mar 27, 2020

@jckarter I'm retesting this in Swift 5.2 and the problem seems to be gone. Can you confirm that this is resolved?

This is what I'm seeing in the Swift 5.2 REPL:

> swift
Welcome to Apple Swift version 5.2 (swiftlang-1103.0.32.1 clang-1103.0.32.29).
Type :help for assistance.
  1> struct Person {
  2.   let name: String
  3. }
  4> let nameKeyPath = \Person.name
nameKeyPath: KeyPath<Person, String> = {
  Swift.PartialKeyPath = {
    Swift.AnyKeyPath = {}
  }
}
  5> type(of: nameKeyPath)
$R0: KeyPath<Person, String>.Type = KeyPath<Person, String>
  6> String(describing: nameKeyPath)
$R1: String = "Swift.KeyPath<__lldb_expr_1.Person, Swift.String>"
  7> dump(nameKeyPath)
- Swift.KeyPath<__lldb_expr_1.Person, Swift.String> #&#8203;0
  - super: Swift.PartialKeyPath<__lldb_expr_1.Person>
    ▿ super: Swift.AnyKeyPath
      - _kvcKeyPathStringPtr: nil
$R2: KeyPath<Person, String> = {
  Swift.PartialKeyPath = {
    Swift.AnyKeyPath = {}
  }
}

@jckarter
Copy link
Member

Yeah, building with a Swift 5 compiler and running with a Swift 5 runtime, a key path that refers to a `let` property ought to be both statically and dynamically read-only.

@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