diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index fe3f256e114..ff4ea930d68 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -57,7 +57,6 @@ import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.renderer.DescriptorRenderer; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContextUtils; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; @@ -2483,9 +2482,8 @@ public class ExpressionCodegen extends KtVisitor impleme } else { mappings.addParameterMappingToNewParameter( - key.getName().getIdentifier(), - parameterDescriptor.getName().getIdentifier() - ); + key.getName().getIdentifier(), type, + parameterDescriptor.getName().getIdentifier()); } } return getOrCreateCallGenerator( @@ -3689,13 +3687,8 @@ The "returned" value of try expression with no finally is either the last expres } if (opToken != KtTokens.AS_SAFE) { - if (!TypeUtils.isNullableType(rightType)) { - v.dup(); - Label nonnull = new Label(); - v.ifnonnull(nonnull); - genThrow(v, "kotlin/TypeCastException", "null cannot be cast to non-null type " + - DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(rightType)); - v.mark(nonnull); + if (!TypeUtils.isNullableType(rightType) && !TypeUtils.isReifiedTypeParameter(rightType)) { + CodegenUtilKt.generateNullCheckForNonSafeAs(v, rightType); } } else { @@ -3759,7 +3752,7 @@ The "returned" value of try expression with no finally is either the last expres if (leaveExpressionOnStack) { v.dup(); } - CodegenUtilKt.generateIsCheck(v, kotlinType, new Function1() { + CodegenUtilKt.generateIsCheck(v, kotlinType.isMarkedNullable() && !TypeUtils.isReifiedTypeParameter(kotlinType), new Function1() { @Override public Unit invoke(InstructionAdapter adapter) { generateInstanceOfInstruction(kotlinType); @@ -3794,8 +3787,8 @@ The "returned" value of try expression with no finally is either the last expres parentCodegen.getReifiedTypeParametersUsages(). addUsedReifiedParameter(typeParameterDescriptor.getName().asString()); } - - v.visitLdcInsn(typeParameterDescriptor.getName().asString()); + boolean putNullableFlag = ReifiedTypeInliner.isNullableMarkerInstruction(markerMethodName) && type.isMarkedNullable(); + v.visitLdcInsn(typeParameterDescriptor.getName().asString() + (putNullableFlag ? "?" : "")); v.invokestatic( IntrinsicMethods.INTRINSICS_CLASS_NAME, markerMethodName, Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 09682f1fda4..32f99816f25 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -911,7 +911,7 @@ public class FunctionCodegen { iv.ifnonnull(afterBarrier); } else { - CodegenUtilKt.generateIsCheck(iv, kotlinType, new Function1() { + CodegenUtilKt.generateIsCheck(iv, kotlinType.isMarkedNullable(), new Function1() { @Override public Unit invoke(InstructionAdapter adapter) { TypeIntrinsics.instanceOf(adapter, kotlinType, boxType(delegateParameterType)); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt index 28c8065782b..33ba8d3565b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt @@ -18,16 +18,17 @@ package org.jetbrains.kotlin.codegen import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo +import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter fun generateIsCheck( v: InstructionAdapter, - type: KotlinType, + isNullable: Boolean, generateInstanceOfInstruction: (InstructionAdapter) -> Unit ) { - if (type.isMarkedNullable) { + if (isNullable) { val nope = Label() val end = Label() @@ -51,6 +52,19 @@ fun generateIsCheck( } } +fun generateNullCheckForNonSafeAs( + v: InstructionAdapter, + type: KotlinType +) { + with(v) { + dup() + val nonnull = Label() + ifnonnull(nonnull) + AsmUtil.genThrow(v, "kotlin/TypeCastException", "null cannot be cast to non-null type " + DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type)) + mark(nonnull) + } +} public fun SpecialSignatureInfo.replaceValueParametersIn(sourceSignature: String?): String? = valueParametersSignature?.let { sourceSignature?.replace("^\\(.*\\)".toRegex(), "($it)") } + diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java index f6afb67f1cf..9f4ea4ab5bd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.codegen.inline; -import com.intellij.openapi.util.Pair; import com.intellij.util.ArrayUtil; import kotlin.jvm.functions.Function0; import org.jetbrains.annotations.NotNull; @@ -237,7 +236,7 @@ public class AnonymousObjectTransformer { @NotNull ParametersBuilder capturedBuilder, boolean isConstructor ) { - ReifiedTypeParametersUsages typeParametersToReify = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode.instructions); + ReifiedTypeParametersUsages typeParametersToReify = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode); Parameters parameters = isConstructor ? capturedBuilder.buildParameters() : getMethodParametersWithCaptured(capturedBuilder, sourceNode); RegeneratedLambdaFieldRemapper remapper = diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index f15068e1cb5..23747d17ce8 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -245,7 +245,7 @@ public class InlineCodegen extends CallGenerator { private InlineResult inlineCall(SMAPAndMethodNode nodeAndSmap) { MethodNode node = nodeAndSmap.getNode(); - ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node.instructions); + ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node); generateClosuresBodies(); //through generation captured parameters will be added to invocationParamBuilder diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java index 5f643529299..124d0b238f7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java @@ -311,8 +311,7 @@ public class InlineCodegenUtil { } } - public static void insertNodeBefore(@NotNull MethodNode from, @NotNull MethodNode to, @NotNull AbstractInsnNode beforeNode) { - InsnList instructions = to.instructions; + public static void insertNodeBefore(@NotNull MethodNode from, @NotNull InsnList instructions, @NotNull AbstractInsnNode beforeNode) { ListIterator iterator = from.instructions.iterator(); while (iterator.hasNext()) { AbstractInsnNode next = iterator.next(); @@ -320,6 +319,10 @@ public class InlineCodegenUtil { } } + public static void insertNodeBefore(@NotNull MethodNode from, @NotNull MethodNode to, @NotNull AbstractInsnNode beforeNode) { + insertNodeBefore(from, to.instructions, beforeNode); + } + public static MethodNode createEmptyMethodNode() { return new MethodNode(API, 0, "fake", "()V", null, null); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt index 14e61f150d3..859eabe13ca 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt @@ -18,16 +18,22 @@ package org.jetbrains.kotlin.codegen.inline import com.google.common.collect.ImmutableSet import org.jetbrains.kotlin.codegen.context.MethodContext +import org.jetbrains.kotlin.codegen.generateIsCheck +import org.jetbrains.kotlin.codegen.generateNullCheckForNonSafeAs import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.org.objectweb.asm.MethodVisitor import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.signature.SignatureReader import org.jetbrains.org.objectweb.asm.signature.SignatureWriter import org.jetbrains.org.objectweb.asm.tree.* +private class ParameterNameAndNullability(val name: String, val nullable: Boolean) + public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParameterMappings?) { companion object { @@ -64,15 +70,23 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame Type.getMethodDescriptor(Type.VOID_TYPE), false ); } + + @JvmStatic + public fun isNullableMarkerInstruction(marker: String) = INSTANCEOF_MARKER_METHOD_NAME == marker || + CHECKCAST_MARKER_METHOD_NAME == marker } + private var maxStackSize = 0 + /** * @return set of type parameters' identifiers contained in markers that should be reified further * e.g. when we're generating inline function containing reified T * and another function containing reifiable parts is inlined into that function */ - public fun reifyInstructions(instructions: InsnList): ReifiedTypeParametersUsages { + public fun reifyInstructions(node: MethodNode): ReifiedTypeParametersUsages { if (parametersMapping == null) return ReifiedTypeParametersUsages() + val instructions = node.instructions + maxStackSize = 0 var result = ReifiedTypeParametersUsages() for (insn in instructions.toArray()) { if (isParametrisedReifiedMarker(insn)) { @@ -83,6 +97,7 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame } } + node.maxStack = node.maxStack + maxStackSize return result } @@ -127,20 +142,25 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame * or null if it shouldn't */ private fun processReifyMarker(insn: MethodInsnNode, instructions: InsnList): String? { - val mapping = getTypeParameterMapping(insn) ?: return null + val parameter = getParameter(insn) ?: return null + val mapping = parametersMapping?.get(parameter.name) ?: return null + val kotlinType = + if (isNullableMarkerInstruction(insn.name) && parameter.nullable) + TypeUtils.makeNullable(mapping.type) + else + mapping.type + val asmType = mapping.asmType if (asmType != null) { - val jetType = mapping.type ?: return null - // process* methods return false if marker should be reified further // or it's invalid (may be emitted explicitly in code) // they return true if instruction is reified and marker can be deleted if (when (insn.name) { NEW_ARRAY_MARKER_METHOD_NAME -> processNewArray(insn, asmType) - CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, jetType, asmType, safe = false) - SAFE_CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, jetType, asmType, safe = true) - INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, instructions, jetType, asmType) + CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, kotlinType, asmType, safe = false) + SAFE_CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, instructions, kotlinType, asmType, safe = true) + INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, instructions, kotlinType, asmType) JAVA_CLASS_MARKER_METHOD_NAME -> processJavaClass(insn, asmType) else -> false }) { @@ -150,7 +170,8 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame return null } else { - instructions.set(insn.getPrevious()!!, LdcInsnNode(mapping.newName)) + val nullableSuffix = if (isNullableMarkerInstruction(insn.name) && kotlinType.isMarkedNullable) "?" else "" + instructions.set(insn.previous!!, LdcInsnNode(mapping.newName + nullableSuffix)) return mapping.newName } } @@ -158,20 +179,66 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame private fun processNewArray(insn: MethodInsnNode, parameter: Type) = processNextTypeInsn(insn, parameter, Opcodes.ANEWARRAY) - private fun processCheckcast(insn: MethodInsnNode, instructions: InsnList, jetType: KotlinType, asmType: Type, safe: Boolean) = + private fun processCheckcast(insn: MethodInsnNode, + instructions: InsnList, + jetType: KotlinType, + asmType: Type, + safe: Boolean) = rewriteNextTypeInsn(insn, Opcodes.CHECKCAST) { instanceofInsn: AbstractInsnNode -> if (instanceofInsn !is TypeInsnNode) return false + + addNullCheckForAsIfNeeded(insn.previous!!, instructions, jetType, safe) TypeIntrinsics.checkcast(instanceofInsn, instructions, jetType, asmType, safe) return true } + private fun addNullCheckForAsIfNeeded(insn: AbstractInsnNode, instructions: InsnList, jetType: KotlinType, safe: Boolean) { + if (!safe && !TypeUtils.isNullableType(jetType)) { + val methodNode = MethodNode(InlineCodegenUtil.API) + generateNullCheckForNonSafeAs(InstructionAdapter(methodNode), jetType) + + InlineCodegenUtil.insertNodeBefore(methodNode, instructions, insn) + maxStackSize = Math.max(maxStackSize, 4) + } + } + private fun processInstanceof(insn: MethodInsnNode, instructions: InsnList, jetType: KotlinType, asmType: Type) = rewriteNextTypeInsn(insn, Opcodes.INSTANCEOF) { instanceofInsn: AbstractInsnNode -> if (instanceofInsn !is TypeInsnNode) return false + + addNullCheckForIsIfNeeded(insn, instructions, jetType) TypeIntrinsics.instanceOf(instanceofInsn, instructions, jetType, asmType) return true } + private fun addNullCheckForIsIfNeeded(insn: AbstractInsnNode, instructions: InsnList, type: KotlinType) { + if (TypeUtils.isNullableType(type)) { + val instanceOf = insn.next + insertNullCheckAround(instructions, insn.previous!!, instanceOf) + maxStackSize = Math.max(maxStackSize, 2) + } + } + + private fun insertNullCheckAround(instructions: InsnList, start: AbstractInsnNode, end: AbstractInsnNode) { + val methodNode = MethodNode(InlineCodegenUtil.API) + var splitIndex: Int = -1 + generateIsCheck(InstructionAdapter(methodNode), true) { + splitIndex = methodNode.instructions.size() + } + assert(splitIndex >= 0) { + "Split index should be non-negative, but $splitIndex" + } + + val nullCheckInsns = methodNode.instructions.toArray() + nullCheckInsns.take(splitIndex).forEach { + instructions.insertBefore(start, it) + } + + nullCheckInsns.drop(splitIndex).reversed().forEach { + instructions.insert(end, it) + } + } + inline private fun rewriteNextTypeInsn( marker: MethodInsnNode, expectedNextOpcode: Int, @@ -195,17 +262,16 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame return true } - private fun getParameterName(insn: MethodInsnNode): String? { + private fun getParameter(insn: MethodInsnNode): ParameterNameAndNullability? { val prev = insn.getPrevious()!! - return when (prev.getOpcode()) { + val parameterNameWithFlag = when (prev.getOpcode()) { Opcodes.LDC -> (prev as LdcInsnNode).cst as String - else -> null + else -> return null } - } - private fun getTypeParameterMapping(insn: MethodInsnNode): ReifiedTypeParameterMapping? { - return parametersMapping?.get(getParameterName(insn) ?: return null) + val parameterName = if (parameterNameWithFlag.endsWith("?")) parameterNameWithFlag.dropLast(1) else parameterNameWithFlag + return ParameterNameAndNullability(parameterName, parameterName !== parameterNameWithFlag) } } @@ -216,8 +282,8 @@ public class ReifiedTypeParameterMappings() { mappingsByName[name] = ReifiedTypeParameterMapping(name, type, asmType, newName = null, signature = signature) } - public fun addParameterMappingToNewParameter(name: String, newName: String) { - mappingsByName[name] = ReifiedTypeParameterMapping(name, type = null, asmType = null, newName = newName, signature = null) + public fun addParameterMappingToNewParameter(name: String, type: KotlinType, newName: String) { + mappingsByName[name] = ReifiedTypeParameterMapping(name, type = type, asmType = null, newName = newName, signature = null) } operator fun get(name: String): ReifiedTypeParameterMapping? { @@ -226,7 +292,7 @@ public class ReifiedTypeParameterMappings() { } public class ReifiedTypeParameterMapping( - val name: String, val type: KotlinType?, val asmType: Type?, val newName: String?, val signature: String? + val name: String, val type: KotlinType, val asmType: Type?, val newName: String?, val signature: String? ) public class ReifiedTypeParametersUsages { diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/chain.1.kt b/compiler/testData/codegen/boxInline/reified/checkCast/chain.1.kt new file mode 100644 index 00000000000..b7751035b64 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/chain.1.kt @@ -0,0 +1,36 @@ +import test.* + +fun box(): String { + if (null.foo3() != null) return "fail 1" + if (null.foo3() != null) return "fail 2" + + if (null.foo3() != null) return "fail 3" + if (null.foo3() != null) return "fail 4" + + val a = A() + + if (a.foo3() != a) return "fail 5" + if (a.foo3() != a) return "fail 6" + + if (a.foo3() != a) return "fail 7" + if (a.foo3() != a) return "fail 8" + + val b = B() + + failClassCast { b.foo3(); return "failTypeCast 9" } + failClassCast { b.foo3(); return "failTypeCast 10" } + + return "OK" +} + +inline fun failClassCast(s: () -> Unit) { + try { + s() + } + catch (e: TypeCastException) { + throw e + } + catch (e: ClassCastException) { + + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/chain.2.kt b/compiler/testData/codegen/boxInline/reified/checkCast/chain.2.kt new file mode 100644 index 00000000000..76cb778209b --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/chain.2.kt @@ -0,0 +1,10 @@ +package test + +class A +class B + +inline fun Any?.foo(): T = this as T + +inline fun Any?.foo2(): Y? = foo() + +inline fun Any?.foo3(): Z? = foo2() diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/kt8043.1.kt b/compiler/testData/codegen/boxInline/reified/checkCast/kt8043.1.kt new file mode 100644 index 00000000000..69133d263d3 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/kt8043.1.kt @@ -0,0 +1,18 @@ +import test.* + +fun case1(): Int = + null.castTo() + +fun box(): String { + failTypeCast { case1(); return "failTypeCast 9" } + return "OK" +} + +inline fun failTypeCast(s: () -> Unit) { + try { + s() + } + catch (e: TypeCastException) { + + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/kt8043.2.kt b/compiler/testData/codegen/boxInline/reified/checkCast/kt8043.2.kt new file mode 100644 index 00000000000..8f46d861b98 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/kt8043.2.kt @@ -0,0 +1,3 @@ +package test + +inline fun T.castTo(): R = this as R diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/maxStack.1.kt b/compiler/testData/codegen/boxInline/reified/checkCast/maxStack.1.kt new file mode 100644 index 00000000000..c1063d1071a --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/maxStack.1.kt @@ -0,0 +1,10 @@ +import test.* + + + +fun box(): String { + val a = A() + if (a.foo() != a) return "failTypeCast 5" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/maxStack.2.kt b/compiler/testData/codegen/boxInline/reified/checkCast/maxStack.2.kt new file mode 100644 index 00000000000..9e7cd2d1858 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/maxStack.2.kt @@ -0,0 +1,13 @@ +package test + +class A + +fun call(a: String, b: String, c: String, d: String, e: String, f: Any) { + +} + +inline fun Any?.foo(): T { + call("1", "2", "3", "4", "5", this as T) + return this as T +} + diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/nullable.1.kt b/compiler/testData/codegen/boxInline/reified/checkCast/nullable.1.kt new file mode 100644 index 00000000000..161aa98d7c9 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/nullable.1.kt @@ -0,0 +1,45 @@ +import test.* + +fun box(): String { + if (null.foo() != null) return "failTypeCast 1" + if (null.foo() != null) return "failTypeCast 2" + + if (null.foo() != null) return "failTypeCast 3" + if (null.foo() != null) return "failTypeCast 4" + + val a = A() + + if (a.foo() != a) return "failTypeCast 5" + if (a.foo() != a) return "failTypeCast 6" + + if (a.foo() != a) return "failTypeCast 7" + if (a.foo() != a) return "failTypeCast 8" + + val b = B() + + failClassCast { b.foo(); return "failTypeCast 9" } + failClassCast { b.foo(); return "failTypeCast 10" } + + return "OK" +} + +inline fun failTypeCast(s: () -> Unit) { + try { + s() + } + catch (e: TypeCastException) { + + } +} + +inline fun failClassCast(s: () -> Unit) { + try { + s() + } + catch (e: TypeCastException) { + throw e + } + catch (e: ClassCastException) { + + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/nullable.2.kt b/compiler/testData/codegen/boxInline/reified/checkCast/nullable.2.kt new file mode 100644 index 00000000000..2f4aee24d93 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/nullable.2.kt @@ -0,0 +1,6 @@ +package test + +class A +class B + +inline fun Any?.foo(): T? = this as T? diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/simple.1.kt b/compiler/testData/codegen/boxInline/reified/checkCast/simple.1.kt new file mode 100644 index 00000000000..baf99b56ccf --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/simple.1.kt @@ -0,0 +1,45 @@ +import test.* + +fun box(): String { + failTypeCast { null.foo(); return "failTypeCast 1" } + if (null.foo() != null) return "failTypeCast 2" + + failTypeCast { null.foo(); return "failTypeCast 3" } + if (null.foo() != null) return "failTypeCast 4" + + val a = A() + + if (a.foo() != a) return "failTypeCast 5" + if (a.foo() != a) return "failTypeCast 6" + + if (a.foo() != a) return "failTypeCast 7" + if (a.foo() != a) return "failTypeCast 8" + + val b = B() + + failClassCast { b.foo(); return "failTypeCast 9" } + failClassCast { b.foo(); return "failTypeCast 10" } + + return "OK" +} + +inline fun failTypeCast(s: () -> Unit) { + try { + s() + } + catch (e: TypeCastException) { + + } +} + +inline fun failClassCast(s: () -> Unit) { + try { + s() + } + catch (e: TypeCastException) { + throw e + } + catch (e: ClassCastException) { + + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/simple.2.kt b/compiler/testData/codegen/boxInline/reified/checkCast/simple.2.kt new file mode 100644 index 00000000000..c7a894a398f --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/simple.2.kt @@ -0,0 +1,6 @@ +package test + +class A +class B + +inline fun Any?.foo(): T = this as T diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/simpleSafe.1.kt b/compiler/testData/codegen/boxInline/reified/checkCast/simpleSafe.1.kt new file mode 100644 index 00000000000..bcfdc5da6ef --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/simpleSafe.1.kt @@ -0,0 +1,45 @@ +import test.* + +fun box(): String { + if (null.foo() != null) return "failTypeCast 1" + if (null.foo() != null) return "failTypeCast 2" + + if (null.foo() != null) return "failTypeCast 3" + if (null.foo() != null) return "failTypeCast 4" + + val a = A() + + if (a.foo() != a) return "failTypeCast 5" + if (a.foo() != a) return "failTypeCast 6" + + if (a.foo() != a) return "failTypeCast 7" + if (a.foo() != a) return "failTypeCast 8" + + val b = B() + + if (b.foo() != null) return "fail 9" + if (b.foo() != null) return "fail 10" + + return "OK" +} + +inline fun failTypeCast(s: () -> Unit) { + try { + s() + } + catch (e: TypeCastException) { + + } +} + +inline fun failClassCast(s: () -> Unit) { + try { + s() + } + catch (e: TypeCastException) { + throw e + } + catch (e: ClassCastException) { + + } +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/reified/checkCast/simpleSafe.2.kt b/compiler/testData/codegen/boxInline/reified/checkCast/simpleSafe.2.kt new file mode 100644 index 00000000000..21999c85c20 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/checkCast/simpleSafe.2.kt @@ -0,0 +1,6 @@ +package test + +class A +class B + +inline fun Any?.foo(): T? = this as? T diff --git a/compiler/testData/codegen/boxInline/reified/isCheck/chain.1.kt b/compiler/testData/codegen/boxInline/reified/isCheck/chain.1.kt new file mode 100644 index 00000000000..ba088c058b9 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/isCheck/chain.1.kt @@ -0,0 +1,24 @@ +import test.* + +fun box(): String { + if (null.foo3() != true) return "fail 1" + if (null.foo3() != true) return "fail 2" + + if (null.foo3() != true) return "fail 3" + if (null.foo3() != true) return "fail 4" + + val a = A() + + if (a.foo3() != true) return "fail 5" + if (a.foo3() != true) return "fail 6" + + if (a.foo3() != true) return "fail 7" + if (a.foo3() != true) return "fail 8" + + val b = B() + + if (b.foo3() != false) return "fail 9" + if (b.foo3() != false) return "fail 10" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/reified/isCheck/chain.2.kt b/compiler/testData/codegen/boxInline/reified/isCheck/chain.2.kt new file mode 100644 index 00000000000..c5d6e4f3a46 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/isCheck/chain.2.kt @@ -0,0 +1,10 @@ +package test + +class A +class B + +inline fun Any?.foo() = this is T + +inline fun Any?.foo2() = foo() + +inline fun Any?.foo3() = foo2() diff --git a/compiler/testData/codegen/boxInline/reified/isCheck/nullable.1.kt b/compiler/testData/codegen/boxInline/reified/isCheck/nullable.1.kt new file mode 100644 index 00000000000..c139c0ae4b6 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/isCheck/nullable.1.kt @@ -0,0 +1,24 @@ +import test.* + +fun box(): String { + if (null.foo() != true) return "fail 1" + if (null.foo() != true) return "fail 2" + + if (null.foo() != true) return "fail 3" + if (null.foo() != true) return "fail 4" + + val a = A() + + if (a.foo() != true) return "fail 5" + if (a.foo() != true) return "fail 6" + + if (a.foo() != true) return "fail 7" + if (a.foo() != true) return "fail 8" + + val b = B() + + if (b.foo() != false) return "fail 9" + if (b.foo() != false) return "fail 10" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/reified/isCheck/nullable.2.kt b/compiler/testData/codegen/boxInline/reified/isCheck/nullable.2.kt new file mode 100644 index 00000000000..9c93bb19fa6 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/isCheck/nullable.2.kt @@ -0,0 +1,6 @@ +package test + +class A +class B + +inline fun Any?.foo() = this is T? \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/reified/isCheck/simple.1.kt b/compiler/testData/codegen/boxInline/reified/isCheck/simple.1.kt new file mode 100644 index 00000000000..863ad2fa627 --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/isCheck/simple.1.kt @@ -0,0 +1,24 @@ +import test.* + +fun box(): String { + if (null.foo() != false) return "fail 1" + if (null.foo() != true) return "fail 2" + + if (null.foo() != false) return "fail 3" + if (null.foo() != true) return "fail 4" + + val a = A() + + if (a.foo() != true) return "fail 5" + if (a.foo() != true) return "fail 6" + + if (a.foo() != true) return "fail 7" + if (a.foo() != true) return "fail 8" + + val b = B() + + if (b.foo() != false) return "fail 9" + if (b.foo() != false) return "fail 10" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxInline/reified/isCheck/simple.2.kt b/compiler/testData/codegen/boxInline/reified/isCheck/simple.2.kt new file mode 100644 index 00000000000..a1841b272cc --- /dev/null +++ b/compiler/testData/codegen/boxInline/reified/isCheck/simple.2.kt @@ -0,0 +1,6 @@ +package test + +class A +class B + +inline fun Any?.foo() = this is T \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/reified/asCheck/JavaClass.java b/compiler/testData/codegen/boxWithJava/reified/asCheck/JavaClass.java new file mode 100644 index 00000000000..ac3dfc287c2 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/reified/asCheck/JavaClass.java @@ -0,0 +1,11 @@ +public class JavaClass { + + public static String nullString() { + return null; + } + + public static String nonnullString() { + return "OK"; + } + +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/reified/asCheck/kotlin.kt b/compiler/testData/codegen/boxWithJava/reified/asCheck/kotlin.kt new file mode 100644 index 00000000000..1b9f417c06e --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/reified/asCheck/kotlin.kt @@ -0,0 +1,16 @@ +fun box(): String { + val nullStr = JavaClass.nullString() + val nonnullStr = JavaClass.nonnullString() + + if (nullStr.foo() != null) return "fail 1" + if (nonnullStr.foo() != nonnullStr) return "fail 2" + + if (nullStr.fooN() != null) return "fail 3" + if (nonnullStr.fooN() != nonnullStr) return "fail 4" + + return "OK" +} + +inline fun T.foo(): T = this as T + +inline fun T.fooN(): T? = this as T? \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/reified/isCheck/JavaClass.java b/compiler/testData/codegen/boxWithJava/reified/isCheck/JavaClass.java new file mode 100644 index 00000000000..ac3dfc287c2 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/reified/isCheck/JavaClass.java @@ -0,0 +1,11 @@ +public class JavaClass { + + public static String nullString() { + return null; + } + + public static String nonnullString() { + return "OK"; + } + +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/reified/isCheck/kotlin.kt b/compiler/testData/codegen/boxWithJava/reified/isCheck/kotlin.kt new file mode 100644 index 00000000000..39b4128cc93 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/reified/isCheck/kotlin.kt @@ -0,0 +1,16 @@ +fun box(): String { + val nullStr = JavaClass.nullString() + val nonnullStr = JavaClass.nonnullString() + + if (nullStr.foo() != true) return "fail 1" + if (nonnullStr.foo() != true) return "fail 2" + + if (nullStr.fooN() != true) return "fail 3" + if (nonnullStr.fooN() != true) return "fail 4" + + return "OK" +} + +inline fun T.foo(): Boolean = this is T + +inline fun T.fooN(): Boolean = this is T? \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/reifiedAsCheck.kt b/compiler/testData/codegen/bytecodeText/reifiedAsCheck.kt new file mode 100644 index 00000000000..52f46d22194 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/reifiedAsCheck.kt @@ -0,0 +1,15 @@ +inline fun Any?.foo() = this as T + +inline fun Any?.foo2() = foo() + +inline fun Any?.foo3() = foo2() + +inline fun Any?.foo4() = foo2() + +inline fun Any?.foo5() = foo() + +// 1 LDC "T" +// 1 LDC "Y\?" +// 1 LDC "Z\?" +// 1 LDC "X\?" +// 1 LDC "A" \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/reifiedAsCheckWithNullable.kt b/compiler/testData/codegen/bytecodeText/reifiedAsCheckWithNullable.kt new file mode 100644 index 00000000000..06754c9ad8c --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/reifiedAsCheckWithNullable.kt @@ -0,0 +1,15 @@ +inline fun Any?.foo() = this as T? + +inline fun Any?.foo2() = foo() + +inline fun Any?.foo3() = foo2() + +inline fun Any?.foo4() = foo2() + +inline fun Any?.foo5() = foo() + +// 1 LDC "T\?" +// 1 LDC "Y\?" +// 1 LDC "Z\?" +// 1 LDC "X\?" +// 1 LDC "A\?" \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/reifiedIsCheck.kt b/compiler/testData/codegen/bytecodeText/reifiedIsCheck.kt new file mode 100644 index 00000000000..56c4d57c545 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/reifiedIsCheck.kt @@ -0,0 +1,15 @@ +inline fun Any?.foo() = this is T + +inline fun Any?.foo2() = foo() + +inline fun Any?.foo3() = foo2() + +inline fun Any?.foo4() = foo2() + +inline fun Any?.foo5() = foo() + +// 1 LDC "T" +// 1 LDC "Y\?" +// 1 LDC "Z\?" +// 1 LDC "X\?" +// 1 LDC "A" \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/reifiedIsCheckWithNullable.kt b/compiler/testData/codegen/bytecodeText/reifiedIsCheckWithNullable.kt new file mode 100644 index 00000000000..ef36caf6a6d --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/reifiedIsCheckWithNullable.kt @@ -0,0 +1,15 @@ +inline fun Any?.foo() = this is T? + +inline fun Any?.foo2() = foo() + +inline fun Any?.foo3() = foo2() + +inline fun Any?.foo4() = foo2() + +inline fun Any?.foo5() = foo() + +// 1 LDC "T\?" +// 1 LDC "Y\?" +// 1 LDC "Z\?" +// 1 LDC "X\?" +// 1 LDC "A\?" \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index a1c29943e7e..28200d65c9c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -257,6 +257,30 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { doTest(fileName); } + @TestMetadata("reifiedAsCheck.kt") + public void testReifiedAsCheck() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/reifiedAsCheck.kt"); + doTest(fileName); + } + + @TestMetadata("reifiedAsCheckWithNullable.kt") + public void testReifiedAsCheckWithNullable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/reifiedAsCheckWithNullable.kt"); + doTest(fileName); + } + + @TestMetadata("reifiedIsCheck.kt") + public void testReifiedIsCheck() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/reifiedIsCheck.kt"); + doTest(fileName); + } + + @TestMetadata("reifiedIsCheckWithNullable.kt") + public void testReifiedIsCheckWithNullable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/reifiedIsCheckWithNullable.kt"); + doTest(fileName); + } + @TestMetadata("safeAsWithMutable.kt") public void testSafeAsWithMutable() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/safeAsWithMutable.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java index 25f8cbd64de..671ed23ae58 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxInlineCodegenTestGenerated.java @@ -1293,6 +1293,78 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt"); doTestMultiFileWithInlineCheck(fileName); } + + @TestMetadata("compiler/testData/codegen/boxInline/reified/checkCast") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CheckCast extends AbstractBlackBoxInlineCodegenTest { + public void testAllFilesPresentInCheckCast() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/reified/checkCast"), Pattern.compile("^(.+)\\.1.kt$"), true); + } + + @TestMetadata("chain.1.kt") + public void testChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/chain.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + + @TestMetadata("kt8043.1.kt") + public void testKt8043() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/kt8043.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + + @TestMetadata("maxStack.1.kt") + public void testMaxStack() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/maxStack.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + + @TestMetadata("nullable.1.kt") + public void testNullable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/nullable.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + + @TestMetadata("simple.1.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/simple.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + + @TestMetadata("simpleSafe.1.kt") + public void testSimpleSafe() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/simpleSafe.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + } + + @TestMetadata("compiler/testData/codegen/boxInline/reified/isCheck") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class IsCheck extends AbstractBlackBoxInlineCodegenTest { + public void testAllFilesPresentInIsCheck() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/reified/isCheck"), Pattern.compile("^(.+)\\.1.kt$"), true); + } + + @TestMetadata("chain.1.kt") + public void testChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/isCheck/chain.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + + @TestMetadata("nullable.1.kt") + public void testNullable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/isCheck/nullable.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + + @TestMetadata("simple.1.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/isCheck/simple.1.kt"); + doTestMultiFileWithInlineCheck(fileName); + } + } } @TestMetadata("compiler/testData/codegen/boxInline/simple") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index 1ff9cf9bd0e..8cceb623974 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -673,6 +673,28 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege } + @TestMetadata("compiler/testData/codegen/boxWithJava/reified") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Reified extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInReified() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithJava/reified"), Pattern.compile("^([^\\.]+)$"), true); + } + + @TestMetadata("asCheck") + public void testAsCheck() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/reified/asCheck/"); + doTestWithJava(fileName); + } + + @TestMetadata("isCheck") + public void testIsCheck() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/reified/isCheck/"); + doTestWithJava(fileName); + } + + } + @TestMetadata("compiler/testData/codegen/boxWithJava/secondaryConstructors") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java index 801836785b5..02899f3bc9b 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -1293,6 +1293,78 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt"); doBoxTestWithInlineCheck(fileName); } + + @TestMetadata("compiler/testData/codegen/boxInline/reified/checkCast") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CheckCast extends AbstractCompileKotlinAgainstInlineKotlinTest { + public void testAllFilesPresentInCheckCast() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/reified/checkCast"), Pattern.compile("^(.+)\\.1.kt$"), true); + } + + @TestMetadata("chain.1.kt") + public void testChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/chain.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + + @TestMetadata("kt8043.1.kt") + public void testKt8043() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/kt8043.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + + @TestMetadata("maxStack.1.kt") + public void testMaxStack() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/maxStack.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + + @TestMetadata("nullable.1.kt") + public void testNullable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/nullable.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + + @TestMetadata("simple.1.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/simple.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + + @TestMetadata("simpleSafe.1.kt") + public void testSimpleSafe() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/checkCast/simpleSafe.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + } + + @TestMetadata("compiler/testData/codegen/boxInline/reified/isCheck") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class IsCheck extends AbstractCompileKotlinAgainstInlineKotlinTest { + public void testAllFilesPresentInIsCheck() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/reified/isCheck"), Pattern.compile("^(.+)\\.1.kt$"), true); + } + + @TestMetadata("chain.1.kt") + public void testChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/isCheck/chain.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + + @TestMetadata("nullable.1.kt") + public void testNullable() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/isCheck/nullable.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + + @TestMetadata("simple.1.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/isCheck/simple.1.kt"); + doBoxTestWithInlineCheck(fileName); + } + } } @TestMetadata("compiler/testData/codegen/boxInline/simple")