[IR] Support function references
Signed-off-by: Evgeniy.Zhelenskiy <Evgeniy.Zhelenskiy@jetbrains.com> #KT-1179
This commit is contained in:
committed by
Space Team
parent
b45f2baff5
commit
89d5592622
+6
@@ -50459,6 +50459,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/valueClasses/forStatement.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionReferences.kt")
|
||||
public void testFunctionReferences() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/functionReferences.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcFieldInitializationOrder.kt")
|
||||
public void testMfvcFieldInitializationOrder() throws Exception {
|
||||
|
||||
+36
-3
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
|
||||
@@ -680,8 +682,34 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
// todo implement
|
||||
return super.visitFunctionReference(expression)
|
||||
val function = expression.symbol.owner
|
||||
val replacement = function.let {
|
||||
replacements.run {
|
||||
getReplacementFunction(it) ?: if (it is IrConstructor) getReplacementForRegularClassConstructor(it) else null
|
||||
}
|
||||
} ?: return super.visitFunctionReference(expression)
|
||||
return if (function is IrConstructor && function.isPrimary && function.constructedClass.isMultiFieldValueClass) {
|
||||
expression.run {
|
||||
IrConstructorCallImpl(
|
||||
startOffset, endOffset, type, function.symbol, typeArgumentsCount, typeArgumentsCount, valueArgumentsCount, origin
|
||||
)
|
||||
}.transform(this, null)
|
||||
} else {
|
||||
context.createJvmIrBuilder(getCurrentScopeSymbol()).irBlock {
|
||||
expression.run {
|
||||
IrFunctionReferenceImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
type,
|
||||
replacement.symbol,
|
||||
function.typeParameters.size,
|
||||
replacement.valueParameters.size,
|
||||
reflectionTarget,
|
||||
origin
|
||||
)
|
||||
}.apply { buildReplacement(function, expression, replacement) }.copyAttributes(expression)
|
||||
}.unwrapBlock()
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression {
|
||||
@@ -1057,7 +1085,12 @@ private class JvmMultiFieldValueClassLowering(context: JvmBackendContext) : JvmV
|
||||
}
|
||||
if (expression is IrTry) {
|
||||
expression.tryResult = irBlock { flattenExpressionTo(expression.tryResult, instance) }.unwrapBlock()
|
||||
expression.catches.replaceAll { irCatch(it.catchParameter, irBlock { flattenExpressionTo(it.result, instance) }.unwrapBlock()) }
|
||||
expression.catches.replaceAll {
|
||||
irCatch(
|
||||
it.catchParameter,
|
||||
irBlock { flattenExpressionTo(it.result, instance) }.unwrapBlock()
|
||||
)
|
||||
}
|
||||
expression.finallyExpression = expression.finallyExpression?.transform(lowering, null)
|
||||
+expression
|
||||
return
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// CHECK_BYTECODE_LISTING
|
||||
// WITH_STDLIB
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// WORKS_WHEN_VALUE_CLASS
|
||||
// LANGUAGE: +ValueClasses
|
||||
|
||||
@JvmInline
|
||||
value class DPoint(val x: Double, val y: Double) {
|
||||
fun f(z: Double) = x + y + z
|
||||
}
|
||||
|
||||
fun g(point: DPoint, z: Double) = point.f(z)
|
||||
|
||||
class A(val point: DPoint) {
|
||||
fun f(otherDPoint: DPoint, z: Double) = point.f(z) * otherDPoint.f(z)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val dPoint = DPoint(1.0, 2.0)
|
||||
val a = A(dPoint)
|
||||
|
||||
require((::DPoint)(1.0, 2.0) == dPoint)
|
||||
require((dPoint::f)(3.0) == 6.0)
|
||||
require((::g)(dPoint, 3.0) == 6.0)
|
||||
require((a::f)(dPoint, 3.0) == 36.0)
|
||||
|
||||
require((::DPoint)(1.0, DPoint(1.0, 2.0).y) == dPoint)
|
||||
require((dPoint::f)(DPoint(1.0, 3.0).y) == 6.0)
|
||||
require((::g)(dPoint, DPoint(1.0, 3.0).y) == 6.0)
|
||||
require((a::f)(dPoint, DPoint(1.0, 3.0).y) == 36.0)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
@kotlin.Metadata
|
||||
public final class A {
|
||||
// source: 'functionReferences.kt'
|
||||
private final field point-0: double
|
||||
private final field point-1: double
|
||||
public method <init>(p0: double, p1: double): void
|
||||
public final method f-GPBa7dw(p0: double, p1: double, p2: double): double
|
||||
public final @org.jetbrains.annotations.NotNull method getPoint(): DPoint
|
||||
public synthetic final method getPoint-0(): double
|
||||
public synthetic final method getPoint-1(): double
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmInline
|
||||
@kotlin.Metadata
|
||||
public final class DPoint {
|
||||
// source: 'functionReferences.kt'
|
||||
private final field field-0: double
|
||||
private final field field-1: double
|
||||
private synthetic method <init>(p0: double, p1: double): void
|
||||
public synthetic final static method box-impl(p0: double, p1: double): DPoint
|
||||
public final static method constructor-impl(p0: double, p1: double): void
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: double, p1: double, p2: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: double, p1: double, p2: double, p3: double): boolean
|
||||
public final static method f-impl(p0: double, p1: double, p2: double): double
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: double, p1: double): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static method toString-impl(p0: double, p1: double): java.lang.String
|
||||
public synthetic final method unbox-impl-0(): double
|
||||
public synthetic final method unbox-impl-1(): double
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class FunctionReferencesKt {
|
||||
// source: 'functionReferences.kt'
|
||||
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
|
||||
public final static method g-GPBa7dw(p0: double, p1: double, p2: double): double
|
||||
}
|
||||
+6
@@ -50459,6 +50459,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/valueClasses/forStatement.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionReferences.kt")
|
||||
public void testFunctionReferences() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/valueClasses/functionReferences.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("mfvcFieldInitializationOrder.kt")
|
||||
public void testMfvcFieldInitializationOrder() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user