Description
Description
While there are many valid reasons to pass self
as a parameter in deinit
, it is never valid to capture it in a Task. This is discussed by @mikeash in #62191 (comment):
But capturing self with a Task or async dispatch is pretty much guaranteed to be wrong, so a warning should be doable for those specific cases.
Doing so should generate a warning.
Reproduction
@MainActor class Service {
func doThings() {}
}
@MainActor class Controller {
let service: Service
init(service: Service) { self.service = service }
func printMe() { print("Controller lives") }
deinit {
print("Controller deinit")
Task { @MainActor in
service.doThings()
}
}
}
let service = Service()
do {
let controller = Controller(service: service)
controller.printMe()
}
Expected behavior
As written, this code will crash, but no diagnostic will be printed in the deinit
. If a [service]
capture is added to the Task, then this code is fine. It is tricky for developers to understand this subtle difference (self
does not even appear in deinit
).
An ideal diagnostic would guide them to the proper capture. If no such capture can solve this, then the diagnostic should still indicate the problem.
Environment
swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
Additional information
No response