Fix for KT-9637: Runtime crash when using class literal in inline functions with reified type parameters

#KT-9637 Fixed
This commit is contained in:
Michael Bogdanov
2015-10-29 16:23:41 +03:00
parent 34fccc6dae
commit f3092bf390
8 changed files with 83 additions and 8 deletions
@@ -2793,7 +2793,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
assert state.getReflectionTypes().getKClass().getTypeConstructor().equals(type.getConstructor())
: "::class expression should be type checked to a KClass: " + type;
return generateClassLiteralReference(typeMapper, CollectionsKt.single(type.getArguments()).getType());
return generateClassLiteralReference(typeMapper, CollectionsKt.single(type.getArguments()).getType(), this);
}
@Override
@@ -2839,7 +2839,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
@NotNull
public static StackValue generateClassLiteralReference(@NotNull final JetTypeMapper typeMapper, @NotNull final KotlinType type) {
public static StackValue generateClassLiteralReference(@NotNull JetTypeMapper typeMapper, @NotNull KotlinType type) {
return generateClassLiteralReference(typeMapper, type, null);
}
@NotNull
private static StackValue generateClassLiteralReference(@NotNull final JetTypeMapper typeMapper, @NotNull final KotlinType type, @Nullable final ExpressionCodegen codegen) {
return StackValue.operation(K_CLASS_TYPE, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter v) {
@@ -2849,11 +2854,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
assert typeParameterDescriptor.isReified() :
"Non-reified type parameter under ::class should be rejected by type checker: " + typeParameterDescriptor;
v.visitLdcInsn(typeParameterDescriptor.getName().asString());
v.invokestatic(
IntrinsicMethods.INTRINSICS_CLASS_NAME, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME,
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false
);
assert codegen != null :
"Reference to member of reified type should be rejected by type checker " + typeParameterDescriptor;
codegen.putReifierMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME);
}
putJavaLangClassInstance(v, classAsmType);
+15
View File
@@ -0,0 +1,15 @@
//NO_CHECK_LAMBDA_INLINING
import test.*
class Boxer {
val box: () -> Box by injectFnc()
}
fun box(): String {
val box = Box()
registerFnc { box }
val prop = Boxer().box
if (prop() != box) return "fail 1"
return "OK"
}
+16
View File
@@ -0,0 +1,16 @@
package test
import java.util.*
import kotlin.reflect.KClass
val valuesInjectFnc = HashMap<KClass<out Any>, Any>()
inline fun <reified T : Any> injectFnc(): Lazy<Function0<T>> = lazy(LazyThreadSafetyMode.NONE) {
(valuesInjectFnc[T::class] ?: throw Exception("no inject ${T::class.simpleName}")) as Function0<T>
}
inline fun <reified T : Any> registerFnc(noinline value: Function0<T>) {
valuesInjectFnc[T::class] = value
}
public class Box
@@ -0,0 +1,8 @@
import test.*
fun box(): String {
val boxClass = injectFnc<Box>()
if (boxClass != Box::class) return "fail 1"
return "OK"
}
@@ -0,0 +1,10 @@
package test
import kotlin.reflect.KClass
inline fun <reified T : Any> injectFnc(): KClass<T> = {
T::class
} ()
public class Box
@@ -65,7 +65,6 @@ public object InlineTestUtil {
val cr = ClassReader(bytes)
val inlineFunctions = inlineFunctionsJvmNames(bytes)
if (inlineFunctions.isEmpty()) continue
val classVisitor = object : ClassVisitorWithName() {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor {
@@ -1108,6 +1108,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
doTestMultiFileWithInlineCheck(fileName);
}
@TestMetadata("kt9637.1.kt")
public void testKt9637() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt9637.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
@TestMetadata("kt9637_2.1.kt")
public void testKt9637_2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt9637_2.1.kt");
doTestMultiFileWithInlineCheck(fileName);
}
@TestMetadata("packages.1.kt")
public void testPackages() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt");
@@ -1108,6 +1108,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
doBoxTestWithInlineCheck(fileName);
}
@TestMetadata("kt9637.1.kt")
public void testKt9637() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt9637.1.kt");
doBoxTestWithInlineCheck(fileName);
}
@TestMetadata("kt9637_2.1.kt")
public void testKt9637_2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt9637_2.1.kt");
doBoxTestWithInlineCheck(fileName);
}
@TestMetadata("packages.1.kt")
public void testPackages() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt");