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-6667] Use of WritableKeyPath on self crashes inside init method unless self is already initialized #49216

Closed
swift-ci opened this issue Dec 27, 2017 · 11 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software key paths Feature: key paths (both native and Objective-C) run-time crash Bug → crash: Swift code crashed during execution runtime The Swift Runtime

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-6667
Radar rdar://problem/36257266
Original Reporter jonathan.gilbert (JIRA User)
Type Bug
Status Resolved
Resolution Done
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, KeyPaths, RunTimeCrash, Runtime
Assignee jonathan.gilbert (JIRA)
Priority Medium

md5: 8b972e84b863fb3a33708f56175eb7bb

relates to:

  • SR-5218 private(set) should block WritableKeyPath
  • SR-6301 Creating a read-only KeyPath creates a WritableKeyPath (but still read-only)

Issue Description:

The use of WritableKeyPath on self crashes inside an init method unless self is already initialized. Put this very simplified example in the playground:

struct Foo {
let bar: Bool
init() {
let path: WritableKeyPath<Foo, Bool> = \Foo.bar // this works
self[keyPath: path] = true // crashes
}
}

let foo = Foo()

Of course our real use-case scenario is nothing similar to this basic example; we are passing arrays of key paths into the init method and iterating through them. It's very awesome but it seems non-ideal to have to specify a default value for every property (or provide a prototype to clone from).

Using var instead of let here does not help.

If ANY of the properties don't have a default value, then ALL of the WritableKeyPaths will crash – even ones that point to properties that do have default values. Also, since there is no way using reflection to determine at runtime which properties have default values and which don't, it doesn't seem like there is a workaround other than giving every property a default value.

This bug prohibits using "let" for values that you want to init with a keypath. Alone this makes it a really bad bug forcing bad compromises when using keypaths in functional programming patterns.

I hope we can find a solution to use WritableKeyPath during init. I'm not sure why it would care that the value is not initialized since we're inside an init method and therefore we should not expect it to be initialized yet.

@swift-ci
Copy link
Collaborator Author

Comment by Jonathan Gilbert (JIRA)

This relates to SR-5218 because inside an init method, or anywhere in the type itself, a keypath to a private(set) variable should be Writable.

This relates to SR-6301 because inside an init method, a keypath to a let constant should be Writable.

@belkadan
Copy link
Contributor

belkadan commented Jan 2, 2018

Since the key path doesn't know that the value is uninitialized, that probably means most of this can't work. At the very least, though, it shouldn't crash.

@jckarter, thoughts? Agreement, disagreement?

@jckarter
Copy link
Member

jckarter commented Jan 2, 2018

Sounds like DI analysis is failing to catch this. This should be a compile-time error, since you can't use `self` freely until it's fully initialized.

@jckarter
Copy link
Member

jckarter commented Jan 2, 2018

@swift-ci create

@belkadan
Copy link
Contributor

belkadan commented Jan 2, 2018

Well, even once it is fully initialized, you won't be able to execute this properly, right?

@jckarter
Copy link
Member

jckarter commented Jan 2, 2018

Why not? Once `self` is fully statically initialized, it can be used like any other value.

@belkadan
Copy link
Contributor

belkadan commented Jan 2, 2018

Yes, but bar is a let property. The compiler is allowed to optimize such that that's only written to once, right?

@jckarter
Copy link
Member

jckarter commented Jan 2, 2018

Ah, I missed that detail. We should also not allow \Foo.bar to be statically used as a WritableKeyPath, since it's only initializable, not rewritable.

@jckarter
Copy link
Member

jckarter commented Apr 7, 2018

Fix for master: #15808

@jckarter
Copy link
Member

jckarter commented Apr 9, 2018

Fix for 4.2: #15826

@jckarter
Copy link
Member

Merged. This should be fixed in future snapshots.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added the crash Bug: A crash, i.e., an abnormal termination of software label Dec 12, 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 crash Bug: A crash, i.e., an abnormal termination of software key paths Feature: key paths (both native and Objective-C) run-time crash Bug → crash: Swift code crashed during execution runtime The Swift Runtime
Projects
None yet
Development

No branches or pull requests

4 participants