diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt index c566cc5abc9..7b2d4ad6f38 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt @@ -912,13 +912,7 @@ internal class JvmMultiFieldValueClassLowering( override fun visitCall(expression: IrCall): IrExpression { val callee = expression.symbol.owner val property = callee.property - if ( - property != null && - callee.extensionReceiverParameter == null && - callee.contextReceiverParametersCount == 0 && - callee.isGetter && - (expression.type.needsMfvcFlattening() || expression.dispatchReceiver?.type?.needsMfvcFlattening() == true) - ) { + if (property != null && callee.isGetter && replacements.getMfvcPropertyNode(property) != null) { require(callee.valueParameters.isEmpty()) { "Unexpected getter:\n${callee.dump()}" } expression.dispatchReceiver = expression.dispatchReceiver?.transform(this, null) return context.createJvmIrBuilder(getCurrentScopeSymbol(), expression).irBlock { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt index 29612a7fd7c..d044d885e00 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt @@ -335,8 +335,9 @@ class MemoizedMultiFieldValueClassReplacements( } } - private fun useRootNode( - parent: IrClass, - property: IrProperty - ) = parent.isMultiFieldValueClass && (property.getter?.isStatic ?: property.backingField?.isStatic) == false + private fun useRootNode(parent: IrClass, property: IrProperty): Boolean { + val getter = property.getter + if (getter != null && (getter.contextReceiverParametersCount > 0 || getter.extensionReceiverParameter != null)) return false + return parent.isMultiFieldValueClass && (getter?.isStatic ?: property.backingField?.isStatic) == false + } } diff --git a/compiler/testData/codegen/box/valueClasses/classFlattening.kt b/compiler/testData/codegen/box/valueClasses/classFlattening.kt index 29932f2a1e1..dce948b0618 100644 --- a/compiler/testData/codegen/box/valueClasses/classFlattening.kt +++ b/compiler/testData/codegen/box/valueClasses/classFlattening.kt @@ -60,6 +60,11 @@ value class SimpleMfvc(val x: UInt, val y: IC, val z: String) { context(SimpleMfvc) private val private2: SimpleMfvc get() = this@SimpleMfvc + + val a4: Int + get() = 2 + val b4: SimpleMfvc + get() = this } fun smfvc(ic: IC, x: SimpleMfvc, ic1: UInt) = ic(ic) + x.x + ic(x.y) + ic1 @@ -154,5 +159,12 @@ fun box(): String { } require(idUnboxed(idBoxed(idUnboxed(o2) /*boxing*/) /*unbox*/) == o2) + + require(o2.a4 == 2) + require(o2.b4 == o2) + require(o2.b4.x == o2.x) + require(o2.b4.y == o2.y) + require(o2.b4.z == o2.z) + return "OK" } diff --git a/compiler/testData/codegen/box/valueClasses/classFlattening.txt b/compiler/testData/codegen/box/valueClasses/classFlattening.txt index 58d90848496..e4035eeee40 100644 --- a/compiler/testData/codegen/box/valueClasses/classFlattening.txt +++ b/compiler/testData/codegen/box/valueClasses/classFlattening.txt @@ -160,9 +160,11 @@ public final class SimpleMfvc { public static method equals-impl(p0: int, p1: int, p2: java.lang.String, p3: java.lang.Object): boolean public final static method equals-impl0(p0: int, p1: int, p2: java.lang.String, p3: int, p4: int, p5: java.lang.String): boolean public final static @org.jetbrains.annotations.NotNull method getA3-sUp7gFk(p0: int, p1: int, @org.jetbrains.annotations.NotNull p2: java.lang.String, p3: int, p4: int, @org.jetbrains.annotations.NotNull p5: java.lang.String): SimpleMfvc + public final static method getA4-impl(p0: int, p1: int, @org.jetbrains.annotations.NotNull p2: java.lang.String): int public final static @org.jetbrains.annotations.NotNull method getB1-sUp7gFk(p0: int, p1: int, @org.jetbrains.annotations.NotNull p2: java.lang.String): SimpleMfvc public final static @org.jetbrains.annotations.NotNull method getB2-sUp7gFk(p0: int, p1: int, @org.jetbrains.annotations.NotNull p2: java.lang.String): SimpleMfvc public final static @org.jetbrains.annotations.NotNull method getB3-sUp7gFk(p0: int, p1: int, @org.jetbrains.annotations.NotNull p2: java.lang.String, p3: int, p4: int, @org.jetbrains.annotations.NotNull p5: java.lang.String): SimpleMfvc + public final static @org.jetbrains.annotations.NotNull method getB4-impl(p0: int, p1: int, @org.jetbrains.annotations.NotNull p2: java.lang.String): SimpleMfvc private final static method getPrivate1-sUp7gFk(p0: int, p1: int, p2: java.lang.String, p3: int, p4: int, p5: java.lang.String): SimpleMfvc private final static method getPrivate2-sUp7gFk(p0: int, p1: int, p2: java.lang.String): SimpleMfvc private final static method getPrivate2-sUp7gFk(p0: int, p1: int, p2: java.lang.String, p3: int, p4: int, p5: java.lang.String): SimpleMfvc diff --git a/compiler/testData/codegen/box/valueClasses/inlineFunctions.kt b/compiler/testData/codegen/box/valueClasses/inlineFunctions.kt index 3417bb5092b..d3e25a5d808 100644 --- a/compiler/testData/codegen/box/valueClasses/inlineFunctions.kt +++ b/compiler/testData/codegen/box/valueClasses/inlineFunctions.kt @@ -13,12 +13,24 @@ fun runSuspend(block: suspend () -> Unit) { } // FILE: dependency.kt +import kotlin.math.sqrt @JvmInline value class DPoint(val x: Double, val y: Double) +fun Double.square() = this * this + @JvmInline -value class DSegment(val p1: DPoint, val p2: DPoint) +value class DSegment(val p1: DPoint, val p2: DPoint) { + inline val length + get() = sqrt((p1.x - p2.x).square() + (p1.y - p2.y).square()) + inline val middle + get() = DPoint((p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0) +} +inline val DSegment.length1 + get() = length +inline val DSegment.middle1 + get() = middle inline fun DSegment.myLet(f: (DSegment) -> DPoint) = f(this) @@ -26,6 +38,7 @@ inline fun DSegment.myLet(f: (DSegment) -> DPoint) = f(this) // FILE: test.kt import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.resume +import kotlin.math.sqrt fun supply(x: Any?) = Unit @@ -68,6 +81,20 @@ fun box(): String { supply("o") runSuspend { require(suspendFun() == DPoint(1.0, 2.0).toString()) } supply("p") + require(segment.length == sqrt(5.0)) + supply("q") + require(segment.length1 == sqrt(5.0)) + supply("r") + require(segment.middle == DPoint(1.5, 3.0)) + supply("s") + require(segment.middle1 == DPoint(1.5, 3.0)) + supply("t") + require(segment.middle.x == 1.5) + require(segment.middle.y == 3.0) + supply("u") + require(segment.middle1.x == 1.5) + require(segment.middle1.y == 3.0) + supply("v") return "OK" } diff --git a/compiler/testData/codegen/box/valueClasses/inlineFunctions.txt b/compiler/testData/codegen/box/valueClasses/inlineFunctions.txt index 523f165bb82..fd67aaa35c2 100644 --- a/compiler/testData/codegen/box/valueClasses/inlineFunctions.txt +++ b/compiler/testData/codegen/box/valueClasses/inlineFunctions.txt @@ -51,6 +51,8 @@ public final class DSegment { public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean public static method equals-impl(p0: double, p1: double, p2: double, p3: double, p4: java.lang.Object): boolean public final static method equals-impl0(p0: double, p1: double, p2: double, p3: double, p4: double, p5: double, p6: double, p7: double): boolean + public final static method getLength-impl(p0: double, p1: double, p2: double, p3: double): double + public final static @org.jetbrains.annotations.NotNull method getMiddle-impl(p0: double, p1: double, p2: double, p3: double): DPoint public final @org.jetbrains.annotations.NotNull method getP1(): DPoint public final @org.jetbrains.annotations.NotNull method getP2(): DPoint public method hashCode(): int @@ -68,7 +70,10 @@ public final class DSegment { @kotlin.Metadata public final class DependencyKt { // source: 'dependency.kt' + public final static method getLength1-sUp7gFk(p0: double, p1: double, p2: double, p3: double): double + public final static @org.jetbrains.annotations.NotNull method getMiddle1-sUp7gFk(p0: double, p1: double, p2: double, p3: double): DPoint public final static @org.jetbrains.annotations.NotNull method myLet-GPBa7dw(p0: double, p1: double, p2: double, p3: double, @org.jetbrains.annotations.NotNull p4: kotlin.jvm.functions.Function1): DPoint + public final static method square(p0: double): double } @kotlin.coroutines.jvm.internal.DebugMetadata