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:
+21
-13
@@ -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) })
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user