Consider the following example:
import Foundation
func qux() { print("Q_U_X") }
func zab() { print("Z_A_B") }
class Foo: NSObject {
deinit {
qux()
}
}
class Bar: Foo {
deinit {
zab()
}
}
Code generated for Bar.deinit()
uses objc_msgSendSuper2
to call [super dealloc]
. Call finds $s3foo3FooCfDTo
(aka @objc foo.Foo.__deallocating_deinit
), which has an extra selector argument. It ignores that argument and then calls $s3foo3FooCfD
(aka foo.Foo.__deallocating_deinit
).
Why not just bypass ObjC machinery altogether and call $s3foo3FooCfD
directly?
For async deinit, FooCfD
is a thunk that creates task and runs asynchronous FooCfZ
(aka foo.Foo.__isolated_deallocating_deinit
) in that task.
So far, I've ended up with implementation where asynchronous $s3foo3BarCfZ
(already running inside a task) calls [super dealloc]
using objc_msgSendSuper2
. This calls $s3foo3FooCfDTo
, which in turn calls $s3foo3FooCfD
, which creates a new task and runs $s3foo3FooCfZ
there.
That sounds very inefficient. I want to call async $s3foo3FooCfZ
directly from async $s3foo3BarCfZ
, which is not possible (or at least hacky) using ObjC machinery.
Are there any reasons why Swift deinit need to use ObjC machinery if base class is known to be a Swift class?