KT-37779 Treat named value arguments in vararg as arguments with '*'

This commit is contained in:
Dmitry Petrov
2020-04-06 19:12:43 +03:00
parent fa9d79392f
commit dae8872aba
15 changed files with 118 additions and 15 deletions
@@ -3141,15 +3141,16 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
List<ValueArgument> 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);
@@ -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");
@@ -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");
@@ -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
+8
View File
@@ -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"))
@@ -1,4 +1,4 @@
// !LANGUAGE: -ProhibitAssigningSingleElementsToVarargsInNamedForm
// !LANGUAGE: -ProhibitAssigningSingleElementsToVarargsInNamedForm -AllowAssigningArrayElementsToVarargsInNamedFormForFunctions
// IGNORE_BACKEND_FIR: JVM_IR
fun box(): String {
+19
View File
@@ -0,0 +1,19 @@
FILE fqName:<root> fileName:/kt37779.kt
FUN name:foo visibility:public modality:FINAL <> (s:kotlin.Array<out kotlin.String>) returnType:kotlin.Unit
VALUE_PARAMETER name:s index:0 type:kotlin.Array<out kotlin.String> 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 <root>' type=kotlin.Unit origin=null
s: VARARG type=kotlin.Array<out kotlin.String> varargElementType=kotlin.String
CALL 'public final fun arrayOf <T> (vararg elements: T of kotlin.arrayOf): kotlin.Array<T of kotlin.arrayOf> [inline] declared in kotlin' type=kotlin.Array<kotlin.String> origin=null
<T>: kotlin.String
elements: VARARG type=kotlin.Array<out kotlin.String> 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<kotlin.String>) returnType:kotlin.Unit
VALUE_PARAMETER name:ss index:0 type:kotlin.Array<kotlin.String>
BLOCK_BODY
CALL 'public final fun foo (vararg s: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
s: VARARG type=kotlin.Array<out kotlin.String> varargElementType=kotlin.String
GET_VAR 'ss: kotlin.Array<kotlin.String> declared in <root>.test2' type=kotlin.Array<kotlin.String> origin=null
+10
View File
@@ -0,0 +1,10 @@
// !LANGUAGE: +AllowAssigningArrayElementsToVarargsInNamedFormForFunctions
fun foo(vararg s: String) {}
fun test1() {
foo(s = arrayOf("", "OK"))
}
fun test2(ss: Array<String>) {
foo(s = ss)
}
+21
View File
@@ -0,0 +1,21 @@
FILE fqName:<root> fileName:/kt37779.kt
FUN name:foo visibility:public modality:FINAL <> (s:kotlin.Array<out kotlin.String>) returnType:kotlin.Unit
VALUE_PARAMETER name:s index:0 type:kotlin.Array<out kotlin.String> 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 <root>' type=kotlin.Unit origin=null
s: VARARG type=kotlin.Array<out kotlin.String> varargElementType=kotlin.String
SPREAD_ELEMENT
CALL 'public final fun arrayOf <T> (vararg elements: T of kotlin.arrayOf): kotlin.Array<T of kotlin.arrayOf> [inline] declared in kotlin' type=kotlin.Array<kotlin.String> origin=null
<T>: kotlin.String
elements: VARARG type=kotlin.Array<out kotlin.String> 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<kotlin.String>) returnType:kotlin.Unit
VALUE_PARAMETER name:ss index:0 type:kotlin.Array<kotlin.String>
BLOCK_BODY
CALL 'public final fun foo (vararg s: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
s: VARARG type=kotlin.Array<out kotlin.String> varargElementType=kotlin.String
SPREAD_ELEMENT
GET_VAR 'ss: kotlin.Array<kotlin.String> declared in <root>.test2' type=kotlin.Array<kotlin.String> origin=null
@@ -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");
@@ -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");
@@ -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");
@@ -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");
@@ -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");
@@ -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");