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:
@@ -2793,7 +2793,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
assert state.getReflectionTypes().getKClass().getTypeConstructor().equals(type.getConstructor())
|
assert state.getReflectionTypes().getKClass().getTypeConstructor().equals(type.getConstructor())
|
||||||
: "::class expression should be type checked to a KClass: " + type;
|
: "::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
|
@Override
|
||||||
@@ -2839,7 +2839,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@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>() {
|
return StackValue.operation(K_CLASS_TYPE, new Function1<InstructionAdapter, Unit>() {
|
||||||
@Override
|
@Override
|
||||||
public Unit invoke(InstructionAdapter v) {
|
public Unit invoke(InstructionAdapter v) {
|
||||||
@@ -2849,11 +2854,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
|
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
|
||||||
assert typeParameterDescriptor.isReified() :
|
assert typeParameterDescriptor.isReified() :
|
||||||
"Non-reified type parameter under ::class should be rejected by type checker: " + typeParameterDescriptor;
|
"Non-reified type parameter under ::class should be rejected by type checker: " + typeParameterDescriptor;
|
||||||
v.visitLdcInsn(typeParameterDescriptor.getName().asString());
|
assert codegen != null :
|
||||||
v.invokestatic(
|
"Reference to member of reified type should be rejected by type checker " + typeParameterDescriptor;
|
||||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME,
|
codegen.putReifierMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME);
|
||||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
putJavaLangClassInstance(v, classAsmType);
|
putJavaLangClassInstance(v, classAsmType);
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
@@ -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 cr = ClassReader(bytes)
|
||||||
|
|
||||||
val inlineFunctions = inlineFunctionsJvmNames(bytes)
|
val inlineFunctions = inlineFunctionsJvmNames(bytes)
|
||||||
if (inlineFunctions.isEmpty()) continue
|
|
||||||
|
|
||||||
val classVisitor = object : ClassVisitorWithName() {
|
val classVisitor = object : ClassVisitorWithName() {
|
||||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor {
|
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<String>?): MethodVisitor {
|
||||||
|
|||||||
+12
@@ -1108,6 +1108,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
doTestMultiFileWithInlineCheck(fileName);
|
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")
|
@TestMetadata("packages.1.kt")
|
||||||
public void testPackages() throws Exception {
|
public void testPackages() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt");
|
||||||
|
|||||||
+12
@@ -1108,6 +1108,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
doBoxTestWithInlineCheck(fileName);
|
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")
|
@TestMetadata("packages.1.kt")
|
||||||
public void testPackages() throws Exception {
|
public void testPackages() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user