From 9e03b712dec51b4d2fb08706d07e557f778bda7e Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 27 Feb 2017 13:17:58 +0300 Subject: [PATCH] Use flexible upper bound of parameter's type for vararg argument See the issue and the test. The problem was that when generating call to `foo` method in member scope of `AT<*>` its resulting descriptor after substitution and approximation was: fun foo(x: Nothing..Array). This signature is correct, but when using this parameter type for generating a vararg argument the assertion is violated that the type of the argument must be an array (by default we're using lower flexible bound everywhere) The solution is using upper bound for flexible types that should always have a form of Array for varargs (even for such corner cases) both for Kotlin and Java declarations. #KT-14607 Fixed --- .../codegen/CallBasedArgumentGenerator.java | 5 ++++- .../codegen/box/arrays/varargsWithJava.kt | 20 +++++++++++++++++++ .../light-analysis/arrays/varargsWithJava.txt | 5 +++++ .../ir/IrBlackBoxCodegenTestGenerated.java | 6 ++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++++++ .../semantics/JsCodegenBoxTestGenerated.java | 6 ++++++ 6 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/box/arrays/varargsWithJava.kt create mode 100644 compiler/testData/codegen/light-analysis/arrays/varargsWithJava.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.java index e83e751031d..76502211980 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallBasedArgumentGenerator.java @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; import org.jetbrains.kotlin.psi.KtExpression; import org.jetbrains.kotlin.psi.ValueArgument; import org.jetbrains.kotlin.resolve.calls.model.*; +import org.jetbrains.kotlin.types.FlexibleTypesKt; import org.jetbrains.org.objectweb.asm.Type; import java.util.List; @@ -84,7 +85,9 @@ public class CallBasedArgumentGenerator extends ArgumentGenerator { protected void generateVararg(int i, @NotNull VarargValueArgument argument) { ValueParameterDescriptor parameter = valueParameters.get(i); Type type = valueParameterTypes.get(i); - codegen.genVarargs(argument, parameter.getType()); + // Upper bound for type of vararg parameter should always have a form of 'Array', + // while its lower bound may be Nothing-typed after approximation + codegen.genVarargs(argument, FlexibleTypesKt.upperIfFlexible(parameter.getType())); callGenerator.afterParameterPut(type, null, i); } diff --git a/compiler/testData/codegen/box/arrays/varargsWithJava.kt b/compiler/testData/codegen/box/arrays/varargsWithJava.kt new file mode 100644 index 00000000000..15c10754d24 --- /dev/null +++ b/compiler/testData/codegen/box/arrays/varargsWithJava.kt @@ -0,0 +1,20 @@ +// FILE: AT.java + +public class AT { + public String result = "fail"; + public void foo(G ...y) { + result = "OK"; + } +} + +// FILE: main.kt + +fun AT<*>.bar() { + foo() +} + +fun box(): String { + val a = AT() + a.bar() + return a.result +} diff --git a/compiler/testData/codegen/light-analysis/arrays/varargsWithJava.txt b/compiler/testData/codegen/light-analysis/arrays/varargsWithJava.txt new file mode 100644 index 00000000000..1292de5ede5 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/arrays/varargsWithJava.txt @@ -0,0 +1,5 @@ +@kotlin.Metadata +public final class MainKt { + public final static method bar(@org.jetbrains.annotations.NotNull p0: AT): void + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 038acb4bea4..b24e5d3e618 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -617,6 +617,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("varargsWithJava.kt") + public void testVarargsWithJava() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/varargsWithJava.kt"); + doTest(fileName); + } + @TestMetadata("compiler/testData/codegen/box/arrays/multiDecl") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 03d3ab26acc..917794eb593 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -617,6 +617,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("varargsWithJava.kt") + public void testVarargsWithJava() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/varargsWithJava.kt"); + doTest(fileName); + } + @TestMetadata("compiler/testData/codegen/box/arrays/multiDecl") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) 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 2bed4a68078..938fc94ab2e 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 @@ -809,6 +809,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("varargsWithJava.kt") + public void testVarargsWithJava() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/arrays/varargsWithJava.kt"); + doTest(fileName); + } + @TestMetadata("compiler/testData/codegen/box/arrays/multiDecl") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)