Fix exception on callBy of callable with more than 32 parameters

The previous condition that checked if we'd skipped any optional
parameters didn't work when number of parameters > 32 because the number
of bit masks in that case was more than one

 #KT-18404 Fixed
This commit is contained in:
Alexander Udalov
2017-06-19 16:44:05 +03:00
parent 62cd57b0d2
commit 90f2ea87a6
7 changed files with 262 additions and 1 deletions
@@ -0,0 +1,99 @@
// IGNORE_BACKEND: JS, NATIVE
// WITH_REFLECT
import kotlin.test.assertEquals
// Generate:
// (1..70).map { " p${"%02d".format(it)}: Int," }.joinToString("\n")
class A(
p01: Int,
p02: Int,
p03: Int,
p04: Int,
p05: Int,
p06: Int,
p07: Int,
p08: Int,
p09: Int,
p10: Int,
p11: Int,
p12: Int,
p13: Int,
p14: Int,
p15: Int,
p16: Int,
p17: Int,
p18: Int,
p19: Int,
p20: Int,
p21: Int,
p22: Int,
p23: Int,
p24: Int,
p25: Int,
p26: Int,
p27: Int,
p28: Int,
p29: Int,
p30: Int,
p31: Int,
p32: Int,
p33: Int,
p34: Int,
p35: Int,
p36: Int,
p37: Int,
p38: Int,
p39: Int,
p40: Int,
p41: Int,
p42: Int,
p43: Int,
p44: Int,
p45: Int,
p46: Int,
p47: Int,
p48: Int,
p49: Int,
p50: Int,
p51: Int,
p52: Int,
p53: Int,
p54: Int,
p55: Int,
p56: Int,
p57: Int,
p58: Int,
p59: Int,
p60: Int,
p61: Int,
p62: Int,
p63: Int,
p64: Int,
p65: Int,
p66: Int,
p67: Int,
p68: Int,
p69: Int,
p70: Int
) {
init {
assertEquals(1, p01)
assertEquals(41, p41)
assertEquals(42, p42)
assertEquals(43, p43)
assertEquals(70, p70)
}
}
fun box(): String {
val f = A::class.constructors.single()
val parameters = f.parameters
f.callBy(mapOf(
*((1..70)).map { i -> parameters[i - 1] to i }.toTypedArray()
))
return "OK"
}
@@ -0,0 +1,100 @@
// IGNORE_BACKEND: JS, NATIVE
// WITH_REFLECT
import kotlin.test.assertEquals
// Generate:
// (1..70).map { " p${"%02d".format(it)}: Int," }.joinToString("\n")
class A {
fun foo(
p01: Int,
p02: Int,
p03: Int,
p04: Int,
p05: Int,
p06: Int,
p07: Int,
p08: Int,
p09: Int,
p10: Int,
p11: Int,
p12: Int,
p13: Int,
p14: Int,
p15: Int,
p16: Int,
p17: Int,
p18: Int,
p19: Int,
p20: Int,
p21: Int,
p22: Int,
p23: Int,
p24: Int,
p25: Int,
p26: Int,
p27: Int,
p28: Int,
p29: Int,
p30: Int,
p31: Int,
p32: Int,
p33: Int,
p34: Int,
p35: Int,
p36: Int,
p37: Int,
p38: Int,
p39: Int,
p40: Int,
p41: Int,
p42: Int,
p43: Int,
p44: Int,
p45: Int,
p46: Int,
p47: Int,
p48: Int,
p49: Int,
p50: Int,
p51: Int,
p52: Int,
p53: Int,
p54: Int,
p55: Int,
p56: Int,
p57: Int,
p58: Int,
p59: Int,
p60: Int,
p61: Int,
p62: Int,
p63: Int,
p64: Int,
p65: Int,
p66: Int,
p67: Int,
p68: Int,
p69: Int,
p70: Int
) {
assertEquals(1, p01)
assertEquals(41, p41)
assertEquals(42, p42)
assertEquals(43, p43)
assertEquals(70, p70)
}
}
fun box(): String {
val f = A::class.members.single { it.name == "foo" }
val parameters = f.parameters
f.callBy(mapOf(
parameters.first() to A(),
*((1..70)).map { i -> parameters[i] to i }.toTypedArray()
))
return "OK"
}
@@ -14176,6 +14176,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("manyArgumentsNoneDefaultConstructor.kt")
public void testManyArgumentsNoneDefaultConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsNoneDefaultConstructor.kt");
doTest(fileName);
}
@TestMetadata("manyArgumentsNoneDefaultFunction.kt")
public void testManyArgumentsNoneDefaultFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsNoneDefaultFunction.kt");
doTest(fileName);
}
@TestMetadata("manyArgumentsOnlyOneDefault.kt")
public void testManyArgumentsOnlyOneDefault() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsOnlyOneDefault.kt");
@@ -14176,6 +14176,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("manyArgumentsNoneDefaultConstructor.kt")
public void testManyArgumentsNoneDefaultConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsNoneDefaultConstructor.kt");
doTest(fileName);
}
@TestMetadata("manyArgumentsNoneDefaultFunction.kt")
public void testManyArgumentsNoneDefaultFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsNoneDefaultFunction.kt");
doTest(fileName);
}
@TestMetadata("manyArgumentsOnlyOneDefault.kt")
public void testManyArgumentsOnlyOneDefault() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsOnlyOneDefault.kt");
@@ -14176,6 +14176,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("manyArgumentsNoneDefaultConstructor.kt")
public void testManyArgumentsNoneDefaultConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsNoneDefaultConstructor.kt");
doTest(fileName);
}
@TestMetadata("manyArgumentsNoneDefaultFunction.kt")
public void testManyArgumentsNoneDefaultFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsNoneDefaultFunction.kt");
doTest(fileName);
}
@TestMetadata("manyArgumentsOnlyOneDefault.kt")
public void testManyArgumentsOnlyOneDefault() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsOnlyOneDefault.kt");
@@ -118,6 +118,7 @@ internal abstract class KCallableImpl<out R> : KCallable<R> {
var mask = 0
val masks = ArrayList<Int>(1)
var index = 0
var anyOptional = false
for (parameter in parameters) {
if (index != 0 && index % Integer.SIZE == 0) {
@@ -132,6 +133,7 @@ internal abstract class KCallableImpl<out R> : KCallable<R> {
parameter.isOptional -> {
arguments.add(defaultPrimitiveValue(parameter.type.javaType))
mask = mask or (1 shl (index % Integer.SIZE))
anyOptional = true
}
else -> {
throw IllegalArgumentException("No argument provided for a required parameter: $parameter")
@@ -143,7 +145,7 @@ internal abstract class KCallableImpl<out R> : KCallable<R> {
}
}
if (mask == 0 && masks.isEmpty()) {
if (!anyOptional) {
return call(*arguments.toTypedArray())
}
@@ -16306,6 +16306,30 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("manyArgumentsNoneDefaultConstructor.kt")
public void testManyArgumentsNoneDefaultConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsNoneDefaultConstructor.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("manyArgumentsNoneDefaultFunction.kt")
public void testManyArgumentsNoneDefaultFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsNoneDefaultFunction.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("manyArgumentsOnlyOneDefault.kt")
public void testManyArgumentsOnlyOneDefault() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/callBy/manyArgumentsOnlyOneDefault.kt");