From dae8872abab551edc093e5714dbeb5ed5af4b5a1 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 6 Apr 2020 19:12:43 +0300 Subject: [PATCH] KT-37779 Treat named value arguments in vararg as arguments with '*' --- .../kotlin/codegen/ExpressionCodegen.java | 17 ++++++++------- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++++ .../kotlin/fir/Fir2IrTextTestGenerated.java | 5 +++++ .../generators/ArgumentsGenerationUtils.kt | 6 +++++- .../testData/codegen/box/vararg/kt37779.kt | 8 +++++++ .../singleAssignmentToVarargsInFunction.kt | 2 +- .../ir/irText/expressions/kt37779.fir.txt | 19 +++++++++++++++++ .../testData/ir/irText/expressions/kt37779.kt | 10 +++++++++ .../ir/irText/expressions/kt37779.txt | 21 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++++ .../LightAnalysisModeTestGenerated.java | 15 ++++++++----- .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++++ .../kotlin/ir/IrTextTestCaseGenerated.java | 5 +++++ .../IrJsCodegenBoxTestGenerated.java | 5 +++++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++++ 15 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 compiler/testData/codegen/box/vararg/kt37779.kt create mode 100644 compiler/testData/ir/irText/expressions/kt37779.fir.txt create mode 100644 compiler/testData/ir/irText/expressions/kt37779.kt create mode 100644 compiler/testData/ir/irText/expressions/kt37779.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index dfda7cc7100..4aacd7e8b4c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -3141,15 +3141,16 @@ public class ExpressionCodegen extends KtVisitor impleme List arguments = valueArgument.getArguments(); int size = arguments.size(); - boolean hasSpread = false; - for (int i = 0; i != size; ++i) { - if (arguments.get(i).getSpreadElement() != null) { - hasSpread = true; - break; - } - } + // Named arguments in vararg are treated as having an implicit spread operator. + // There can be only single such argument for a given vararg parameter, but here it doesn't really matter: + // we'll just build a copy of array as if an array argument was passed as positional with an explicit spread operator. + boolean hasSpreadOperator = + state.getLanguageVersionSettings() + .supportsFeature(LanguageFeature.AllowAssigningArrayElementsToVarargsInNamedFormForFunctions) + ? arguments.stream().anyMatch(argument -> argument.getSpreadElement() != null || argument.isNamed()) + : arguments.stream().anyMatch(argument -> argument.getSpreadElement() != null); - if (hasSpread) { + if (hasSpreadOperator) { boolean arrayOfReferences = KotlinBuiltIns.isArray(outType); if (size == 1) { Type arrayType = getArrayType(arrayOfReferences ? AsmTypes.OBJECT_TYPE : elementType); diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 07e3cc51801..378729caafd 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -27974,6 +27974,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/vararg/kt1978.kt"); } + @TestMetadata("kt37779.kt") + public void testKt37779() throws Exception { + runTest("compiler/testData/codegen/box/vararg/kt37779.kt"); + } + @TestMetadata("kt581.kt") public void testKt581() throws Exception { runTest("compiler/testData/codegen/box/vararg/kt581.kt"); diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java index 91c95af4485..ecd4db91170 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/fir/Fir2IrTextTestGenerated.java @@ -1087,6 +1087,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest { runTest("compiler/testData/ir/irText/expressions/kt37570.kt"); } + @TestMetadata("kt37779.kt") + public void testKt37779() throws Exception { + runTest("compiler/testData/ir/irText/expressions/kt37779.kt"); + } + @TestMetadata("lambdaInCAO.kt") public void testLambdaInCAO() throws Exception { runTest("compiler/testData/ir/irText/expressions/lambdaInCAO.kt"); diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt index ecfe3a3b9d4..2a6f107e0f2 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt @@ -262,7 +262,11 @@ fun StatementGenerator.generateVarargExpressionUsing( val irArgumentExpression = generateArgumentExpression(ktArgumentExpression) ?: throw AssertionError("'generateArgumentExpression' should return non-null for vararg element ${ktArgumentExpression.text}") val irVarargElement = - if (argument.getSpreadElement() != null) + if (argument.getSpreadElement() != null || + context.languageVersionSettings + .supportsFeature(LanguageFeature.AllowAssigningArrayElementsToVarargsInNamedFormForFunctions) && + argument.isNamed() + ) IrSpreadElementImpl( ktArgumentExpression.startOffsetSkippingComments, ktArgumentExpression.endOffset, irArgumentExpression diff --git a/compiler/testData/codegen/box/vararg/kt37779.kt b/compiler/testData/codegen/box/vararg/kt37779.kt new file mode 100644 index 00000000000..d187e212f83 --- /dev/null +++ b/compiler/testData/codegen/box/vararg/kt37779.kt @@ -0,0 +1,8 @@ +// !LANGUAGE: +AllowAssigningArrayElementsToVarargsInNamedFormForFunctions +// IGNORE_BACKEND_FIR: JVM_IR +// IGNORE_BACKEND: JS + +fun test(vararg s: String) = s[1] + +fun box(): String = + test(s = arrayOf("", "OK")) \ No newline at end of file diff --git a/compiler/testData/codegen/box/vararg/singleAssignmentToVarargsInFunction.kt b/compiler/testData/codegen/box/vararg/singleAssignmentToVarargsInFunction.kt index 0ebfa09e668..8a07a67fc27 100644 --- a/compiler/testData/codegen/box/vararg/singleAssignmentToVarargsInFunction.kt +++ b/compiler/testData/codegen/box/vararg/singleAssignmentToVarargsInFunction.kt @@ -1,4 +1,4 @@ -// !LANGUAGE: -ProhibitAssigningSingleElementsToVarargsInNamedForm +// !LANGUAGE: -ProhibitAssigningSingleElementsToVarargsInNamedForm -AllowAssigningArrayElementsToVarargsInNamedFormForFunctions // IGNORE_BACKEND_FIR: JVM_IR fun box(): String { diff --git a/compiler/testData/ir/irText/expressions/kt37779.fir.txt b/compiler/testData/ir/irText/expressions/kt37779.fir.txt new file mode 100644 index 00000000000..aff9c793413 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/kt37779.fir.txt @@ -0,0 +1,19 @@ +FILE fqName: fileName:/kt37779.kt + FUN name:foo visibility:public modality:FINAL <> (s:kotlin.Array) returnType:kotlin.Unit + VALUE_PARAMETER name:s index:0 type:kotlin.Array varargElementType:kotlin.String [vararg] + BLOCK_BODY + FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + CALL 'public final fun foo (vararg s: kotlin.String): kotlin.Unit declared in ' type=kotlin.Unit origin=null + s: VARARG type=kotlin.Array varargElementType=kotlin.String + CALL 'public final fun arrayOf (vararg elements: T of kotlin.arrayOf): kotlin.Array [inline] declared in kotlin' type=kotlin.Array origin=null + : kotlin.String + elements: VARARG type=kotlin.Array varargElementType=kotlin.String + CONST String type=kotlin.String value="" + CONST String type=kotlin.String value="OK" + FUN name:test2 visibility:public modality:FINAL <> (ss:kotlin.Array) returnType:kotlin.Unit + VALUE_PARAMETER name:ss index:0 type:kotlin.Array + BLOCK_BODY + CALL 'public final fun foo (vararg s: kotlin.String): kotlin.Unit declared in ' type=kotlin.Unit origin=null + s: VARARG type=kotlin.Array varargElementType=kotlin.String + GET_VAR 'ss: kotlin.Array declared in .test2' type=kotlin.Array origin=null diff --git a/compiler/testData/ir/irText/expressions/kt37779.kt b/compiler/testData/ir/irText/expressions/kt37779.kt new file mode 100644 index 00000000000..94a1899c346 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/kt37779.kt @@ -0,0 +1,10 @@ +// !LANGUAGE: +AllowAssigningArrayElementsToVarargsInNamedFormForFunctions +fun foo(vararg s: String) {} + +fun test1() { + foo(s = arrayOf("", "OK")) +} + +fun test2(ss: Array) { + foo(s = ss) +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/kt37779.txt b/compiler/testData/ir/irText/expressions/kt37779.txt new file mode 100644 index 00000000000..9e6ed63477b --- /dev/null +++ b/compiler/testData/ir/irText/expressions/kt37779.txt @@ -0,0 +1,21 @@ +FILE fqName: fileName:/kt37779.kt + FUN name:foo visibility:public modality:FINAL <> (s:kotlin.Array) returnType:kotlin.Unit + VALUE_PARAMETER name:s index:0 type:kotlin.Array varargElementType:kotlin.String [vararg] + BLOCK_BODY + FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit + BLOCK_BODY + CALL 'public final fun foo (vararg s: kotlin.String): kotlin.Unit declared in ' type=kotlin.Unit origin=null + s: VARARG type=kotlin.Array varargElementType=kotlin.String + SPREAD_ELEMENT + CALL 'public final fun arrayOf (vararg elements: T of kotlin.arrayOf): kotlin.Array [inline] declared in kotlin' type=kotlin.Array origin=null + : kotlin.String + elements: VARARG type=kotlin.Array varargElementType=kotlin.String + CONST String type=kotlin.String value="" + CONST String type=kotlin.String value="OK" + FUN name:test2 visibility:public modality:FINAL <> (ss:kotlin.Array) returnType:kotlin.Unit + VALUE_PARAMETER name:ss index:0 type:kotlin.Array + BLOCK_BODY + CALL 'public final fun foo (vararg s: kotlin.String): kotlin.Unit declared in ' type=kotlin.Unit origin=null + s: VARARG type=kotlin.Array varargElementType=kotlin.String + SPREAD_ELEMENT + GET_VAR 'ss: kotlin.Array declared in .test2' type=kotlin.Array origin=null diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index d5e74b2aee7..87e1b693212 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -29535,6 +29535,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/vararg/kt1978.kt"); } + @TestMetadata("kt37779.kt") + public void testKt37779() throws Exception { + runTest("compiler/testData/codegen/box/vararg/kt37779.kt"); + } + @TestMetadata("kt581.kt") public void testKt581() throws Exception { runTest("compiler/testData/codegen/box/vararg/kt581.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index cdafed18ae3..7f86f85985f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -17611,6 +17611,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class Optimized extends AbstractLightAnalysisModeTest { + @TestMetadata("callableReferencesToSamePropertiesFromDifferentPackages.kt") + public void ignoreCallableReferencesToSamePropertiesFromDifferentPackages() throws Exception { + runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSamePropertiesFromDifferentPackages.kt"); + } + private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); } @@ -17649,11 +17654,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSameFunctionsFromDifferentPackages.kt"); } - @TestMetadata("callableReferencesToSamePropertiesFromDifferentPackages.kt") - public void testCallableReferencesToSamePropertiesFromDifferentPackages() throws Exception { - runTest("compiler/testData/codegen/box/multifileClasses/optimized/callableReferencesToSamePropertiesFromDifferentPackages.kt"); - } - @TestMetadata("calls.kt") public void testCalls() throws Exception { runTest("compiler/testData/codegen/box/multifileClasses/optimized/calls.kt"); @@ -28352,6 +28352,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/vararg/kt1978.kt"); } + @TestMetadata("kt37779.kt") + public void testKt37779() throws Exception { + runTest("compiler/testData/codegen/box/vararg/kt37779.kt"); + } + @TestMetadata("kt581.kt") public void testKt581() throws Exception { runTest("compiler/testData/codegen/box/vararg/kt581.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index aff7f468463..801acf6d818 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -27974,6 +27974,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/vararg/kt1978.kt"); } + @TestMetadata("kt37779.kt") + public void testKt37779() throws Exception { + runTest("compiler/testData/codegen/box/vararg/kt37779.kt"); + } + @TestMetadata("kt581.kt") public void testKt581() throws Exception { runTest("compiler/testData/codegen/box/vararg/kt581.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index e7978c4d85f..a828392d7d1 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -1086,6 +1086,11 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { runTest("compiler/testData/ir/irText/expressions/kt37570.kt"); } + @TestMetadata("kt37779.kt") + public void testKt37779() throws Exception { + runTest("compiler/testData/ir/irText/expressions/kt37779.kt"); + } + @TestMetadata("lambdaInCAO.kt") public void testLambdaInCAO() throws Exception { runTest("compiler/testData/ir/irText/expressions/lambdaInCAO.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index b754f0edf1d..24261f1979f 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -22795,6 +22795,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/vararg/kt1978.kt"); } + @TestMetadata("kt37779.kt") + public void testKt37779() throws Exception { + runTest("compiler/testData/codegen/box/vararg/kt37779.kt"); + } + @TestMetadata("kt581.kt") public void testKt581() throws Exception { runTest("compiler/testData/codegen/box/vararg/kt581.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 6858b091074..9c51b4cadc5 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -22855,6 +22855,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/vararg/kt1978.kt"); } + @TestMetadata("kt37779.kt") + public void testKt37779() throws Exception { + runTest("compiler/testData/codegen/box/vararg/kt37779.kt"); + } + @TestMetadata("kt581.kt") public void testKt581() throws Exception { runTest("compiler/testData/codegen/box/vararg/kt581.kt");