JVM_IR: fix copying of receivers when unboxing inline class parameters
If an extension receiver is copied into a normal parameter, this may later cause default argument masks to be shifted.
This commit is contained in:
+5
@@ -118,6 +118,11 @@ public class FirCompileKotlinAgainstKotlinTestGenerated extends AbstractFirCompi
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/defaultLambdaRegeneration2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultWithInlineClassAndReceivers.kt")
|
||||
public void testDefaultWithInlineClassAndReceivers() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/defaultWithInlineClassAndReceivers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("delegatedDefault.kt")
|
||||
public void testDelegatedDefault() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/delegatedDefault.kt");
|
||||
|
||||
+25
-33
@@ -146,45 +146,37 @@ class MemoizedInlineClassReplacements(private val mangleReturnTypes: Boolean, pr
|
||||
private fun createMethodReplacement(function: IrFunction): IrSimpleFunction =
|
||||
buildReplacement(function, function.origin) {
|
||||
require(function.dispatchReceiverParameter != null && function is IrSimpleFunction)
|
||||
val newValueParameters = ArrayList<IrValueParameter>()
|
||||
for ((index, parameter) in function.explicitParameters.withIndex()) {
|
||||
val name = if (parameter == function.extensionReceiverParameter) Name.identifier("\$receiver") else parameter.name
|
||||
val newParameter: IrValueParameter
|
||||
if (parameter == function.dispatchReceiverParameter) {
|
||||
newParameter = parameter.copyTo(this, index = -1, name = name, defaultValue = null)
|
||||
dispatchReceiverParameter = newParameter
|
||||
} else {
|
||||
newParameter = parameter.copyTo(this, index = index - 1, name = name, defaultValue = null)
|
||||
newValueParameters += newParameter
|
||||
dispatchReceiverParameter = function.dispatchReceiverParameter?.copyTo(this, index = -1)
|
||||
extensionReceiverParameter = function.extensionReceiverParameter?.copyTo(this, index = -1, name = Name.identifier("\$receiver"))
|
||||
valueParameters = function.valueParameters.mapIndexed { index, parameter ->
|
||||
parameter.copyTo(this, index = index, defaultValue = null).also {
|
||||
// Assuming that constructors and non-override functions are always replaced with the unboxed
|
||||
// equivalent, deep-copying the value here is unnecessary. See `JvmInlineClassLowering`.
|
||||
it.defaultValue = parameter.defaultValue?.patchDeclarationParents(this)
|
||||
}
|
||||
// Assuming that constructors and non-override functions are always replaced with the unboxed
|
||||
// equivalent, deep-copying the value here is unnecessary. See `JvmInlineClassLowering`.
|
||||
newParameter.defaultValue = parameter.defaultValue?.patchDeclarationParents(this)
|
||||
}
|
||||
valueParameters = newValueParameters
|
||||
}
|
||||
|
||||
private fun createStaticReplacement(function: IrFunction): IrSimpleFunction =
|
||||
buildReplacement(function, JvmLoweredDeclarationOrigin.STATIC_INLINE_CLASS_REPLACEMENT, noFakeOverride = true) {
|
||||
val newValueParameters = ArrayList<IrValueParameter>()
|
||||
for ((index, parameter) in function.explicitParameters.withIndex()) {
|
||||
newValueParameters += when (parameter) {
|
||||
// FAKE_OVERRIDEs have broken dispatch receivers
|
||||
function.dispatchReceiverParameter ->
|
||||
function.parentAsClass.thisReceiver!!.copyTo(
|
||||
this, index = index, name = Name.identifier("arg$index"),
|
||||
type = function.parentAsClass.defaultType, origin = IrDeclarationOrigin.MOVED_DISPATCH_RECEIVER
|
||||
)
|
||||
function.extensionReceiverParameter ->
|
||||
parameter.copyTo(
|
||||
this, index = index, name = Name.identifier("\$this\$${function.name}"),
|
||||
origin = IrDeclarationOrigin.MOVED_EXTENSION_RECEIVER
|
||||
)
|
||||
else ->
|
||||
parameter.copyTo(this, index = index, defaultValue = null).also {
|
||||
// See comment next to a similar line above.
|
||||
it.defaultValue = parameter.defaultValue?.patchDeclarationParents(this)
|
||||
}
|
||||
val newValueParameters = mutableListOf<IrValueParameter>()
|
||||
if (function.dispatchReceiverParameter != null) {
|
||||
// FAKE_OVERRIDEs have broken dispatch receivers
|
||||
newValueParameters += function.parentAsClass.thisReceiver!!.copyTo(
|
||||
this, index = newValueParameters.size, name = Name.identifier("arg${newValueParameters.size}"),
|
||||
type = function.parentAsClass.defaultType, origin = IrDeclarationOrigin.MOVED_DISPATCH_RECEIVER
|
||||
)
|
||||
}
|
||||
function.extensionReceiverParameter?.let {
|
||||
newValueParameters += it.copyTo(
|
||||
this, index = newValueParameters.size, name = Name.identifier("\$this\$${function.name}"),
|
||||
origin = IrDeclarationOrigin.MOVED_EXTENSION_RECEIVER
|
||||
)
|
||||
}
|
||||
for (parameter in function.valueParameters) {
|
||||
newValueParameters += parameter.copyTo(this, index = newValueParameters.size, defaultValue = null).also {
|
||||
// See comment next to a similar line above.
|
||||
it.defaultValue = parameter.defaultValue?.patchDeclarationParents(this)
|
||||
}
|
||||
}
|
||||
valueParameters = newValueParameters
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// FILE: A.kt
|
||||
package z
|
||||
|
||||
inline class Z(val s: String)
|
||||
|
||||
class X {
|
||||
fun Int.foo(z: Z, value: String = "OK") = value
|
||||
}
|
||||
|
||||
// FILE: B.kt
|
||||
import z.*
|
||||
|
||||
fun box(): String = with(X()) { 1.foo(Z("")) }
|
||||
+5
@@ -123,6 +123,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/defaultLambdaRegeneration2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultWithInlineClassAndReceivers.kt")
|
||||
public void testDefaultWithInlineClassAndReceivers() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/defaultWithInlineClassAndReceivers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("delegatedDefault.kt")
|
||||
public void testDelegatedDefault() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/delegatedDefault.kt");
|
||||
|
||||
Generated
+5
@@ -118,6 +118,11 @@ public class IrCompileKotlinAgainstKotlinTestGenerated extends AbstractIrCompile
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/defaultLambdaRegeneration2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultWithInlineClassAndReceivers.kt")
|
||||
public void testDefaultWithInlineClassAndReceivers() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/defaultWithInlineClassAndReceivers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("delegatedDefault.kt")
|
||||
public void testDelegatedDefault() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/delegatedDefault.kt");
|
||||
|
||||
+5
@@ -118,6 +118,11 @@ public class JvmIrAgainstOldBoxTestGenerated extends AbstractJvmIrAgainstOldBoxT
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/defaultLambdaRegeneration2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultWithInlineClassAndReceivers.kt")
|
||||
public void testDefaultWithInlineClassAndReceivers() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/defaultWithInlineClassAndReceivers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("delegatedDefault.kt")
|
||||
public void testDelegatedDefault() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/delegatedDefault.kt");
|
||||
|
||||
+5
@@ -118,6 +118,11 @@ public class JvmOldAgainstIrBoxTestGenerated extends AbstractJvmOldAgainstIrBoxT
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/defaultLambdaRegeneration2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultWithInlineClassAndReceivers.kt")
|
||||
public void testDefaultWithInlineClassAndReceivers() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/defaultWithInlineClassAndReceivers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("delegatedDefault.kt")
|
||||
public void testDelegatedDefault() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlin/delegatedDefault.kt");
|
||||
|
||||
Reference in New Issue
Block a user