codeql icon indicating copy to clipboard operation
codeql copied to clipboard

Kotlin: implement default interface forwarding

Open smowton opened this issue 3 years ago • 0 comments
trafficstars

Kotlin's implementation of defaults depends on the -Xjvm-default setting (or the @JvmDefault deprecated annotation, not implemented here): by default, actual interface class files don't use default methods, and any class that would inherit one instead implements the interface calling a static method defined on TheInterface$DefaultImpls. With -Xjvm-default=all or =all-compatibility, real interface default methods are emitted, with the latter retaining the DefaultImpls methods so that other Kotlin can use it.

Here I adopt a hybrid solution: create a real default method implementation, but also emit a forwarding method like @override int f(int x) { return super.TheInterface.f(x); }, because the Java extractor will see MyClass.f in the emitted class file and try to dispatch directly to it. The only downside is that we emit a default interface method body for a prototype that will appear to be abstract to the Java extractor and which it will extract as such. I work around this by tolerating the combination default abstract in QL. The alternative would be to fully mimic the DefaultImpls approach, giving 100% fidelity to kotlinc's strategy and therefore no clash with the Java extractor's view of the world.

This is currently based on https://github.com/github/codeql/pull/9811

smowton avatar Jul 21 '22 08:07 smowton