-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Description
| Previous ID | SR-3636 |
| Radar | rdar://problem/30066053 |
| Original Reporter | @mayoff |
| Type | Bug |
Attachment: Download
Environment
Crashes with Xcode 8.2.1 toolchain, and also with Swift development snapshot 2017-01-05 for Xcode.
Additional Detail from JIRA
| Votes | 2 |
| Component/s | Compiler |
| Labels | Bug |
| Assignee | None |
| Priority | Medium |
md5: 178de470313241a40fd1800eb932d1b2
Issue Description:
Consider this member of NSKeyedUnarchiverDelegate:
- (nullable id)unarchiver:(NSKeyedUnarchiver *)unarchiver didDecodeObject:(nullable id) NS_RELEASES_ARGUMENT object NS_RETURNS_RETAINED;
It should release or autorelease the object argument, and retain the returned object.
The attached program implements this method in Swift. The attached program crashes; just run swift main.swift.
The compiler generates an objc-compatible unarchiver:didDecodeObject: method to conform to the NSKeyedUnarchiverDelegate method.
The generated objc method wraps the Swift method UnarchiverDelegate.unarchiver (_: NSKeyedUnarchiver, didDecode: Any?) -> Any?. The objc method bridges the incoming (nullable id) object to a Swift Any?, and also bridges the returned Swift Any? to nullable id.
The objc method is supposed to consume a +1 retain count on the incoming object and deliver a +1 retain count on the outgoing object. However, it appears that the generated code does the opposite, because the incoming Placeholder ends up leaked, and the outgoing RealDeal ends up over-released, causing a crash.
The attached program contains two commented-out lines that experimentally verify the above hypothesis. If you uncomment the passRetained line, the program no longer crashes. The RealDeal is correctly deallocated and not over-released. If you also uncomment the autorelease line, the Placeholder is correctly deallocated but not over-released.