[IR] Fixed fake override builder for lowerings

This commit is contained in:
Igor Chevdar
2020-09-04 22:26:12 +05:00
parent 7f4bda0d52
commit e39ce91253
13 changed files with 167 additions and 141 deletions
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildReceiverParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildTypeParameter
import org.jetbrains.kotlin.ir.declarations.*
@@ -25,8 +24,11 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
@@ -438,63 +440,41 @@ val IrFunction.allParameters: List<IrValueParameter>
explicitParameters
}
fun IrClass.addFakeOverridesViaIncorrectHeuristic(implementedMembers: List<IrSimpleFunction> = emptyList()) {
fun IrDeclaration.toList() = when (this) {
is IrSimpleFunction -> listOf(this)
is IrProperty -> listOfNotNull(getter, setter)
else -> emptyList()
private object FakeOverrideBuilder : FakeOverrideBuilderStrategy() {
override fun linkFakeOverride(fakeOverride: IrOverridableMember) {
when (fakeOverride) {
is IrFakeOverrideFunction -> linkFunctionFakeOverride(fakeOverride)
is IrFakeOverrideProperty -> linkPropertyFakeOverride(fakeOverride)
else -> error("Unexpected fake override: $fakeOverride")
}
}
val overriddenFunctions = (declarations + implementedMembers)
.flatMap { it.toList() }
.flatMap { it.overriddenSymbols.map { it.owner } }
.toSet()
val unoverriddenSuperFunctions = superTypes
.map { it.getClass()!! }
.flatMap { irClass ->
irClass.declarations
.flatMap { it.toList() }
.filter { it !in overriddenFunctions }
.filter { it.visibility != DescriptorVisibilities.PRIVATE }
}
.toMutableSet()
// TODO: A dirty hack.
val groupedUnoverriddenSuperFunctions = unoverriddenSuperFunctions.groupBy { it.name.asString() + it.allParameters.size }
fun createFakeOverride(overriddenFunctions: List<IrSimpleFunction>) =
overriddenFunctions.first().let { irFunction ->
irFunction.factory.buildFun {
origin = IrDeclarationOrigin.FAKE_OVERRIDE
name = irFunction.name
visibility = DescriptorVisibilities.PUBLIC
modality = irFunction.modality
returnType = irFunction.returnType
isInline = irFunction.isInline
isExternal = irFunction.isExternal
isTailrec = irFunction.isTailrec
isSuspend = irFunction.isSuspend
isOperator = irFunction.isOperator
isInfix = irFunction.isInfix
isExpect = irFunction.isExpect
isFakeOverride = true
}.apply {
parent = this@addFakeOverridesViaIncorrectHeuristic
overriddenSymbols = overriddenFunctions.map { it.symbol }
copyParameterDeclarationsFrom(irFunction)
copyAttributes(irFunction)
}
}
val fakeOverriddenFunctions = groupedUnoverriddenSuperFunctions
.asSequence()
.associate { it.value.first() to createFakeOverride(it.value) }
.toMutableMap()
for (fo in fakeOverriddenFunctions.values) {
addChild(fo)
private fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction) {
declaration.acquireSymbol(IrSimpleFunctionSymbolImpl(WrappedSimpleFunctionDescriptor()))
}
private fun linkPropertyFakeOverride(declaration: IrFakeOverrideProperty) {
val propertySymbol = IrPropertySymbolImpl(WrappedPropertyDescriptor())
declaration.getter?.let { it.correspondingPropertySymbol = propertySymbol }
declaration.setter?.let { it.correspondingPropertySymbol = propertySymbol }
declaration.acquireSymbol(propertySymbol)
declaration.getter?.let {
it.correspondingPropertySymbol = declaration.symbol
linkFunctionFakeOverride(it as? IrFakeOverrideFunction ?: error("Unexpected fake override getter: $it"))
}
declaration.setter?.let {
it.correspondingPropertySymbol = declaration.symbol
linkFunctionFakeOverride(it as? IrFakeOverrideFunction ?: error("Unexpected fake override setter: $it"))
}
}
}
fun IrClass.addFakeOverrides(irBuiltIns: IrBuiltIns, implementedMembers: List<IrOverridableMember> = emptyList()) {
IrOverridingUtil(irBuiltIns, FakeOverrideBuilder)
.buildFakeOverridesForClassUsingOverriddenSymbols(this, implementedMembers)
.forEach { addChild(it) }
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
@@ -354,7 +354,7 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
}
coroutineClass.superTypes += superTypes
coroutineClass.addFakeOverridesViaIncorrectHeuristic()
coroutineClass.addFakeOverrides(context.irBuiltIns)
initializeStateMachine(coroutineConstructors, coroutineClassThis)
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.ir.addFakeOverridesViaIncorrectHeuristic
import org.jetbrains.kotlin.backend.common.ir.addFakeOverrides
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
@@ -225,7 +225,7 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
if (superType.needEqualsHashCodeMethods)
generateEqualsHashCode(subclass, superType, field)
subclass.addFakeOverridesViaIncorrectHeuristic()
subclass.addFakeOverrides(context.irBuiltIns)
return subclass
}
@@ -5,9 +5,8 @@
package org.jetbrains.kotlin.backend.common.lower.inline
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DescriptorsToIrRemapper
import org.jetbrains.kotlin.backend.common.WrappedDescriptorPatcher
import org.jetbrains.kotlin.ir.util.DescriptorsToIrRemapper
import org.jetbrains.kotlin.ir.util.WrappedDescriptorPatcher
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
@@ -438,7 +438,7 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
coroutineClass.superTypes += coroutineBaseClass.defaultType
}
coroutineClass.addFakeOverridesViaIncorrectHeuristic(implementedMembers)
coroutineClass.addFakeOverrides(context.irBuiltIns, implementedMembers)
// TODO: find out whether Kotlin/Native needs this call
initializeStateMachine(listOf(coroutineConstructor), coroutineClassThis)
@@ -221,7 +221,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
generateSamEqualsHashCodeMethods(boundReceiverVar)
}
if (isKotlinFunInterface) {
functionReferenceClass.addFakeOverridesViaIncorrectHeuristic()
functionReferenceClass.addFakeOverrides(context.irBuiltIns)
}
+functionReferenceClass
@@ -1,7 +1,12 @@
package org.jetbrains.kotlin.backend.common.overrides
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
import org.jetbrains.kotlin.backend.common.DescriptorsToIrRemapper
import org.jetbrains.kotlin.backend.common.WrappedDescriptorPatcher
package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.ir.util.DescriptorsToIrRemapper
import org.jetbrains.kotlin.ir.util.WrappedDescriptorPatcher
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
@@ -84,10 +89,14 @@ class DeepCopyIrTreeWithSymbolsForFakeOverrides(typeArguments: Map<IrTypeParamet
}
}
private val symbolRemapper = FakeOverrideSymbolRemapperImpl(typeArguments, DescriptorsToIrRemapper)
private val copier = FakeOverrideCopier(
symbolRemapper,
FakeOverrideTypeRemapper(symbolRemapper, typeArguments),
SymbolRenamer.DEFAULT
private val symbolRemapper =
FakeOverrideSymbolRemapperImpl(
typeArguments,
DescriptorsToIrRemapper
)
private val copier = FakeOverrideCopier(
symbolRemapper,
FakeOverrideTypeRemapper(symbolRemapper, typeArguments),
SymbolRenamer.DEFAULT
)
}
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.overrides
package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.*
@@ -1,20 +1,9 @@
/*
* Copyright 2010-2020 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.overrides
package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.Modality
@@ -22,27 +11,54 @@ import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrDynamicType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.descriptors.WrappedPropertyDescriptor
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.isReal
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.incompatible
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.types.Variance
interface FakeOverrideBuilderStrategy {
fun fakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember
abstract class FakeOverrideBuilderStrategy {
open fun fakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember{
require(superType is IrSimpleType) { "superType is $superType, expected IrSimpleType" }
val classifier = superType.classifier
require(classifier is IrClassSymbol) { "superType classifier is not IrClassSymbol: $classifier" }
val typeParameters = extractTypeParameters(classifier.owner)
val superArguments = superType.arguments
assert(typeParameters.size == superArguments.size) {
"typeParameters = $typeParameters size != typeArguments = $superArguments size "
}
val substitutionMap = mutableMapOf<IrTypeParameterSymbol, IrType>()
for (i in typeParameters.indices) {
val tp = typeParameters[i]
val ta = superArguments[i]
require(ta is IrTypeProjection) { "Unexpected super type argument: $ta @ $i" }
assert(ta.variance == Variance.INVARIANT) { "Unexpected variance in super type argument: ${ta.variance} @$i" }
substitutionMap[tp.symbol] = ta.type
}
val copier = DeepCopyIrTreeWithSymbolsForFakeOverrides(substitutionMap)
val deepCopyFakeOverride = copier.copy(member, clazz) as IrOverridableMember
deepCopyFakeOverride.parent = clazz
return deepCopyFakeOverride
}
// TODO: this one doesn't belong here. IrOverridingUtil shouldn't know about symbol table.
fun linkFakeOverride(fakeOverride: IrOverridableMember)
abstract fun linkFakeOverride(fakeOverride: IrOverridableMember)
// TODO: need to make IrProperty carry overriddenSymbols.
val propertyOverriddenSymbols: MutableMap<IrOverridableMember, List<IrSymbol>>
val propertyOverriddenSymbols: MutableMap<IrOverridableMember, List<IrSymbol>> = mutableMapOf()
}
// TODO:
@@ -127,6 +143,45 @@ class IrOverridingUtil(
}
}
fun buildFakeOverridesForClassUsingOverriddenSymbols(
clazz: IrClass,
implementedMembers: List<IrOverridableMember> = emptyList()
): List<IrOverridableMember> {
fakeOverrideBuilder.propertyOverriddenSymbols.clear()
val overriddenMembers = (clazz.declarations.filterIsInstance<IrOverridableMember>() + implementedMembers)
.flatMap {
when (it) {
is IrSimpleFunction -> it.overriddenSymbols.map { it.owner }
is IrProperty -> (it.getter ?: it.setter)?.overriddenSymbols
?.map { it.owner.correspondingPropertySymbol!!.owner }
?: emptyList()
else -> error("Unexpected IrOverridableMember: $it")
}
}
.toSet()
val unoverriddenSuperMembers = clazz.superTypes.flatMap { superType ->
val superClass = superType.getClass() ?: error("Unexpected super type: $superType")
superClass.declarations
.filterIsInstance<IrOverridableMember>()
.filter { it !in overriddenMembers }
.map { overridenMember ->
val fakeOverride = fakeOverrideBuilder.fakeOverrideMember(superType, overridenMember, clazz)
originals[fakeOverride] = overridenMember
originalSuperTypes[fakeOverride] = superType
fakeOverride
}
}
val unoverriddenSuperMembersGroupedByName = unoverriddenSuperMembers.groupBy { it.name }
val fakeOverrides = mutableListOf<IrOverridableMember>()
for (group in unoverriddenSuperMembersGroupedByName.values) {
createAndBindFakeOverrides(clazz, group, fakeOverrides)
}
return fakeOverrides
}
private fun generateOverridesInFunctionGroup(
membersFromSupertypes: List<IrOverridableMember>,
membersFromCurrent: List<IrOverridableMember>,
@@ -139,7 +194,9 @@ class IrOverridingUtil(
notOverridden.removeAll(bound)
}
createAndBindFakeOverrides(current, notOverridden)
val addedFakeOverrides = mutableListOf<IrOverridableMember>()
createAndBindFakeOverrides(current, notOverridden, addedFakeOverrides)
current.declarations.addAll(addedFakeOverrides)
}
private fun extractAndBindOverridesForMember(
@@ -150,7 +207,8 @@ class IrOverridingUtil(
val overridden = mutableSetOf<IrOverridableMember>()
for (fromSupertype in descriptorsFromSuper) {
val result = isOverridableBy(fromSupertype, fromCurrent/*, current*/).result
val isVisibleForOverride = isVisibleForOverride(fromCurrent, fromSupertype.original)
val isVisibleForOverride =
isVisibleForOverride(fromCurrent, fromSupertype.original)
when (result) {
OverrideCompatibilityInfo.Result.OVERRIDABLE -> {
if (isVisibleForOverride) {
@@ -178,7 +236,8 @@ class IrOverridingUtil(
private fun createAndBindFakeOverrides(
current: IrClass,
notOverridden: Collection<IrOverridableMember>
notOverridden: Collection<IrOverridableMember>,
addedFakeOverrides: MutableList<IrOverridableMember>
) {
val fromSuper = notOverridden.toMutableSet()
while (fromSuper.isNotEmpty()) {
@@ -187,7 +246,7 @@ class IrOverridingUtil(
notOverriddenFromSuper,
fromSuper
)
createAndBindFakeOverride(overridables, current)
createAndBindFakeOverride(overridables, current, addedFakeOverrides)
}
}
@@ -292,7 +351,8 @@ class IrOverridingUtil(
private fun createAndBindFakeOverride(
overridables: Collection<IrOverridableMember>,
current: IrClass
current: IrClass,
addedFakeOverrides: MutableList<IrOverridableMember>
) {
val effectiveOverridden = filterVisibleFakeOverrides(overridables)
@@ -327,7 +387,7 @@ class IrOverridingUtil(
) { "Overridden symbols should be set for " + CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
fakeOverrideBuilder.linkFakeOverride(fakeOverride)
current.declarations.add(fakeOverride)
addedFakeOverrides.add(fakeOverride)
}
private fun isVisibilityMoreSpecific(
@@ -582,7 +642,11 @@ class IrOverridingUtil(
}
val typeCheckerContext =
IrTypeCheckerContextWithAdditionalAxioms(irBuiltIns, superTypeParameters, subTypeParameters)
IrTypeCheckerContextWithAdditionalAxioms(
irBuiltIns,
superTypeParameters,
subTypeParameters
)
/* TODO: check the bounds. See OverridingUtil.areTypeParametersEquivalent()
superTypeParameters.forEachIndexed { index, parameter ->
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.overrides
package org.jetbrains.kotlin.ir.overrides
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithVisibility
@@ -1,8 +1,12 @@
package org.jetbrains.kotlin.backend.common.overrides
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.types.IrTypeCheckerContext
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
open class IrTypeCheckerContextWithAdditionalAxioms(
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common
package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
@@ -21,6 +21,9 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.descriptors.WrappedPropertyDescriptor
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.ir.overrides.DeepCopyIrTreeWithSymbolsForFakeOverrides
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
@@ -55,43 +58,10 @@ class FakeOverrideBuilder(
val signaturer: IdSignatureSerializer,
val irBuiltIns: IrBuiltIns,
val platformSpecificClassFilter: PlatformFakeOverrideClassFilter = DefaultFakeOverrideClassFilter
) : FakeOverrideBuilderStrategy {
) : FakeOverrideBuilderStrategy() {
private val haveFakeOverrides = mutableSetOf<IrClass>()
override val propertyOverriddenSymbols = mutableMapOf<IrOverridableMember, List<IrSymbol>>()
private val irOverridingUtil = IrOverridingUtil(irBuiltIns, this)
override fun fakeOverrideMember(
superType: IrType,
member: IrOverridableMember,
clazz: IrClass
): IrOverridableMember {
require(superType is IrSimpleType) { "superType is $superType, expected IrSimpleType" }
val classifier = superType.classifier
require(classifier is IrClassSymbol) { "superType classifier is not IrClassSymbol: $classifier" }
val typeParameters = extractTypeParameters(classifier.owner)
val superArguments = superType.arguments
assert(typeParameters.size == superArguments.size) {
"typeParameters = $typeParameters size != typeArguments = $superArguments size "
}
val substitutionMap = mutableMapOf<IrTypeParameterSymbol, IrType>()
for (i in typeParameters.indices) {
val tp = typeParameters[i]
val ta = superArguments[i]
require(ta is IrTypeProjection) { "Unexpected super type argument: $ta @ $i" }
assert(ta.variance == Variance.INVARIANT) { "Unexpected variance in super type argument: ${ta.variance} @$i" }
substitutionMap[tp.symbol] = ta.type
}
val copier = DeepCopyIrTreeWithSymbolsForFakeOverrides(substitutionMap)
val deepCopyFakeOverride = copier.copy(member, clazz) as IrOverridableMember
deepCopyFakeOverride.parent = clazz
return deepCopyFakeOverride
}
fun buildFakeOverrideChainsForClass(clazz: IrClass) {
if (haveFakeOverrides.contains(clazz)) return
if (!platformSpecificClassFilter.constructFakeOverrides(clazz) || !clazz.symbol.isPublicApi) return