Fix for KT-7999: Wrong result when use nullable types as reified parameter, KT-8043: Unsafe cast to reified parameter throws NPE instead of TypeCastException
#KT-7999 Fixed #KT-8043 Fixed ~
This commit is contained in:
@@ -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<StackValue, StackValue> 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<InstructionAdapter, Unit>() {
|
||||
CodegenUtilKt.generateIsCheck(v, kotlinType.isMarkedNullable() && !TypeUtils.isReifiedTypeParameter(kotlinType), new Function1<InstructionAdapter, Unit>() {
|
||||
@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
|
||||
|
||||
@@ -911,7 +911,7 @@ public class FunctionCodegen {
|
||||
iv.ifnonnull(afterBarrier);
|
||||
}
|
||||
else {
|
||||
CodegenUtilKt.generateIsCheck(iv, kotlinType, new Function1<InstructionAdapter, Unit>() {
|
||||
CodegenUtilKt.generateIsCheck(iv, kotlinType.isMarkedNullable(), new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter adapter) {
|
||||
TypeIntrinsics.instanceOf(adapter, kotlinType, boxType(delegateParameterType));
|
||||
|
||||
@@ -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)") }
|
||||
|
||||
|
||||
+1
-2
@@ -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 =
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<AbstractInsnNode> 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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
if (null.foo3<Any>() != null) return "fail 1"
|
||||
if (null.foo3<Any?>() != null) return "fail 2"
|
||||
|
||||
if (null.foo3<A>() != null) return "fail 3"
|
||||
if (null.foo3<A?>() != null) return "fail 4"
|
||||
|
||||
val a = A()
|
||||
|
||||
if (a.foo3<Any>() != a) return "fail 5"
|
||||
if (a.foo3<Any?>() != a) return "fail 6"
|
||||
|
||||
if (a.foo3<A>() != a) return "fail 7"
|
||||
if (a.foo3<A?>() != a) return "fail 8"
|
||||
|
||||
val b = B()
|
||||
|
||||
failClassCast { b.foo3<A>(); return "failTypeCast 9" }
|
||||
failClassCast { b.foo3<A?>(); return "failTypeCast 10" }
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
inline fun failClassCast(s: () -> Unit) {
|
||||
try {
|
||||
s()
|
||||
}
|
||||
catch (e: TypeCastException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: ClassCastException) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
class A
|
||||
class B
|
||||
|
||||
inline fun <reified T> Any?.foo(): T = this as T
|
||||
|
||||
inline fun <reified Y> Any?.foo2(): Y? = foo<Y?>()
|
||||
|
||||
inline fun <reified Z> Any?.foo3(): Z? = foo2<Z>()
|
||||
@@ -0,0 +1,18 @@
|
||||
import test.*
|
||||
|
||||
fun case1(): Int =
|
||||
null.castTo<Int?, Int>()
|
||||
|
||||
fun box(): String {
|
||||
failTypeCast { case1(); return "failTypeCast 9" }
|
||||
return "OK"
|
||||
}
|
||||
|
||||
inline fun failTypeCast(s: () -> Unit) {
|
||||
try {
|
||||
s()
|
||||
}
|
||||
catch (e: TypeCastException) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
inline fun <reified T, reified R>T.castTo(): R = this as R
|
||||
@@ -0,0 +1,10 @@
|
||||
import test.*
|
||||
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
if (a.foo<Any>() != a) return "failTypeCast 5"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package test
|
||||
|
||||
class A
|
||||
|
||||
fun call(a: String, b: String, c: String, d: String, e: String, f: Any) {
|
||||
|
||||
}
|
||||
|
||||
inline fun <reified T: Any> Any?.foo(): T {
|
||||
call("1", "2", "3", "4", "5", this as T)
|
||||
return this as T
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
if (null.foo<Any>() != null) return "failTypeCast 1"
|
||||
if (null.foo<Any?>() != null) return "failTypeCast 2"
|
||||
|
||||
if (null.foo<A>() != null) return "failTypeCast 3"
|
||||
if (null.foo<A?>() != null) return "failTypeCast 4"
|
||||
|
||||
val a = A()
|
||||
|
||||
if (a.foo<Any>() != a) return "failTypeCast 5"
|
||||
if (a.foo<Any?>() != a) return "failTypeCast 6"
|
||||
|
||||
if (a.foo<A>() != a) return "failTypeCast 7"
|
||||
if (a.foo<A?>() != a) return "failTypeCast 8"
|
||||
|
||||
val b = B()
|
||||
|
||||
failClassCast { b.foo<A>(); return "failTypeCast 9" }
|
||||
failClassCast { b.foo<A?>(); 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) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
class A
|
||||
class B
|
||||
|
||||
inline fun <reified T> Any?.foo(): T? = this as T?
|
||||
@@ -0,0 +1,45 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
failTypeCast { null.foo<Any>(); return "failTypeCast 1" }
|
||||
if (null.foo<Any?>() != null) return "failTypeCast 2"
|
||||
|
||||
failTypeCast { null.foo<A>(); return "failTypeCast 3" }
|
||||
if (null.foo<A?>() != null) return "failTypeCast 4"
|
||||
|
||||
val a = A()
|
||||
|
||||
if (a.foo<Any>() != a) return "failTypeCast 5"
|
||||
if (a.foo<Any?>() != a) return "failTypeCast 6"
|
||||
|
||||
if (a.foo<A>() != a) return "failTypeCast 7"
|
||||
if (a.foo<A?>() != a) return "failTypeCast 8"
|
||||
|
||||
val b = B()
|
||||
|
||||
failClassCast { b.foo<A>(); return "failTypeCast 9" }
|
||||
failClassCast { b.foo<A?>(); 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) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
class A
|
||||
class B
|
||||
|
||||
inline fun <reified T> Any?.foo(): T = this as T
|
||||
@@ -0,0 +1,45 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
if (null.foo<Any>() != null) return "failTypeCast 1"
|
||||
if (null.foo<Any?>() != null) return "failTypeCast 2"
|
||||
|
||||
if (null.foo<A>() != null) return "failTypeCast 3"
|
||||
if (null.foo<A?>() != null) return "failTypeCast 4"
|
||||
|
||||
val a = A()
|
||||
|
||||
if (a.foo<Any>() != a) return "failTypeCast 5"
|
||||
if (a.foo<Any?>() != a) return "failTypeCast 6"
|
||||
|
||||
if (a.foo<A>() != a) return "failTypeCast 7"
|
||||
if (a.foo<A?>() != a) return "failTypeCast 8"
|
||||
|
||||
val b = B()
|
||||
|
||||
if (b.foo<A>() != null) return "fail 9"
|
||||
if (b.foo<A?>() != 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) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
class A
|
||||
class B
|
||||
|
||||
inline fun <reified T> Any?.foo(): T? = this as? T
|
||||
@@ -0,0 +1,24 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
if (null.foo3<Any>() != true) return "fail 1"
|
||||
if (null.foo3<Any?>() != true) return "fail 2"
|
||||
|
||||
if (null.foo3<A>() != true) return "fail 3"
|
||||
if (null.foo3<A?>() != true) return "fail 4"
|
||||
|
||||
val a = A()
|
||||
|
||||
if (a.foo3<Any>() != true) return "fail 5"
|
||||
if (a.foo3<Any?>() != true) return "fail 6"
|
||||
|
||||
if (a.foo3<A>() != true) return "fail 7"
|
||||
if (a.foo3<A?>() != true) return "fail 8"
|
||||
|
||||
val b = B()
|
||||
|
||||
if (b.foo3<A>() != false) return "fail 9"
|
||||
if (b.foo3<A?>() != false) return "fail 10"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
class A
|
||||
class B
|
||||
|
||||
inline fun <reified T> Any?.foo() = this is T
|
||||
|
||||
inline fun <reified Y> Any?.foo2() = foo<Y?>()
|
||||
|
||||
inline fun <reified Z> Any?.foo3() = foo2<Z>()
|
||||
@@ -0,0 +1,24 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
if (null.foo<Any>() != true) return "fail 1"
|
||||
if (null.foo<Any?>() != true) return "fail 2"
|
||||
|
||||
if (null.foo<A>() != true) return "fail 3"
|
||||
if (null.foo<A?>() != true) return "fail 4"
|
||||
|
||||
val a = A()
|
||||
|
||||
if (a.foo<Any>() != true) return "fail 5"
|
||||
if (a.foo<Any?>() != true) return "fail 6"
|
||||
|
||||
if (a.foo<A>() != true) return "fail 7"
|
||||
if (a.foo<A?>() != true) return "fail 8"
|
||||
|
||||
val b = B()
|
||||
|
||||
if (b.foo<A>() != false) return "fail 9"
|
||||
if (b.foo<A?>() != false) return "fail 10"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
class A
|
||||
class B
|
||||
|
||||
inline fun <reified T> Any?.foo() = this is T?
|
||||
@@ -0,0 +1,24 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
if (null.foo<Any>() != false) return "fail 1"
|
||||
if (null.foo<Any?>() != true) return "fail 2"
|
||||
|
||||
if (null.foo<A>() != false) return "fail 3"
|
||||
if (null.foo<A?>() != true) return "fail 4"
|
||||
|
||||
val a = A()
|
||||
|
||||
if (a.foo<Any>() != true) return "fail 5"
|
||||
if (a.foo<Any?>() != true) return "fail 6"
|
||||
|
||||
if (a.foo<A>() != true) return "fail 7"
|
||||
if (a.foo<A?>() != true) return "fail 8"
|
||||
|
||||
val b = B()
|
||||
|
||||
if (b.foo<A>() != false) return "fail 9"
|
||||
if (b.foo<A?>() != false) return "fail 10"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
class A
|
||||
class B
|
||||
|
||||
inline fun <reified T> Any?.foo() = this is T
|
||||
@@ -0,0 +1,11 @@
|
||||
public class JavaClass {
|
||||
|
||||
public static String nullString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String nonnullString() {
|
||||
return "OK";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 <reified T> T.foo(): T = this as T
|
||||
|
||||
inline fun <reified T> T.fooN(): T? = this as T?
|
||||
@@ -0,0 +1,11 @@
|
||||
public class JavaClass {
|
||||
|
||||
public static String nullString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String nonnullString() {
|
||||
return "OK";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 <reified T> T.foo(): Boolean = this is T
|
||||
|
||||
inline fun <reified T> T.fooN(): Boolean = this is T?
|
||||
@@ -0,0 +1,15 @@
|
||||
inline fun <reified T> Any?.foo() = this as T
|
||||
|
||||
inline fun <reified Y> Any?.foo2() = foo<Y?>()
|
||||
|
||||
inline fun <reified Z> Any?.foo3() = foo2<Z>()
|
||||
|
||||
inline fun <reified X> Any?.foo4() = foo2<X?>()
|
||||
|
||||
inline fun <reified A> Any?.foo5() = foo<A>()
|
||||
|
||||
// 1 LDC "T"
|
||||
// 1 LDC "Y\?"
|
||||
// 1 LDC "Z\?"
|
||||
// 1 LDC "X\?"
|
||||
// 1 LDC "A"
|
||||
@@ -0,0 +1,15 @@
|
||||
inline fun <reified T> Any?.foo() = this as T?
|
||||
|
||||
inline fun <reified Y> Any?.foo2() = foo<Y?>()
|
||||
|
||||
inline fun <reified Z> Any?.foo3() = foo2<Z>()
|
||||
|
||||
inline fun <reified X> Any?.foo4() = foo2<X?>()
|
||||
|
||||
inline fun <reified A> Any?.foo5() = foo<A>()
|
||||
|
||||
// 1 LDC "T\?"
|
||||
// 1 LDC "Y\?"
|
||||
// 1 LDC "Z\?"
|
||||
// 1 LDC "X\?"
|
||||
// 1 LDC "A\?"
|
||||
@@ -0,0 +1,15 @@
|
||||
inline fun <reified T> Any?.foo() = this is T
|
||||
|
||||
inline fun <reified Y> Any?.foo2() = foo<Y?>()
|
||||
|
||||
inline fun <reified Z> Any?.foo3() = foo2<Z>()
|
||||
|
||||
inline fun <reified X> Any?.foo4() = foo2<X?>()
|
||||
|
||||
inline fun <reified A> Any?.foo5() = foo<A>()
|
||||
|
||||
// 1 LDC "T"
|
||||
// 1 LDC "Y\?"
|
||||
// 1 LDC "Z\?"
|
||||
// 1 LDC "X\?"
|
||||
// 1 LDC "A"
|
||||
@@ -0,0 +1,15 @@
|
||||
inline fun <reified T> Any?.foo() = this is T?
|
||||
|
||||
inline fun <reified Y> Any?.foo2() = foo<Y?>()
|
||||
|
||||
inline fun <reified Z> Any?.foo3() = foo2<Z>()
|
||||
|
||||
inline fun <reified X> Any?.foo4() = foo2<X?>()
|
||||
|
||||
inline fun <reified A> Any?.foo5() = foo<A>()
|
||||
|
||||
// 1 LDC "T\?"
|
||||
// 1 LDC "Y\?"
|
||||
// 1 LDC "Z\?"
|
||||
// 1 LDC "X\?"
|
||||
// 1 LDC "A\?"
|
||||
@@ -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");
|
||||
|
||||
+72
@@ -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")
|
||||
|
||||
+22
@@ -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)
|
||||
|
||||
+72
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user