diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 7008756a055..566c321ffd8 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -3810,7 +3810,7 @@ The "returned" value of try expression with no finally is either the last expres return StackValue.onStack(type); } - private void putReifierMarkerIfTypeIsReifiedParameter(@NotNull JetType type, @NotNull String markerMethodName) { + public void putReifierMarkerIfTypeIsReifiedParameter(@NotNull JetType type, @NotNull String markerMethodName) { TypeParameterDescriptor typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type); if (typeParameterDescriptor != null && typeParameterDescriptor.isReified()) { v.iconst(typeParameterDescriptor.getIndex()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/ReifiedTypeInliner.kt b/compiler/backend/src/org/jetbrains/jet/codegen/inline/ReifiedTypeInliner.kt index 7b08345834d..9ad6ad5b494 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/ReifiedTypeInliner.kt +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/ReifiedTypeInliner.kt @@ -37,6 +37,7 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame public val NEW_ARRAY_MARKER_METHOD_NAME: String = "reifyNewArray" public val CHECKCAST_MARKER_METHOD_NAME: String = "reifyCheckcast" public val INSTANCEOF_MARKER_METHOD_NAME: String = "reifyInstanceof" + public val JAVA_CLASS_MARKER_METHOD_NAME: String = "reifyJavaClass" } public fun reifyInstructions(instructions: InsnList) { @@ -62,6 +63,7 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame NEW_ARRAY_MARKER_METHOD_NAME -> processNewArray(insn, asmType) CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, asmType) INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, asmType) + JAVA_CLASS_MARKER_METHOD_NAME -> processJavaClass(insn, asmType) else -> false }) { return @@ -88,6 +90,13 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame return true } + private fun processJavaClass(insn: MethodInsnNode, parameter: Type): Boolean { + val next = insn.getNext() + if (next !is LdcInsnNode) return false + next.cst = parameter + return true + } + private fun getParameterIndex(insn: MethodInsnNode): Int? { val prev = insn.getPrevious()!! diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/JavaClassFunction.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/JavaClassFunction.java index 4853eb4130b..6d2a146ad11 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/JavaClassFunction.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/JavaClassFunction.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.StackValue; +import org.jetbrains.jet.codegen.inline.ReifiedTypeInliner; import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage; @@ -49,7 +50,12 @@ public class JavaClassFunction extends IntrinsicMethod { (JetElement) element, codegen.getBindingContext()); JetType returnType = resolvedCall.getResultingDescriptor().getReturnType(); assert returnType != null; - putJavaLangClassInstance(v, codegen.getState().getTypeMapper().mapType(returnType.getArguments().get(0).getType())); + + JetType type = returnType.getArguments().get(0).getType(); + + codegen.putReifierMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME); + + putJavaLangClassInstance(v, codegen.getState().getTypeMapper().mapType(type)); return getType(Class.class); } diff --git a/compiler/testData/codegen/boxWithStdlib/reified/defaultJavaClass.kt b/compiler/testData/codegen/boxWithStdlib/reified/defaultJavaClass.kt new file mode 100644 index 00000000000..462611eab6b --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reified/defaultJavaClass.kt @@ -0,0 +1,17 @@ +import kotlin.test.assertEquals + +inline fun foo(x: Class = javaClass()): String = x.getName() + +inline fun bar(x: R): String = foo() + +fun box(): String { + assertEquals("java.lang.String", foo()) + assertEquals("java.lang.Integer", foo()) + assertEquals("java.lang.Object", foo()) + + assertEquals("java.lang.String", bar("abc")) + assertEquals("java.lang.Integer", bar(1)) + assertEquals("java.lang.Object", bar(Any())) + + return "OK" +} diff --git a/compiler/testData/codegen/boxWithStdlib/reified/javaClass.kt b/compiler/testData/codegen/boxWithStdlib/reified/javaClass.kt new file mode 100644 index 00000000000..7159bd28763 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reified/javaClass.kt @@ -0,0 +1,12 @@ +import kotlin.test.assertEquals + +inline fun javaClassName(): String { + return javaClass().getName() +} + +fun box(): String { + assertEquals("java.lang.String", javaClassName()) + assertEquals("java.lang.Integer", javaClassName()) + assertEquals("java.lang.Object", javaClassName()) + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 9fe1df46888..14a65b5e9a4 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -2426,6 +2426,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("defaultJavaClass.kt") + public void testDefaultJavaClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/defaultJavaClass.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("filterIsInstance.kt") public void testFilterIsInstance() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/filterIsInstance.kt"); @@ -2438,6 +2444,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("javaClass.kt") + public void testJavaClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/javaClass.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("newArrayInt.kt") public void testNewArrayInt() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/newArrayInt.kt"); diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/Intrinsics.java b/core/runtime.jvm/src/kotlin/jvm/internal/Intrinsics.java index cc2801d4865..2cf6cb7883a 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/Intrinsics.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/Intrinsics.java @@ -118,6 +118,10 @@ public class Intrinsics { throwUndefinedForReified(); } + public static void reifyJavaClass(int parameterTypeIndex) { + throwUndefinedForReified(); + } + public static T sanitizeStackTrace(T throwable) { StackTraceElement[] stackTrace = throwable.getStackTrace(); ArrayList list = new ArrayList(stackTrace.length);