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<out Nothing>).

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<out T> for varargs (even for such corner cases)
both for Kotlin and Java declarations.

 #KT-14607 Fixed
This commit is contained in:
Denis Zharkov
2017-02-27 13:17:58 +03:00
parent 14dad61fe5
commit 9e03b712de
6 changed files with 47 additions and 1 deletions
@@ -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<out T>',
// while its lower bound may be Nothing-typed after approximation
codegen.genVarargs(argument, FlexibleTypesKt.upperIfFlexible(parameter.getType()));
callGenerator.afterParameterPut(type, null, i);
}
+20
View File
@@ -0,0 +1,20 @@
// FILE: AT.java
public class AT<G> {
public String result = "fail";
public void foo(G ...y) {
result = "OK";
}
}
// FILE: main.kt
fun AT<*>.bar() {
foo()
}
fun box(): String {
val a = AT<String>()
a.bar()
return a.result
}
@@ -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
}
@@ -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)
@@ -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)
@@ -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)