JVM_IR: slightly refactor JvmPropertiesLowering

to make it easier to generate different kinds of synthetic methods.

 #KT-47609 Fixed
This commit is contained in:
pyos
2021-06-30 18:47:20 +02:00
committed by Alexander Udalov
parent a943cdadef
commit 7ae4303e1b
7 changed files with 83 additions and 63 deletions
@@ -18850,6 +18850,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inlineClasses/kt46554.kt"); runTest("compiler/testData/codegen/box/inlineClasses/kt46554.kt");
} }
@Test
@TestMetadata("kt47609.kt")
public void testKt47609() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt47609.kt");
}
@Test @Test
@TestMetadata("mangledDefaultParameterFunction.kt") @TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception { public void testMangledDefaultParameterFunction() throws Exception {
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters
import org.jetbrains.kotlin.backend.jvm.ir.needsAccessor import org.jetbrains.kotlin.backend.jvm.ir.needsAccessor
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledReturnType import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledReturnType
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.requiresMangling import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.requiresMangling
@@ -27,7 +28,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression import org.jetbrains.kotlin.ir.expressions.IrFieldAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAbi
@@ -157,73 +158,54 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE
accessor != null && !property.needsAccessor(accessor) accessor != null && !property.needsAccessor(accessor)
private fun createSyntheticMethodForAnnotations(declaration: IrProperty): IrSimpleFunction = private fun createSyntheticMethodForAnnotations(declaration: IrProperty): IrSimpleFunction =
backendContext.irFactory.buildFun { backendContext.createSyntheticMethodForProperty(
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS declaration,
name = Name.identifier(computeSyntheticMethodName(declaration)) JvmAbi.ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX,
visibility = declaration.visibility JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS,
modality = Modality.OPEN // TODO: technically JVM permits having fields with same name but different type, so we could potentially
// generate two properties like that; should this be the getter's return type instead?
returnType = backendContext.irBuiltIns.unitType returnType = backendContext.irBuiltIns.unitType
}.apply { ).apply {
declaration.getter?.extensionReceiverParameter?.let { extensionReceiver ->
extensionReceiverParameter = extensionReceiver.copyTo(
this,
type = extensionReceiver.type.erasePropertyAnnotationsExtensionReceiverType()
)
}
body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET) body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
parent = declaration.parent
annotations = declaration.annotations annotations = declaration.annotations
}
companion object {
private fun JvmBackendContext.createSyntheticMethodForProperty(
declaration: IrProperty,
suffix: String,
origin: IrDeclarationOrigin,
returnType: IrType = IrUninitializedType
) = irFactory.buildFun {
name = Name.identifier(computeSyntheticMethodName(declaration, suffix))
modality = Modality.OPEN
visibility = declaration.visibility
this.origin = origin
this.returnType = returnType
}.apply {
declaration.getter?.extensionReceiverParameter?.let {
// Synthetic methods don't get generic type signatures anyway, so not exactly useful to preserve type parameters.
extensionReceiverParameter = it.copyTo(this, type = it.type.eraseTypeParameters())
}
parent = declaration.parent
metadata = declaration.metadata metadata = declaration.metadata
} }
private fun IrType.erasePropertyAnnotationsExtensionReceiverType(): IrType { private fun JvmBackendContext.computeSyntheticMethodName(property: IrProperty, suffix: String): String {
// Use raw type of extension receiver to avoid generic signature, val baseName =
// which should not be generated for '...$annotations' method. if (state.languageVersionSettings.supportsFeature(LanguageFeature.UseGetterNameForPropertyAnnotationsMethodOnJvm)) {
if (this !is IrSimpleType) { val getter = property.getter
throw AssertionError("Unexpected property receiver type: $this") if (getter != null) {
} val needsMangling =
val erasedType = if (isArray()) { getter.extensionReceiverParameter?.type?.requiresMangling == true ||
when (val arg0 = arguments[0]) { (state.functionsWithInlineClassReturnTypesMangled && getter.hasMangledReturnType)
is IrStarProjection -> { val mangled = if (needsMangling) inlineClassReplacements.getReplacementFunction(getter) else null
// 'Array<*>' becomes 'Array<*>' methodSignatureMapper.mapFunctionName(mangled ?: getter)
this } else JvmAbi.getterName(property.name.asString())
} else {
property.name.asString()
} }
is IrTypeProjection -> { return baseName + suffix
// 'Array<VARIANCE TYPE>' becomes 'Array<VARIANCE erase(TYPE)>'
classifier.typeWithArguments(
listOf(makeTypeProjection(arg0.type.erasePropertyAnnotationsExtensionReceiverType(), arg0.variance))
)
}
else ->
throw AssertionError("Unexpected type argument: $arg0")
}
} else {
classifier.typeWith()
} }
return erasedType
.withHasQuestionMark(this.hasQuestionMark)
.addAnnotations(this.annotations)
}
private fun computeSyntheticMethodName(property: IrProperty): String {
val baseName =
if (backendContext.state.languageVersionSettings.supportsFeature(LanguageFeature.UseGetterNameForPropertyAnnotationsMethodOnJvm)) {
val getter = property.getter
if (getter != null) {
val needsMangling =
getter.extensionReceiverParameter?.type?.requiresMangling == true ||
(backendContext.state.functionsWithInlineClassReturnTypesMangled && getter.hasMangledReturnType)
backendContext.methodSignatureMapper.mapFunctionName(
if (needsMangling) backendContext.inlineClassReplacements.getReplacementFunction(getter) ?: getter
else getter
)
} else JvmAbi.getterName(property.name.asString())
} else {
property.name.asString()
}
return JvmAbi.getSyntheticMethodNameForAnnotatedProperty(baseName)
} }
} }
@@ -121,8 +121,12 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
// Internal underlying vals of inline classes have no getter method // Internal underlying vals of inline classes have no getter method
getter.owner.isInlineClassFieldGetter && getter.owner.visibility == DescriptorVisibilities.INTERNAL getter.owner.isInlineClassFieldGetter && getter.owner.visibility == DescriptorVisibilities.INTERNAL
val origin = if (needsDummySignature) InlineClassAbi.UNMANGLED_FUNCTION_REFERENCE else null val origin = if (needsDummySignature) InlineClassAbi.UNMANGLED_FUNCTION_REFERENCE else null
val reference = val reference = IrFunctionReferenceImpl.fromSymbolOwner(
IrFunctionReferenceImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, expression.type, getter, 0, getter, origin) startOffset, endOffset, expression.type, getter, getter.owner.typeParameters.size, getter, origin
)
for ((index, parameter) in getter.owner.typeParameters.withIndex()) {
reference.putTypeArgument(index, parameter.erasedUpperBound.defaultType)
}
return irCall(signatureStringIntrinsic).apply { putValueArgument(0, reference) } return irCall(signatureStringIntrinsic).apply { putValueArgument(0, reference) }
} }
+11
View File
@@ -0,0 +1,11 @@
// WITH_REFLECT
// TARGET_BACKEND: JVM
annotation class Ann(val value: String)
inline class C<T>(val x: String)
@Ann("OK")
val <T> C<T>.value: String
get() = x
fun box() = (C<Any?>::value.annotations.singleOrNull() as? Ann)?.value ?: "null"
@@ -18808,6 +18808,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/kt46554.kt"); runTest("compiler/testData/codegen/box/inlineClasses/kt46554.kt");
} }
@Test
@TestMetadata("kt47609.kt")
public void testKt47609() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt47609.kt");
}
@Test @Test
@TestMetadata("mangledDefaultParameterFunction.kt") @TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception { public void testMangledDefaultParameterFunction() throws Exception {
@@ -18850,6 +18850,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/kt46554.kt"); runTest("compiler/testData/codegen/box/inlineClasses/kt46554.kt");
} }
@Test
@TestMetadata("kt47609.kt")
public void testKt47609() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt47609.kt");
}
@Test @Test
@TestMetadata("mangledDefaultParameterFunction.kt") @TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception { public void testMangledDefaultParameterFunction() throws Exception {
@@ -15598,6 +15598,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/kt46554.kt"); runTest("compiler/testData/codegen/box/inlineClasses/kt46554.kt");
} }
@TestMetadata("kt47609.kt")
public void testKt47609() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt47609.kt");
}
@TestMetadata("mangledDefaultParameterFunction.kt") @TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception { public void testMangledDefaultParameterFunction() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt"); runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");