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");
}
@Test
@TestMetadata("kt47609.kt")
public void testKt47609() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt47609.kt");
}
@Test
@TestMetadata("mangledDefaultParameterFunction.kt")
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.jvm.JvmBackendContext
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.lower.inlineclasses.hasMangledReturnType
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.impl.IrBlockBodyImpl
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.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JvmAbi
@@ -157,73 +158,54 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE
accessor != null && !property.needsAccessor(accessor)
private fun createSyntheticMethodForAnnotations(declaration: IrProperty): IrSimpleFunction =
backendContext.irFactory.buildFun {
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS
name = Name.identifier(computeSyntheticMethodName(declaration))
visibility = declaration.visibility
modality = Modality.OPEN
backendContext.createSyntheticMethodForProperty(
declaration,
JvmAbi.ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX,
JvmLoweredDeclarationOrigin.SYNTHETIC_METHOD_FOR_PROPERTY_OR_TYPEALIAS_ANNOTATIONS,
// 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
}.apply {
declaration.getter?.extensionReceiverParameter?.let { extensionReceiver ->
extensionReceiverParameter = extensionReceiver.copyTo(
this,
type = extensionReceiver.type.erasePropertyAnnotationsExtensionReceiverType()
)
}
).apply {
body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
parent = declaration.parent
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
}
private fun IrType.erasePropertyAnnotationsExtensionReceiverType(): IrType {
// Use raw type of extension receiver to avoid generic signature,
// which should not be generated for '...$annotations' method.
if (this !is IrSimpleType) {
throw AssertionError("Unexpected property receiver type: $this")
}
val erasedType = if (isArray()) {
when (val arg0 = arguments[0]) {
is IrStarProjection -> {
// 'Array<*>' becomes 'Array<*>'
this
private fun JvmBackendContext.computeSyntheticMethodName(property: IrProperty, suffix: String): String {
val baseName =
if (state.languageVersionSettings.supportsFeature(LanguageFeature.UseGetterNameForPropertyAnnotationsMethodOnJvm)) {
val getter = property.getter
if (getter != null) {
val needsMangling =
getter.extensionReceiverParameter?.type?.requiresMangling == true ||
(state.functionsWithInlineClassReturnTypesMangled && getter.hasMangledReturnType)
val mangled = if (needsMangling) inlineClassReplacements.getReplacementFunction(getter) else null
methodSignatureMapper.mapFunctionName(mangled ?: getter)
} else JvmAbi.getterName(property.name.asString())
} else {
property.name.asString()
}
is IrTypeProjection -> {
// '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 baseName + suffix
}
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
getter.owner.isInlineClassFieldGetter && getter.owner.visibility == DescriptorVisibilities.INTERNAL
val origin = if (needsDummySignature) InlineClassAbi.UNMANGLED_FUNCTION_REFERENCE else null
val reference =
IrFunctionReferenceImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, expression.type, getter, 0, getter, origin)
val reference = IrFunctionReferenceImpl.fromSymbolOwner(
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) }
}
+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");
}
@Test
@TestMetadata("kt47609.kt")
public void testKt47609() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt47609.kt");
}
@Test
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
@@ -18850,6 +18850,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
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
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
@@ -15598,6 +15598,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
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")
public void testMangledDefaultParameterFunction() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");