swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.25k stars 10.32k forks source link

[SR-3805] Creating a strong reference to self in a closure should warn if self is never accessed "strongly" #46390

Open swift-ci opened 7 years ago

swift-ci commented 7 years ago
Previous ID SR-3805
Radar None
Original Reporter alanf (JIRA User)
Type Improvement
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 4 | |Component/s | Compiler | |Labels | Improvement, LanguageFeatureRequest | |Assignee | None | |Priority | Medium | md5: 749bbb1e7e9a82cb5f26ca678d24746e

is duplicated by:

Issue Description:

This was discussed on the mailing list over a year ago but no proposal was made:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001197.html

class ViewControllerBase: UIViewController {
    let timer:DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue:  DispatchQueue(label: "q.q"))

    deinit {
        NSLog("deinit of \(NSStringFromClass(type(of: self)))")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        timer.scheduleRepeating(deadline: .now(), interval: .seconds(1))

        timer.setEventHandler {
            UIView.animate(withDuration: 0.2) { [weak self] in
                self?.view.backgroundColor = UIColor.green
            }
        }
}

This leaks memory in a subtle way...there is a retain loop even though self is only used in a "weak" manner. This is because the nested closure captures a strong reference for use in the closure that follows.

belkadan commented 7 years ago

Full test case in the dup.

swift-ci commented 4 years ago

Comment by Kostiantyn Herasimov (JIRA)

This also hides errors when captured instance (like a UIViewController) is deallocating inside wrong thread (like not main). It could be hard to find that cases because where is no any warning from compiler