JVM_IR: repair synthetic accessors to fields

This commit is contained in:
Georgy Bronnikov
2020-04-13 14:06:29 +03:00
parent 461c368ee0
commit 41a28bde5c
8 changed files with 99 additions and 22 deletions
@@ -14366,6 +14366,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt"); runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt");
} }
@TestMetadata("protectedField.kt")
public void testProtectedField() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt");
}
@TestMetadata("samUnboundTypeParameter.kt") @TestMetadata("samUnboundTypeParameter.kt")
public void testSamUnboundTypeParameter() throws Exception { public void testSamUnboundTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt"); runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt");
@@ -14,8 +14,6 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs
import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator
import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault
import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault
import org.jetbrains.kotlin.backend.jvm.ir.isLambda import org.jetbrains.kotlin.backend.jvm.ir.isLambda
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledParameters import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledParameters
import org.jetbrains.kotlin.codegen.syntheticAccessorToSuperSuffix import org.jetbrains.kotlin.codegen.syntheticAccessorToSuperSuffix
@@ -75,8 +73,8 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
} }
private val functionMap = mutableMapOf<Pair<IrFunctionSymbol, IrDeclarationParent>, IrFunctionSymbol>() private val functionMap = mutableMapOf<Pair<IrFunctionSymbol, IrDeclarationParent>, IrFunctionSymbol>()
private val getterMap = mutableMapOf<IrFieldSymbol, IrSimpleFunctionSymbol>() private val getterMap = mutableMapOf<Pair<IrFieldSymbol, IrDeclarationParent>, IrSimpleFunctionSymbol>()
private val setterMap = mutableMapOf<IrFieldSymbol, IrSimpleFunctionSymbol>() private val setterMap = mutableMapOf<Pair<IrFieldSymbol, IrDeclarationParent>, IrSimpleFunctionSymbol>()
override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression { override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression {
if (expression.usesDefaultArguments()) { if (expression.usesDefaultArguments()) {
@@ -155,21 +153,46 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
return super.visitExpression(modifyFunctionAccessExpression(expression, accessor)) return super.visitExpression(modifyFunctionAccessExpression(expression, accessor))
} }
override fun visitGetField(expression: IrGetField) = super.visitExpression( override fun visitGetField(expression: IrGetField): IrExpression {
if (!expression.symbol.isAccessible(false, expression.receiver?.type?.classifierOrNull as? IrClassSymbol)) { val dispatchReceiverType = expression.receiver?.type
modifyGetterExpression(expression, getterMap.getOrPut(expression.symbol) { makeGetterAccessorSymbol(expression.symbol) }) return super.visitExpression(
} else { if (!expression.symbol.isAccessible(false, dispatchReceiverType?.classifierOrNull as? IrClassSymbol)) {
expression val symbol = expression.symbol
} val parent =
) symbol.owner.accessorParent(dispatchReceiverType?.classOrNull?.owner ?: symbol.owner.parent) as IrClass
val symbolToAccess = symbol.owner.findDescendantIn(parent)?.symbol ?: symbol
modifyGetterExpression(
expression,
getterMap.getOrPut(Pair(symbolToAccess, parent)) { makeGetterAccessorSymbol(symbolToAccess, parent) }
)
} else {
expression
}
)
}
override fun visitSetField(expression: IrSetField) = super.visitExpression( override fun visitSetField(expression: IrSetField): IrExpression {
if (!expression.symbol.isAccessible(false, expression.receiver?.type?.classifierOrNull as? IrClassSymbol)) { val dispatchReceiverType = expression.receiver?.type
modifySetterExpression(expression, setterMap.getOrPut(expression.symbol) { makeSetterAccessorSymbol(expression.symbol) }) return super.visitExpression(
} else { if (!expression.symbol.isAccessible(false, dispatchReceiverType?.classifierOrNull as? IrClassSymbol)) {
expression val symbol = expression.symbol
val parent =
symbol.owner.accessorParent(dispatchReceiverType?.classOrNull?.owner ?: symbol.owner.parent) as IrClass
val symbolToAccess = symbol.owner.findDescendantIn(parent)?.symbol ?: symbol
modifySetterExpression(
expression,
setterMap.getOrPut(Pair(symbolToAccess, parent)) { makeSetterAccessorSymbol(symbolToAccess, parent) }
)
} else {
expression
}
)
}
private fun IrField.findDescendantIn(derivedClass: IrClass): IrField? =
derivedClass.fields.singleOrNull { candidate ->
candidate.name == this.name && candidate.overrides(this)
} }
)
override fun visitConstructor(declaration: IrConstructor): IrStatement { override fun visitConstructor(declaration: IrConstructor): IrStatement {
if (declaration.isOrShouldBeHidden) { if (declaration.isOrShouldBeHidden) {
@@ -303,7 +326,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
copyAllParamsToArgs(it, accessor) copyAllParamsToArgs(it, accessor)
} }
private fun makeGetterAccessorSymbol(fieldSymbol: IrFieldSymbol): IrSimpleFunctionSymbol = private fun makeGetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrDeclarationParent): IrSimpleFunctionSymbol =
buildFun { buildFun {
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
name = fieldSymbol.owner.accessorNameForGetter() name = fieldSymbol.owner.accessorNameForGetter()
@@ -311,7 +334,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
modality = Modality.FINAL modality = Modality.FINAL
returnType = fieldSymbol.owner.type returnType = fieldSymbol.owner.type
}.also { accessor -> }.also { accessor ->
accessor.parent = fieldSymbol.owner.accessorParent() accessor.parent = parent
pendingAccessorsToAdd.add(accessor) pendingAccessorsToAdd.add(accessor)
if (!fieldSymbol.owner.isStatic) { if (!fieldSymbol.owner.isStatic) {
@@ -339,7 +362,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
) )
} }
private fun makeSetterAccessorSymbol(fieldSymbol: IrFieldSymbol): IrSimpleFunctionSymbol = private fun makeSetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrDeclarationParent): IrSimpleFunctionSymbol =
buildFun { buildFun {
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
name = fieldSymbol.owner.accessorNameForSetter() name = fieldSymbol.owner.accessorNameForSetter()
@@ -347,7 +370,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
modality = Modality.FINAL modality = Modality.FINAL
returnType = context.irBuiltIns.unitType returnType = context.irBuiltIns.unitType
}.also { accessor -> }.also { accessor ->
accessor.parent = fieldSymbol.owner.accessorParent() accessor.parent = parent
pendingAccessorsToAdd.add(accessor) pendingAccessorsToAdd.add(accessor)
if (!fieldSymbol.owner.isStatic) { if (!fieldSymbol.owner.isStatic) {
@@ -79,6 +79,18 @@ fun IrSimpleFunction.overrides(other: IrSimpleFunction): Boolean {
return false return false
} }
fun IrField.overrides(other: IrField): Boolean {
if (this == other) return true
this.overriddenSymbols.forEach {
if (it.owner.overrides(other)) {
return true
}
}
return false
}
private val IrConstructorCall.annotationClass private val IrConstructorCall.annotationClass
get() = this.symbol.owner.constructedClass get() = this.symbol.owner.constructedClass
@@ -0,0 +1,23 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: ProtectedField.java
public abstract class ProtectedField {
protected String field = "fail";
}
//FILE: test.kt
package test
import ProtectedField
class Derived: ProtectedField() {
fun setAndGetField(arg: String) = myRun {
super.field = arg
super.field
}
}
fun myRun(f: () -> String) = f()
fun box() = Derived().setAndGetField("OK")
@@ -1,5 +1,4 @@
// !LANGUAGE: -ProhibitProtectedCallFromInline // !LANGUAGE: -ProhibitProtectedCallFromInline
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// FILE: Test.java // FILE: Test.java
@@ -15581,6 +15581,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt"); runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt");
} }
@TestMetadata("protectedField.kt")
public void testProtectedField() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt");
}
@TestMetadata("samUnboundTypeParameter.kt") @TestMetadata("samUnboundTypeParameter.kt")
public void testSamUnboundTypeParameter() throws Exception { public void testSamUnboundTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt"); runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt");
@@ -15581,6 +15581,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt"); runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt");
} }
@TestMetadata("protectedField.kt")
public void testProtectedField() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt");
}
@TestMetadata("samUnboundTypeParameter.kt") @TestMetadata("samUnboundTypeParameter.kt")
public void testSamUnboundTypeParameter() throws Exception { public void testSamUnboundTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt"); runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt");
@@ -14366,6 +14366,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt"); runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt");
} }
@TestMetadata("protectedField.kt")
public void testProtectedField() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt");
}
@TestMetadata("samUnboundTypeParameter.kt") @TestMetadata("samUnboundTypeParameter.kt")
public void testSamUnboundTypeParameter() throws Exception { public void testSamUnboundTypeParameter() throws Exception {
runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt"); runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt");