KT-30419 Box inline classes in return types of covariant overrides

Use boxed version of an inline class in return type position for
covariant and generic-specialized overrides.

Also fixes KT-35234 and KT-31585.
This commit is contained in:
Dmitry Petrov
2020-03-30 12:41:48 +03:00
parent e44f12d7b0
commit 24b8495e00
31 changed files with 1296 additions and 68 deletions
@@ -18,15 +18,16 @@ package org.jetbrains.kotlin.backend.common.bridges
import org.jetbrains.kotlin.utils.DFS
import java.util.*
import kotlin.collections.LinkedHashMap
interface FunctionHandle {
val isDeclaration: Boolean
val isAbstract: Boolean
/** On finding concrete super declaration we should distinguish non-abstract java8/js default methods from
* class ones (see [findConcreteSuperDeclaration] method in bridges.kt).
* Note that interface methods with body compiled to jvm 8 target are assumed to be non-abstract in bridges method calculation
* (more details in [DescriptorBasedFunctionHandle.isBodyOwner] comment).*/
* class ones (see [findConcreteSuperDeclaration] method in bridges.kt).
* Note that interface methods with body compiled to jvm 8 target are assumed to be non-abstract in bridges method calculation
* (more details in [DescriptorBasedFunctionHandle.isBodyOwner] comment).*/
val mayBeUsedAsSuperImplementation: Boolean
fun getOverridden(): Iterable<FunctionHandle>
@@ -34,18 +35,19 @@ interface FunctionHandle {
val mightBeIncorrectCode: Boolean get() = false
}
data class Bridge<out Signature>(
val from: Signature,
val to: Signature
data class Bridge<out Signature, out Function : FunctionHandle>(
val from: Signature,
val to: Signature,
val originalFunctions: Set<Function>
) {
override fun toString() = "$from -> $to"
}
fun <Function : FunctionHandle, Signature> generateBridges(
function: Function,
signature: (Function) -> Signature
): Set<Bridge<Signature>> {
function: Function,
signature: (Function) -> Signature
): Set<Bridge<Signature, Function>> {
// If it's an abstract function, no bridges are needed: when an implementation will appear in some concrete subclass, all necessary
// bridges will be generated there
if (function.isAbstract) return setOf()
@@ -58,7 +60,7 @@ fun <Function : FunctionHandle, Signature> generateBridges(
val implementation = findConcreteSuperDeclaration(function) ?: return setOf()
val bridgesToGenerate = findAllReachableDeclarations(function).mapTo(LinkedHashSet<Signature>(), signature)
val bridgesToGenerate = findAllReachableDeclarations(function).groupByTo(LinkedHashMap(), signature)
if (fake) {
// If it's a concrete fake override, some of the bridges may be inherited from the super-classes. Specifically, bridges for all
@@ -67,14 +69,20 @@ fun <Function : FunctionHandle, Signature> generateBridges(
@Suppress("UNCHECKED_CAST")
for (overridden in function.getOverridden() as Iterable<Function>) {
if (!overridden.isAbstract) {
bridgesToGenerate.removeAll(findAllReachableDeclarations(overridden).map(signature))
for (reachable in findAllReachableDeclarations(overridden)) {
bridgesToGenerate.remove(signature(reachable))
}
}
}
}
val method = signature(implementation)
bridgesToGenerate.remove(method)
return bridgesToGenerate.map { Bridge(it, method) }.toSet()
return bridgesToGenerate.entries
.map { (overriddenSignature, overriddenFunctions) ->
Bridge(overriddenSignature, method, overriddenFunctions.toSet())
}
.toSet()
}
fun <Function : FunctionHandle> findAllReachableDeclarations(function: Function): MutableSet<Function> {
@@ -95,7 +103,7 @@ fun <Function : FunctionHandle> findAllReachableDeclarations(function: Function)
* The implementation is guaranteed to exist because if it wouldn't, the given function would've been abstract
*/
fun <Function : FunctionHandle> findConcreteSuperDeclaration(function: Function): Function? {
require(!function.isAbstract, { "Only concrete functions have implementations: $function" })
require(!function.isAbstract) { "Only concrete functions have implementations: $function" }
if (function.isDeclaration) return function
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
fun <Signature> generateBridgesForFunctionDescriptor(
descriptor: FunctionDescriptor,
signature: (FunctionDescriptor) -> Signature
): Set<Bridge<Signature>> {
): Set<Bridge<Signature, DescriptorBasedFunctionHandle>> {
return generateBridges(DescriptorBasedFunctionHandle(descriptor), { signature(it.descriptor) })
}