JVM_IR: slightly refactor JvmPropertiesLowering
to make it easier to generate different kinds of synthetic methods. #KT-47609 Fixed
This commit is contained in:
+6
@@ -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 {
|
||||||
|
|||||||
+43
-61
@@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-2
@@ -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) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
+6
@@ -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 {
|
||||||
|
|||||||
+6
@@ -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 {
|
||||||
|
|||||||
+5
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user