Expand default parameters conditions on inlining default function

#KT-14564 Fixed
 #KT-10848 Fixed
 #KT-12497 Fixed
This commit is contained in:
Mikhael Bogdanov
2017-04-26 16:08:47 +02:00
parent d49e9d7064
commit 02cc5f6bc1
16 changed files with 483 additions and 23 deletions
@@ -21,6 +21,12 @@ import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.org.objectweb.asm.Type
enum class ValueKind {
GENERAL,
DEFAULT_MASK,
METHOD_HANDLE_IN_DEFAULT
}
abstract class CallGenerator {
internal class DefaultCallGenerator(private val codegen: ExpressionCodegen) : CallGenerator() {
@@ -67,8 +73,7 @@ abstract class CallGenerator {
stackValue.put(stackValue.type, codegen.v)
}
override fun putValueIfNeeded(
parameterType: Type, value: StackValue) {
override fun putValueIfNeeded(parameterType: Type, value: StackValue, kind: ValueKind) {
value.put(value.type, codegen.v)
}
@@ -117,9 +122,16 @@ abstract class CallGenerator {
parameterType: Type,
parameterIndex: Int)
fun putValueIfNeeded(
parameterType: Type,
value: StackValue) {
putValueIfNeeded(parameterType, value, ValueKind.GENERAL)
}
abstract fun putValueIfNeeded(
parameterType: Type,
value: StackValue)
value: StackValue,
kind: ValueKind)
abstract fun putCapturedValueOnStack(
stackValue: StackValue,
@@ -32,7 +32,7 @@ class DefaultCallArgs(val size: Int) {
bits.set(index)
}
fun toInts(): List<Int> {
private fun toInts(): List<Int> {
if (bits.isEmpty || size == 0) {
return emptyList()
}
@@ -56,11 +56,11 @@ class DefaultCallArgs(val size: Int) {
val toInts = toInts()
if (!toInts.isEmpty()) {
for (mask in toInts) {
callGenerator.putValueIfNeeded(Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE))
callGenerator.putValueIfNeeded(Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE), ValueKind.DEFAULT_MASK)
}
val parameterType = if (isConstructor) AsmTypes.DEFAULT_CONSTRUCTOR_MARKER else AsmTypes.OBJECT_TYPE
callGenerator.putValueIfNeeded(parameterType, StackValue.constant(null, parameterType))
callGenerator.putValueIfNeeded(parameterType, StackValue.constant(null, parameterType), ValueKind.METHOD_HANDLE_IN_DEFAULT)
}
return toInts.isNotEmpty()
}
@@ -741,9 +741,9 @@ public abstract class StackValue {
}
}
private static class Constant extends StackValue {
public static class Constant extends StackValue {
@Nullable
private final Object value;
public final Object value;
public Constant(@Nullable Object value, Type type) {
super(type, false);
@@ -101,6 +101,10 @@ public class InlineCodegen extends CallGenerator {
private Runnable delayedHiddenWriting;
private List<Integer> maskValues = new ArrayList<>();
private int maskStartIndex = -1;
private int methodHandleInDefaultMethodIndex = -1;
public InlineCodegen(
@NotNull ExpressionCodegen codegen,
@NotNull GenerationState state,
@@ -177,7 +181,7 @@ public class InlineCodegen extends CallGenerator {
SMAPAndMethodNode nodeAndSmap = null;
try {
nodeAndSmap = createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, resolvedCall);
endCall(inlineCall(nodeAndSmap));
endCall(inlineCall(nodeAndSmap, callDefault));
}
catch (CompilationException e) {
throw e;
@@ -378,7 +382,7 @@ public class InlineCodegen extends CallGenerator {
implementationOwner.getInternalName()
);
if (!(element instanceof KtNamedFunction)) {
throw new IllegalStateException("Propertiy accessors with default parameters not supported " + callableDescriptor);
throw new IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor);
}
FunctionCodegen.generateDefaultImplBody(
methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
@@ -404,11 +408,14 @@ public class InlineCodegen extends CallGenerator {
}
@NotNull
private InlineResult inlineCall(@NotNull SMAPAndMethodNode nodeAndSmap) {
private InlineResult inlineCall(@NotNull SMAPAndMethodNode nodeAndSmap, boolean callDefault) {
assert delayedHiddenWriting == null : "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'";
DefaultSourceMapper defaultSourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
defaultSourceMapper.setCallSiteMarker(new CallSiteMarker(codegen.getLastLineNumber()));
MethodNode node = nodeAndSmap.getNode();
if (callDefault) {
MethodInlinerUtilKt.expandMaskConditions(node, maskStartIndex, maskValues, methodHandleInDefaultMethodIndex);
}
ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node);
generateClosuresBodies();
@@ -676,7 +683,7 @@ public class InlineCodegen extends CallGenerator {
) {
if (!asFunctionInline && Type.VOID_TYPE != type) {
//TODO remap only inlinable closure => otherwise we could get a lot of problem
boolean couldBeRemapped = !shouldPutValue(type, stackValue);
boolean couldBeRemapped = !shouldPutGeneralValue(type, stackValue);
StackValue remappedValue = couldBeRemapped ? stackValue : null;
ParameterInfo info;
@@ -694,7 +701,7 @@ public class InlineCodegen extends CallGenerator {
}
/*descriptor is null for captured vars*/
private static boolean shouldPutValue(@NotNull Type type, @Nullable StackValue stackValue) {
private static boolean shouldPutGeneralValue(@NotNull Type type, @Nullable StackValue stackValue) {
if (stackValue == null) {
//default or vararg
return true;
@@ -899,7 +906,7 @@ public class InlineCodegen extends CallGenerator {
}
else {
StackValue value = codegen.gen(argumentExpression);
putValueIfNeeded(parameterType, value, valueParameterDescriptor.getIndex());
putValueIfNeeded(parameterType, value, valueParameterDescriptor.getIndex(), ValueKind.GENERAL);
}
}
@@ -918,20 +925,44 @@ public class InlineCodegen extends CallGenerator {
}
@Override
public void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value) {
putValueIfNeeded(parameterType, value, -1);
public void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value, @NotNull ValueKind kind) {
putValueIfNeeded(parameterType, value, -1, kind);
}
private void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value, int index) {
if (shouldPutValue(parameterType, value)) {
private void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value, int index, @NotNull ValueKind kind) {
if (processDefaultMaskOrMethodHandler(value, kind)) return;
assert maskValues.isEmpty() : "Additional default call arguments should be last ones, but " + value;
if (shouldPutGeneralValue(parameterType, value)) {
value.put(parameterType, codegen.v);
}
afterParameterPut(parameterType, value, index);
}
private boolean processDefaultMaskOrMethodHandler(@NotNull StackValue value, @NotNull ValueKind kind) {
if (kind != ValueKind.DEFAULT_MASK && kind != ValueKind.METHOD_HANDLE_IN_DEFAULT) {
return false;
}
assert value instanceof StackValue.Constant : "Additional default method argument should be constant, but " + value;
Object constantValue = ((StackValue.Constant) value).value;
if (kind == ValueKind.DEFAULT_MASK) {
assert constantValue instanceof Integer : "Mask should be of Integer type, but " + constantValue;
maskValues.add((Integer) constantValue);
if (maskStartIndex == -1) {
maskStartIndex = invocationParamBuilder.getNextParameterOffset();
}
}
else {
assert constantValue == null : "Additional method handle for default argument should be null, but " + constantValue;
methodHandleInDefaultMethodIndex = maskStartIndex + maskValues.size();
}
return true;
}
@Override
public void putCapturedValueOnStack(@NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex) {
if (shouldPutValue(stackValue.type, stackValue)) {
if (shouldPutGeneralValue(stackValue.type, stackValue)) {
stackValue.put(stackValue.type, codegen.v);
}
putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex, paramIndex);
@@ -95,7 +95,7 @@ class InlineCodegenForDefaultBody(
throw UnsupportedOperationException("Shouldn't be called")
}
override fun putValueIfNeeded(parameterType: Type, value: StackValue) {
override fun putValueIfNeeded(parameterType: Type, value: StackValue, kind: ValueKind) {
//original method would be inlined directly into default impl body without any inline magic
//so we no need to load variables on stack to further method call
}
@@ -16,12 +16,12 @@
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
import org.jetbrains.kotlin.codegen.optimization.common.asSequence
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.InsnList
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
@@ -88,3 +88,63 @@ private fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
}
fun SourceValue.singleOrNullInsn() = insns.singleOrNull()
fun expandMaskConditions(node: MethodNode, maskStartIndex: Int, masks: List<Int>, methodHandlerIndex: Int) {
class Condition(mask: Int, constant: Int, val maskInstruction: VarInsnNode, val jumpInstruction: JumpInsnNode) {
val expandNotDelete = mask and constant != 0
}
val maskProcessingHeader = node.instructions.asSequence().takeWhile {
if (it is VarInsnNode) {
if (isMaskIndex(it, maskStartIndex, masks)) {
/*if slot for default mask is updated than we occurred in actual function body*/
return@takeWhile it.opcode == Opcodes.ILOAD
}
else if (isMethodHandleIndex(methodHandlerIndex, it)) {
return@takeWhile it.opcode == Opcodes.ALOAD
}
}
true
}
val conditions = maskProcessingHeader.filterIsInstance<VarInsnNode>().mapNotNull {
if (isMaskIndex(it, maskStartIndex, masks) &&
it.next?.next?.opcode == Opcodes.IAND &&
it.next.next.next?.opcode == Opcodes.IFEQ) {
Condition(
masks[it.`var` - maskStartIndex],
InlineCodegenUtil.getConstant(it.next),
it,
it.next?.next?.next as JumpInsnNode
)
}
else if (isMethodHandleIndex(methodHandlerIndex, it) &&
it.next?.opcode == Opcodes.IFNULL &&
it.next.next?.opcode == Opcodes.NEW) {
//Always delete method handle for now
//This logic should be updated when method handles would be supported
Condition(0, 0, it,it.next as JumpInsnNode)
}
else null
}
val toDelete = arrayListOf<AbstractInsnNode>()
conditions.forEach {
val jumpInstruction = it.jumpInstruction
InsnSequence(it.maskInstruction, (if (it.expandNotDelete) jumpInstruction.next else jumpInstruction.label)).forEach {
toDelete.add(it)
}
}
toDelete.forEach {
node.instructions.remove(it)
}
}
private fun isMethodHandleIndex(methodHandlerIndex: Int, it: VarInsnNode) = methodHandlerIndex == it.`var`
private fun isMaskIndex(variable: VarInsnNode, maskStartIndex: Int, masks: List<Int>): Boolean {
val varIndex = variable.`var`
return maskStartIndex <= varIndex && varIndex < maskStartIndex + masks.size
}
@@ -0,0 +1,36 @@
// FILE: 1.kt
//NO_CHECK_LAMBDA_INLINING
package test
object TimeUtil {
inline fun waitForEx(retryWait: Int = 200,
action: () -> Boolean) {
var now = 1L
if (now++ <= 3) {
action()
}
}
}
// FILE: 2.kt
import test.*
var result = "fail"
fun box(): String {
TimeUtil.waitForEx(
action = {
try {
result = "OK"
true
}
catch (t: Throwable) {
false
}
})
return result
}
@@ -0,0 +1,33 @@
// FILE: 1.kt
package test
var result = "fail"
object TimeUtil {
fun waitForAssert(z: String) {
waitForEx(
action = {
result = z
result
})
}
inline fun waitForEx(retryWait: Int = 200,
action: () -> String) {
var now = 1L
now++
action()
}
}
// FILE: 2.kt
import test.*
fun box(): String {
TimeUtil.waitForAssert("OK")
return result
}
@@ -0,0 +1,66 @@
// FILE: 1.kt
package test
fun calc() = "OK"
inline fun test(
p1: String = "1",
p2: String = "2",
p3: String = "3",
p4: String = "4",
p5: String = "5",
p6: String = "6",
p7: String = "7",
p8: String = "8",
p9: String = "9",
p10: String = "10",
p11: String = "11",
p12: String = "12",
p13: String = "13",
p14: String = "14",
p15: String = "15",
p16: String = "16",
p17: String = "17",
p18: String = "18",
p19: String = "19",
p20: String = "20",
p21: String = "21",
p22: String = "22",
p23: String = "23",
p24: String = "24",
p25: String = "25",
p26: String = "26",
p27: String = "27",
p28: String = "28",
p29: String = "29",
p30: String = "30",
p31: String = "31",
p32: String = "32"
): String {
return p1 + " " + p2 + " " + p3 + " " + p4 + " " + p5 + " " + p6 + " " +
p7 + " " + p8 + " " + p9 + " " + p10 + " " + p11 + " " + p12 + " " + p13 + " " + p14 + " " +
p15 + " " + p16 + " " + p17 + " " + p18 + " " + p19 + " " + p20 + " " + p21 + " " +
p22 + " " + p23 + " " + p24 + " " + p25 + " " + p26 + " " + p27 + " " + p28 + " " +
p29 + " " + p30 + " " + p31 + " " + p32
}
// FILE: 2.kt
import test.*
fun box(): String {
if (test() != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32")
return "fail 1: ${test()}"
if (test(p20 = "OK") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 OK 21 22 23 24 25 26 27 28 29 30 31 32")
return "fail 2: ${test(p20 = "OK")}"
if (test(p20 = "O", p22 = "K") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 O 21 K 23 24 25 26 27 28 29 30 31 32")
return "fail 3: ${test(p20 = "O", p22 = "K")}"
if (test(p20 = "O", p22 = "K", p32 = "23") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 O 21 K 23 24 25 26 27 28 29 30 31 23")
return "fail 4: ${test(p20 = "O", p22 = "K", p32 = "23")}"
return "OK"
}
@@ -0,0 +1,70 @@
// FILE: 1.kt
package test
fun calc() = "OK"
inline fun test(
p1: String = "1",
p2: String = "2",
p3: String = "3",
p4: String = "4",
p5: String = "5",
p6: String = "6",
p7: String = "7",
p8: String = "8",
p9: String = "9",
p10: String = "10",
p11: String = "11",
p12: String = "12",
p13: String = "13",
p14: String = "14",
p15: String = "15",
p16: String = "16",
p17: String = "17",
p18: String = "18",
p19: String = "19",
p20: String = "20",
p21: String = "21",
p22: String = "22",
p23: String = "23",
p24: String = "24",
p25: String = "25",
p26: String = "26",
p27: String = "27",
p28: String = "28",
p29: String = "29",
p30: String = "30",
p31: String = "31",
p32: String = "32",
p33: String = "33"
): String {
return p1 + " " + p2 + " " + p3 + " " + p4 + " " + p5 + " " + p6 + " " +
p7 + " " + p8 + " " + p9 + " " + p10 + " " + p11 + " " + p12 + " " + p13 + " " + p14 + " " +
p15 + " " + p16 + " " + p17 + " " + p18 + " " + p19 + " " + p20 + " " + p21 + " " +
p22 + " " + p23 + " " + p24 + " " + p25 + " " + p26 + " " + p27 + " " + p28 + " " +
p29 + " " + p30 + " " + p31 + " " + p32 + " " + p33
}
// FILE: 2.kt
import test.*
fun box(): String {
if (test() != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33")
return "fail 1: ${test()}"
if (test(p20 = "OK") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 OK 21 22 23 24 25 26 27 28 29 30 31 32 33")
return "fail 2: ${test(p20 = "OK")}"
if (test(p20 = "O", p22 = "K") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 O 21 K 23 24 25 26 27 28 29 30 31 32 33")
return "fail 3: ${test(p20 = "O", p22 = "K")}"
if (test(p20 = "O", p22 = "K", p32 = "23") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 O 21 K 23 24 25 26 27 28 29 30 31 23 33")
return "fail 4: ${test(p20 = "O", p22 = "K", p32 = "23")}"
if (test(p20 = "O", p22 = "K", p32 = "33", p33 ="32") != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 O 21 K 23 24 25 26 27 28 29 30 31 33 32")
return "fail 4: ${test(p20 = "O", p22 = "K", p32 = "33", p33 ="32")}"
return "OK"
}
@@ -0,0 +1,36 @@
// FILE: 1.kt
package test
fun calc() = "OK"
/*open modifier for method handle check in default method*/
open class A {
inline fun test(p: String = calc()): String {
return p
}
inline fun String.testExt(p: String = "K"): String {
return this + p
}
fun callExt(): String {
return "O".testExt()
}
fun callExt(arg: String): String {
return "O".testExt(arg)
}
}
// FILE: 2.kt
import test.*
fun box() : String {
if (A().callExt() != "OK") return "fail 1: ${A().callExt()}"
if (A().callExt("O") != "OO") return "fail 2: ${A().callExt("O")}"
if (A().test("KK") != "KK") return "fail 3: ${A().test("KK")}"
return A().test()
}
@@ -0,0 +1,11 @@
inline fun test(p: String = "OK"): String {
return p
}
fun box() : String {
return test()
}
//mask check in test$default
// 1 IFEQ
// 1 IF
@@ -0,0 +1,15 @@
open class A {
inline fun test(p: String = "OK"): String {
return p
}
}
fun box(): String {
return A().test()
}
//handler check in test$default
// 1 IFNULL
//mask check in test$default
// 1 IFEQ
// 2 IF
@@ -905,6 +905,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
doTest(fileName);
}
@TestMetadata("kt14564.kt")
public void testKt14564() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt14564.kt");
doTest(fileName);
}
@TestMetadata("kt14564_2.kt")
public void testKt14564_2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt14564_2.kt");
doTest(fileName);
}
@TestMetadata("kt5685.kt")
public void testKt5685() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt5685.kt");
@@ -916,6 +928,33 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/simpleDefaultMethod.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MaskElumination extends AbstractBlackBoxInlineCodegenTest {
@TestMetadata("32Parameters.kt")
public void test32Parameters() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/32Parameters.kt");
doTest(fileName);
}
@TestMetadata("33Parameters.kt")
public void test33Parameters() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/33Parameters.kt");
doTest(fileName);
}
public void testAllFilesPresentInMaskElumination() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/defaultValues/maskElumination"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/simple.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/boxInline/delegatedProperty")
@@ -1090,6 +1090,18 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/defaultArguments/kt11962.kt");
doTest(fileName);
}
@TestMetadata("maskElumination.kt")
public void testMaskElumination() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/defaultArguments/maskElumination.kt");
doTest(fileName);
}
@TestMetadata("methodHandlerElumination.kt")
public void testMethodHandlerElumination() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/defaultArguments/methodHandlerElumination.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/directInvoke")
@@ -905,6 +905,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
doTest(fileName);
}
@TestMetadata("kt14564.kt")
public void testKt14564() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt14564.kt");
doTest(fileName);
}
@TestMetadata("kt14564_2.kt")
public void testKt14564_2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt14564_2.kt");
doTest(fileName);
}
@TestMetadata("kt5685.kt")
public void testKt5685() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/kt5685.kt");
@@ -916,6 +928,33 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/simpleDefaultMethod.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class MaskElumination extends AbstractCompileKotlinAgainstInlineKotlinTest {
@TestMetadata("32Parameters.kt")
public void test32Parameters() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/32Parameters.kt");
doTest(fileName);
}
@TestMetadata("33Parameters.kt")
public void test33Parameters() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/33Parameters.kt");
doTest(fileName);
}
public void testAllFilesPresentInMaskElumination() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/defaultValues/maskElumination"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/maskElumination/simple.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/boxInline/delegatedProperty")