JVM_IR KT-46839 lower varargs for *arrayOf function references
This commit is contained in:
committed by
teamcityserver
parent
6ca7b39f6a
commit
ba00709e4d
+24
@@ -2440,12 +2440,24 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayConstructorArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("builtinFunctionReferenceOwner.kt")
|
||||
public void testBuiltinFunctionReferenceOwner() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/builtinFunctionReferenceOwner.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classesAreSynthetic.kt")
|
||||
public void testClassesAreSynthetic() throws Exception {
|
||||
@@ -21437,6 +21449,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayConstructor.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enumValueOf.kt")
|
||||
public void testEnumValueOf() throws Exception {
|
||||
|
||||
+8
-3
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.backend.jvm.lower.indy.LambdaMetafactoryArguments
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.indy.LambdaMetafactoryArgumentsBuilder
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.indy.SamDelegatingLambdaBlock
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.indy.SamDelegatingLambdaBuilder
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
||||
import org.jetbrains.kotlin.config.JvmClosureGenerationScheme
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
@@ -704,7 +703,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
|
||||
body = context.createJvmIrBuilder(symbol, startOffset, endOffset).run {
|
||||
var unboundIndex = 0
|
||||
irExprBody(irCall(callee).apply {
|
||||
val call = irCall(callee).apply {
|
||||
for (typeParameter in irFunctionReference.symbol.owner.allTypeParameters) {
|
||||
putTypeArgument(typeParameter.index, typeArgumentsMap[typeParameter.symbol])
|
||||
}
|
||||
@@ -735,7 +734,13 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
irGet(valueParameters[unboundIndex++])
|
||||
}?.let { putArgument(callee, parameter, it) }
|
||||
}
|
||||
})
|
||||
}
|
||||
irExprBody(
|
||||
if (irFunctionReference.symbol.owner.isArrayOf())
|
||||
call.transform(VarargLowering(this@FunctionReferenceLowering.context), null)
|
||||
else
|
||||
call
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-29
@@ -34,7 +34,7 @@ val varargPhase = makeIrFilePhase(
|
||||
prerequisite = setOf(polymorphicSignaturePhase)
|
||||
)
|
||||
|
||||
private class VarargLowering(val context: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoidWithContext() {
|
||||
internal class VarargLowering(val context: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoidWithContext() {
|
||||
override fun lower(irFile: IrFile) = irFile.transformChildrenVoid()
|
||||
|
||||
// Ignore annotations
|
||||
@@ -65,7 +65,7 @@ private class VarargLowering(val context: JvmBackendContext) : FileLoweringPass,
|
||||
return when {
|
||||
// Lower `arrayOf` calls. When `isArrayOf` returns true we know that the function has exactly one
|
||||
// vararg parameter. Meanwhile, the code above ensures that the corresponding argument is not null.
|
||||
function.isArrayOf ->
|
||||
function.owner.isArrayOf() ->
|
||||
expression.getValueArgument(0)!!
|
||||
function.isEmptyArray ->
|
||||
createBuilder(expression.startOffset, expression.endOffset).irArrayOf(expression.type)
|
||||
@@ -83,7 +83,7 @@ private class VarargLowering(val context: JvmBackendContext) : FileLoweringPass,
|
||||
is IrExpression -> +element.transform(this@VarargLowering, null)
|
||||
is IrSpreadElement -> {
|
||||
val spread = element.expression
|
||||
if (spread is IrFunctionAccessExpression && spread.symbol.isArrayOf) {
|
||||
if (spread is IrFunctionAccessExpression && spread.symbol.owner.isArrayOf()) {
|
||||
// Skip empty arrays and don't copy immediately created arrays
|
||||
val argument = spread.getValueArgument(0) ?: continue@loop
|
||||
if (argument is IrVararg) {
|
||||
@@ -101,33 +101,28 @@ private class VarargLowering(val context: JvmBackendContext) : FileLoweringPass,
|
||||
private fun createBuilder(startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET) =
|
||||
context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol, startOffset, endOffset)
|
||||
|
||||
private val IrFunctionSymbol.isArrayOf: Boolean
|
||||
get() = owner.isArrayOf
|
||||
|
||||
private val IrFunctionSymbol.isEmptyArray: Boolean
|
||||
get() = owner.name.asString() == "emptyArray" &&
|
||||
(owner.parent as? IrPackageFragment)?.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME
|
||||
|
||||
companion object {
|
||||
private val PRIMITIVE_ARRAY_OF_NAMES: Set<String> =
|
||||
(PrimitiveType.values().map { type -> type.name } + UnsignedType.values().map { type -> type.typeName.asString() })
|
||||
.map { name -> name.toLowerCaseAsciiOnly() + "ArrayOf" }.toSet()
|
||||
private const val ARRAY_OF_NAME = "arrayOf"
|
||||
|
||||
|
||||
private val IrFunction.isArrayOf: Boolean
|
||||
get() {
|
||||
val parent = when (val directParent = parent) {
|
||||
is IrClass -> directParent.getPackageFragment() ?: return false
|
||||
is IrPackageFragment -> directParent
|
||||
else -> return false
|
||||
}
|
||||
return parent.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME &&
|
||||
name.asString().let { it in PRIMITIVE_ARRAY_OF_NAMES || it == ARRAY_OF_NAME } &&
|
||||
extensionReceiverParameter == null &&
|
||||
dispatchReceiverParameter == null &&
|
||||
valueParameters.size == 1 &&
|
||||
valueParameters[0].isVararg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal val PRIMITIVE_ARRAY_OF_NAMES: Set<String> =
|
||||
(PrimitiveType.values().map { type -> type.name } + UnsignedType.values().map { type -> type.typeName.asString() })
|
||||
.map { name -> name.toLowerCaseAsciiOnly() + "ArrayOf" }.toSet()
|
||||
|
||||
internal const val ARRAY_OF_NAME = "arrayOf"
|
||||
|
||||
internal fun IrFunction.isArrayOf(): Boolean {
|
||||
val parent = when (val directParent = parent) {
|
||||
is IrClass -> directParent.getPackageFragment() ?: return false
|
||||
is IrPackageFragment -> directParent
|
||||
else -> return false
|
||||
}
|
||||
return parent.fqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME &&
|
||||
name.asString().let { it in PRIMITIVE_ARRAY_OF_NAMES || it == ARRAY_OF_NAME } &&
|
||||
extensionReceiverParameter == null &&
|
||||
dispatchReceiverParameter == null &&
|
||||
valueParameters.size == 1 &&
|
||||
valueParameters[0].isVararg
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// IGNORE_BACKEND: WASM
|
||||
|
||||
fun use(fn: (Array<String>) -> Array<String>) =
|
||||
fn(arrayOf("OK"))
|
||||
|
||||
fun box(): String {
|
||||
return use(::arrayOf)[0]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
|
||||
fun box(): String {
|
||||
val ref: (CharArray) -> CharArray = ::charArrayOf
|
||||
val arr = ref(charArrayOf('O', 'K'))
|
||||
return "${arr[0]}${arr[1]}"
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: arrayOf.kt
|
||||
fun box() =
|
||||
Sam(::arrayOf).get(arrayOf("OK"))[0]
|
||||
|
||||
// FILE: Sam.java
|
||||
public interface Sam {
|
||||
String[] get(String[] s);
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// SAM_CONVERSIONS: INDY
|
||||
|
||||
// CHECK_BYTECODE_TEXT
|
||||
// JVM_IR_TEMPLATES
|
||||
// 0 java/lang/invoke/LambdaMetafactory
|
||||
|
||||
// FILE: charArrayOf.kt
|
||||
fun box(): String {
|
||||
val sam = Sam(::charArrayOf)
|
||||
val arr = sam.get(charArrayOf('O', 'K'))
|
||||
return "${arr[0]}${arr[1]}"
|
||||
}
|
||||
|
||||
// FILE: Sam.java
|
||||
public interface Sam {
|
||||
char[] get(char[] s);
|
||||
}
|
||||
+24
@@ -2440,12 +2440,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayConstructorArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("builtinFunctionReferenceOwner.kt")
|
||||
public void testBuiltinFunctionReferenceOwner() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/builtinFunctionReferenceOwner.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classesAreSynthetic.kt")
|
||||
public void testClassesAreSynthetic() throws Exception {
|
||||
@@ -21413,6 +21425,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayConstructor.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enumValueOf.kt")
|
||||
public void testEnumValueOf() throws Exception {
|
||||
|
||||
+24
@@ -2440,12 +2440,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayConstructorArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("builtinFunctionReferenceOwner.kt")
|
||||
public void testBuiltinFunctionReferenceOwner() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/builtinFunctionReferenceOwner.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classesAreSynthetic.kt")
|
||||
public void testClassesAreSynthetic() throws Exception {
|
||||
@@ -21437,6 +21449,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayConstructor.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enumValueOf.kt")
|
||||
public void testEnumValueOf() throws Exception {
|
||||
|
||||
+20
@@ -2165,11 +2165,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayConstructorArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("builtinFunctionReferenceOwner.kt")
|
||||
public void testBuiltinFunctionReferenceOwner() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/builtinFunctionReferenceOwner.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classesAreSynthetic.kt")
|
||||
public void testClassesAreSynthetic() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/classesAreSynthetic.kt");
|
||||
@@ -17903,6 +17913,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumValueOf.kt")
|
||||
public void testEnumValueOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValueOf.kt");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+10
@@ -1460,6 +1460,16 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayConstructorArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericConstructorReference.kt")
|
||||
public void testGenericConstructorReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/genericConstructorReference.kt");
|
||||
|
||||
Generated
+10
@@ -1460,6 +1460,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayConstructorArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericConstructorReference.kt")
|
||||
public void testGenericConstructorReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/genericConstructorReference.kt");
|
||||
|
||||
Generated
+10
@@ -1460,6 +1460,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayConstructorArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericConstructorReference.kt")
|
||||
public void testGenericConstructorReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/genericConstructorReference.kt");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+10
@@ -1265,6 +1265,16 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/callableReference"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrayOf.kt")
|
||||
public void testArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("charArrayOf.kt")
|
||||
public void testCharArrayOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/charArrayOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineArrayConstructors.kt")
|
||||
public void testInlineArrayConstructors() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/inlineArrayConstructors.kt");
|
||||
|
||||
Reference in New Issue
Block a user