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-5689] Can't append KeyPath when lhs value is optional #48259

Open
mdiep opened this issue Aug 15, 2017 · 5 comments
Open

[SR-5689] Can't append KeyPath when lhs value is optional #48259

mdiep opened this issue Aug 15, 2017 · 5 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@mdiep
Copy link
Contributor

mdiep commented Aug 15, 2017

Previous ID SR-5689
Radar None
Original Reporter @mdiep
Type Bug
Environment

Xcode 9.0.0 ß5
Apple Swift version 4.0 (swiftlang-900.0.59 clang-900.0.34.2)
Target: x86_64-apple-macosx10.9

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: c160af841d3bf69ec27401edfd434563

Issue Description:

This code doesn't work:

struct A {
    var b: B?
}

struct B {
    var c: Int
}

let ab1 = \A.b?.c

let a = \A.b
let b = \B.c
let ab2: KeyPath<A, Int?> = a.appending(path: b)

It yields this error:

error: MyPlayground.playground:7:47: error: cannot convert value of type 'WritableKeyPath<B, Int>' to expected argument type 'KeyPath<B?, Int?>'
let ab2: KeyPath<A, Int?> = a.appending(path: b)
                                              ^

There doesn't be any way to append b to a to recreate ab1.

It's not just type inference. Attempting this with AnyKeyPath results in a nil value.

let a: AnyKeyPath = \A.b
let b: AnyKeyPath = \B.c
let ab2: AnyKeyPath = a.appending(path: b)!
@belkadan
Copy link
Contributor

@jckarter, there's already a bug for this, right?

@jckarter
Copy link
Member

This is as currently designed. KeyPaths aren't covariant, and appending only succeeds when the root type of the RHS matches the value type of the LHS exactly. With subscript support you would be able to write \A.[keyPath: a]?[keyPath: b] to chain these paths together.

@mdiep
Copy link
Contributor Author

mdiep commented Aug 15, 2017

What I'm really interested in is breaking ab1 into its parts, a and b.

Since there's not currently possible, I enumerate all the available KeyPaths and append them to find which combination combines to make ab1. But the inability to append these leaves me in a real pickle.

It seems like I should be able to append these two things, even without proper covariance. The inability to create ab2 from its parts is a real shortcoming.

@jckarter
Copy link
Member

If you want to break key paths into their components, that's something I feel key paths ought to eventually support directly. The object layout is not finalized, but the current layout is described here, which might allow you to experiment ahead of our ability to design proper APIs for this: https://github.com/apple/swift/blob/master/docs/ABI/KeyPaths.md Optional chains are fundamentally somewhat special because, as key path components, they have non-local influence over the behavior of the entire following chain, since it short-circuits further evaluation if the component is nil.

@swift-ci
Copy link
Collaborator

Comment by Helge Heß (JIRA)

Since I'm also interested in this kind of stuff for ZeeQL, I started to try the decoding thing. I didn't finish it because I noticed it is not quite what I want (the string names of the path). But in the case someone wants to play with the (completely unfinished, super hacky, probably quite incorrect) thing: https://gist.github.com/helje5/e5e6e50af60d0ee62169ac815f60d6d3

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
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
Projects
None yet
Development

No branches or pull requests

4 participants