Support class reference expression for reified type parameters
Also make KClass::java an intrinsic property. Based on the work by @dnpetrov #KT-6976 Fixed
This commit is contained in:
@@ -38,7 +38,7 @@ import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
|
||||
import org.jetbrains.kotlin.codegen.inline.*;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethod;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicPropertyGetter;
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsnsPackage;
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
@@ -53,7 +53,6 @@ import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo;
|
||||
import org.jetbrains.kotlin.jvm.bindingContextSlices.BindingContextSlicesPackage;
|
||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
@@ -1981,10 +1980,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
CallableMemberDescriptor memberDescriptor = DescriptorUtils.unwrapFakeOverride((CallableMemberDescriptor) descriptor);
|
||||
|
||||
IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor);
|
||||
if (intrinsic instanceof JavaClassProperty) {
|
||||
if (intrinsic instanceof IntrinsicPropertyGetter) {
|
||||
//TODO: intrinsic properties (see intermediateValueForProperty)
|
||||
Type returnType = typeMapper.mapType(memberDescriptor);
|
||||
return ((JavaClassProperty) intrinsic).generate(returnType, receiver);
|
||||
StackValue intrinsicResult = ((IntrinsicPropertyGetter) intrinsic).generate(resolvedCall, this, returnType, receiver);
|
||||
if (intrinsicResult != null) return intrinsicResult;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2498,15 +2498,17 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
TypeParameterDescriptor key = entry.getKey();
|
||||
if (!key.isReified()) continue;
|
||||
|
||||
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(entry.getValue());
|
||||
JetType type = entry.getValue();
|
||||
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type);
|
||||
if (parameterDescriptor == null) {
|
||||
// type is not generic
|
||||
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
|
||||
Type type = typeMapper.mapTypeParameter(entry.getValue(), signatureWriter);
|
||||
Type asmType = typeMapper.mapTypeParameter(type, signatureWriter);
|
||||
|
||||
mappings.addParameterMappingToType(
|
||||
key.getName().getIdentifier(),
|
||||
type,
|
||||
asmType,
|
||||
signatureWriter.toString()
|
||||
);
|
||||
}
|
||||
@@ -2813,12 +2815,25 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
Type classAsmType = typeMapper.mapType(type);
|
||||
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
//noinspection ConstantConditions
|
||||
ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor);
|
||||
// Instantiate annotation classes as foreign due to bug in JDK 6 and 7:
|
||||
// http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6857918
|
||||
if (descriptor instanceof JavaClassDescriptor || module == module.getBuiltIns().getBuiltInsModule() ||
|
||||
DescriptorUtils.isAnnotationClass(descriptor)) {
|
||||
if (descriptor instanceof TypeParameterDescriptor) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
|
||||
if (typeParameterDescriptor.isReified()) {
|
||||
// Emit reified type parameters as Kotlin classes.
|
||||
// ReifiedTypeInliner will rewrite the following GETSTATIC to proper bytecode instructions
|
||||
// if the class literal for actual type should be emitted with wrapped Java class.
|
||||
v.visitLdcInsn(typeParameterDescriptor.getName().asString());
|
||||
v.invokestatic(
|
||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, ReifiedTypeInliner.CLASS_LITERAL_MARKER_METHOD_NAME,
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false
|
||||
);
|
||||
v.getstatic(classAsmType.getInternalName(), JvmAbi.KOTLIN_CLASS_FIELD_NAME, K_CLASS_TYPE.getDescriptor());
|
||||
}
|
||||
else {
|
||||
throw new AssertionError("Non-reified type parameter under ::class should be rejected by type checker: " +
|
||||
typeParameterDescriptor.getName().asString());
|
||||
}
|
||||
}
|
||||
else if (shouldUseJavaClassForClassLiteral(descriptor)) {
|
||||
putJavaLangClassInstance(v, classAsmType);
|
||||
wrapJavaClassIntoKClass(v);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||
import org.jetbrains.kotlin.codegen.context.PackageContext;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment;
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass;
|
||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass;
|
||||
@@ -237,4 +238,11 @@ public class JvmCodegenUtil {
|
||||
return InlineUtil.canBeInlineArgument(declaration) &&
|
||||
InlineUtil.isInlinedArgument((JetFunction) declaration, bindingContext, false);
|
||||
}
|
||||
|
||||
public static boolean shouldUseJavaClassForClassLiteral(@NotNull ClassifierDescriptor descriptor) {
|
||||
ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor);
|
||||
return descriptor instanceof JavaClassDescriptor ||
|
||||
module == module.getBuiltIns().getBuiltInsModule() ||
|
||||
DescriptorUtils.isAnnotationClass(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,21 +16,21 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.TypeInsnNode
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import kotlin.platform.platformStatic
|
||||
import org.jetbrains.org.objectweb.asm.tree.LdcInsnNode
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
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.signature.SignatureReader
|
||||
import org.jetbrains.org.objectweb.asm.signature.SignatureWriter
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import kotlin.platform.platformStatic
|
||||
|
||||
public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParameterMappings?) {
|
||||
|
||||
@@ -39,11 +39,13 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
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 val CLASS_LITERAL_MARKER_METHOD_NAME: String = "reifyClassLiteral"
|
||||
public val NEED_CLASS_REIFICATION_MARKER_METHOD_NAME: String = "needClassReification"
|
||||
|
||||
private val PARAMETRISED_MARKERS = ImmutableSet.of(
|
||||
NEW_ARRAY_MARKER_METHOD_NAME, CHECKCAST_MARKER_METHOD_NAME,
|
||||
INSTANCEOF_MARKER_METHOD_NAME, JAVA_CLASS_MARKER_METHOD_NAME
|
||||
INSTANCEOF_MARKER_METHOD_NAME, JAVA_CLASS_MARKER_METHOD_NAME,
|
||||
CLASS_LITERAL_MARKER_METHOD_NAME
|
||||
)
|
||||
|
||||
private fun isParametrisedReifiedMarker(insn: AbstractInsnNode) =
|
||||
@@ -139,6 +141,7 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, asmType)
|
||||
INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, asmType)
|
||||
JAVA_CLASS_MARKER_METHOD_NAME -> processJavaClass(insn, asmType)
|
||||
CLASS_LITERAL_MARKER_METHOD_NAME -> processClassLiteral(insn, asmType, instructions, mapping.type!!)
|
||||
else -> false
|
||||
}) {
|
||||
instructions.remove(insn.getPrevious()!!)
|
||||
@@ -153,13 +156,13 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
}
|
||||
|
||||
private fun processNewArray(insn: MethodInsnNode, parameter: Type) =
|
||||
processNextTypeInsn(insn, parameter, Opcodes.ANEWARRAY)
|
||||
processNextTypeInsn(insn, parameter, Opcodes.ANEWARRAY)
|
||||
|
||||
private fun processCheckcast(insn: MethodInsnNode, parameter: Type) =
|
||||
processNextTypeInsn(insn, parameter, Opcodes.CHECKCAST)
|
||||
processNextTypeInsn(insn, parameter, Opcodes.CHECKCAST)
|
||||
|
||||
private fun processInstanceof(insn: MethodInsnNode, parameter: Type) =
|
||||
processNextTypeInsn(insn, parameter, Opcodes.INSTANCEOF)
|
||||
processNextTypeInsn(insn, parameter, Opcodes.INSTANCEOF)
|
||||
|
||||
private fun processNextTypeInsn(insn: MethodInsnNode, parameter: Type, expectedNextOpcode: Int): Boolean {
|
||||
if (insn.getNext()?.getOpcode() != expectedNextOpcode) return false
|
||||
@@ -174,6 +177,30 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
return true
|
||||
}
|
||||
|
||||
private fun processClassLiteral(insn: MethodInsnNode, parameter: Type, instructions: InsnList, type: JetType): Boolean {
|
||||
val next = insn.next
|
||||
if (next !is FieldInsnNode || next.opcode != Opcodes.GETSTATIC) return false
|
||||
val descriptor = type.constructor.declarationDescriptor!!
|
||||
if (JvmCodegenUtil.shouldUseJavaClassForClassLiteral(descriptor)) {
|
||||
instructions.insertBefore(
|
||||
next,
|
||||
if (AsmUtil.isPrimitive(parameter))
|
||||
FieldInsnNode(Opcodes.GETSTATIC, AsmUtil.boxType(parameter).internalName, "TYPE", "Ljava/lang/Class;")
|
||||
else
|
||||
LdcInsnNode(parameter)
|
||||
)
|
||||
val foreignKotlinClassDesc = Type.getMethodDescriptor(AsmTypes.K_CLASS_TYPE, AsmTypes.JAVA_CLASS_TYPE)
|
||||
instructions.insertBefore(
|
||||
next, MethodInsnNode(Opcodes.INVOKESTATIC, AsmTypes.REFLECTION, "foreignKotlinClass", foreignKotlinClassDesc, false)
|
||||
)
|
||||
instructions.remove(next)
|
||||
}
|
||||
else {
|
||||
next.owner = AsmUtil.boxType(parameter).internalName
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun getParameterName(insn: MethodInsnNode): String? {
|
||||
val prev = insn.getPrevious()!!
|
||||
|
||||
@@ -191,12 +218,12 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
||||
public class ReifiedTypeParameterMappings() {
|
||||
private val mappingsByName = hashMapOf<String, ReifiedTypeParameterMapping>()
|
||||
|
||||
public fun addParameterMappingToType(name: String, asmType: Type, signature: String) {
|
||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, asmType, newName = null, signature = signature)
|
||||
public fun addParameterMappingToType(name: String, type: JetType, asmType: Type, signature: String) {
|
||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, type, asmType, newName = null, signature = signature)
|
||||
}
|
||||
|
||||
public fun addParameterMappingToNewParameter(name: String, newName: String) {
|
||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, asmType = null, newName = newName, signature = null)
|
||||
mappingsByName[name] = ReifiedTypeParameterMapping(name, type = null, asmType = null, newName = newName, signature = null)
|
||||
}
|
||||
|
||||
fun get(name: String): ReifiedTypeParameterMapping? {
|
||||
@@ -204,7 +231,9 @@ public class ReifiedTypeParameterMappings() {
|
||||
}
|
||||
}
|
||||
|
||||
public class ReifiedTypeParameterMapping(val name: String, val asmType: Type?, val newName: String?, val signature: String?)
|
||||
public class ReifiedTypeParameterMapping(
|
||||
val name: String, val type: JetType?, val asmType: Type?, val newName: String?, val signature: String?
|
||||
)
|
||||
|
||||
public class ReifiedTypeParametersUsages {
|
||||
val usedTypeParameters: MutableSet<String> = hashSetOf()
|
||||
|
||||
@@ -62,6 +62,7 @@ public class IntrinsicMethods {
|
||||
public IntrinsicMethods() {
|
||||
namedMethods.put("kotlin.javaClass.function", new JavaClassFunction());
|
||||
namedMethods.put("kotlin.javaClass.property", new JavaClassProperty());
|
||||
namedMethods.put("kotlin.KClass.java.property", new KClassJavaProperty());
|
||||
namedMethods.put("kotlin.arrays.array", new JavaClassArray());
|
||||
namedMethods.put("kotlin.jvm.internal.unsafe.monitorEnter", MonitorInstruction.MONITOR_ENTER);
|
||||
namedMethods.put("kotlin.jvm.internal.unsafe.monitorExit", MonitorInstruction.MONITOR_EXIT);
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
public abstract class IntrinsicPropertyGetter : IntrinsicMethod() {
|
||||
public abstract fun generate(
|
||||
resolvedCall: ResolvedCall<*>?,
|
||||
codegen: ExpressionCodegen,
|
||||
returnType: Type,
|
||||
receiver: StackValue
|
||||
): StackValue?
|
||||
}
|
||||
@@ -28,8 +28,13 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
public class JavaClassProperty : IntrinsicMethod() {
|
||||
public fun generate(returnType: Type, receiver: StackValue): StackValue =
|
||||
public class JavaClassProperty : IntrinsicPropertyGetter() {
|
||||
public override fun generate(
|
||||
resolvedCall: ResolvedCall<*>?,
|
||||
codegen: ExpressionCodegen,
|
||||
returnType: Type,
|
||||
receiver: StackValue
|
||||
): StackValue? =
|
||||
StackValue.operation(returnType) {
|
||||
val actualType = generateImpl(it, receiver)
|
||||
StackValue.coerce(actualType, returnType, it)
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.psi.JetClassLiteralExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
public class KClassJavaProperty : IntrinsicPropertyGetter() {
|
||||
override fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? {
|
||||
val type = resolvedCall!!.extensionReceiver.type.arguments.single().type
|
||||
val asmType = codegen.state.typeMapper.mapType(type)
|
||||
|
||||
return when {
|
||||
isReifiedTypeParameter(type) -> {
|
||||
StackValue.operation(returnType) { iv ->
|
||||
codegen.putReifierMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME)
|
||||
AsmUtil.putJavaLangClassInstance(iv, asmType)
|
||||
coerceToJavaLangClass(iv, returnType)
|
||||
}
|
||||
}
|
||||
isWithClassLiteralArgument(resolvedCall) -> {
|
||||
StackValue.operation(returnType) { iv ->
|
||||
if (AsmUtil.isPrimitive(asmType)) {
|
||||
iv.getstatic(AsmUtil.boxType(asmType).internalName, "TYPE", "Ljava/lang/Class;")
|
||||
}
|
||||
else {
|
||||
iv.tconst(asmType)
|
||||
}
|
||||
coerceToJavaLangClass(iv, returnType)
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun isReifiedTypeParameter(type: JetType): Boolean {
|
||||
val typeDescriptor = type.constructor.declarationDescriptor
|
||||
return typeDescriptor is TypeParameterDescriptor && typeDescriptor.isReified
|
||||
}
|
||||
|
||||
private fun isWithClassLiteralArgument(resolvedCall: ResolvedCall<*>): Boolean {
|
||||
val extensionReceiver = resolvedCall.extensionReceiver
|
||||
return extensionReceiver is ExpressionReceiver && extensionReceiver.expression is JetClassLiteralExpression
|
||||
}
|
||||
|
||||
private fun coerceToJavaLangClass(iv: InstructionAdapter, returnType: Type) {
|
||||
StackValue.coerce(AsmTypes.JAVA_CLASS_TYPE, returnType, iv)
|
||||
}
|
||||
}
|
||||
+13
-7
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
|
||||
import org.jetbrains.kotlin.lexer.JetTokens;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
@@ -585,16 +584,23 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (type.isMarkedNullable()) return false;
|
||||
|
||||
TypeConstructor typeConstructor = type.getConstructor();
|
||||
if (!(typeConstructor.getDeclarationDescriptor() instanceof ClassDescriptor)) return false;
|
||||
ClassifierDescriptor typeDeclarationDescriptor = typeConstructor.getDeclarationDescriptor();
|
||||
|
||||
List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
|
||||
if (parameters.size() != type.getArguments().size()) return false;
|
||||
if (typeDeclarationDescriptor instanceof ClassDescriptor) {
|
||||
List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
|
||||
if (parameters.size() != type.getArguments().size()) return false;
|
||||
|
||||
for (TypeParameterDescriptor parameter : parameters) {
|
||||
if (!parameter.isReified()) return false;
|
||||
for (TypeParameterDescriptor parameter : parameters) {
|
||||
if (!parameter.isReified()) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (typeDeclarationDescriptor instanceof TypeParameterDescriptor) {
|
||||
return ((TypeParameterDescriptor) typeDeclarationDescriptor).isReified();
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
import kotlin.test.*
|
||||
import kotlin.reflect.jvm.java
|
||||
|
||||
class Klass
|
||||
class Other
|
||||
|
||||
inline fun <reified T> simpleName(): String =
|
||||
T::class.simpleName!!
|
||||
|
||||
inline fun <reified T1, reified T2> twoReifiedParams(): String =
|
||||
"${T1::class.simpleName!!}, ${T2::class.simpleName!!}"
|
||||
|
||||
inline fun <reified T> myJavaClass(): Class<T> =
|
||||
T::class.java
|
||||
|
||||
fun box(): String {
|
||||
assertEquals("Klass", simpleName<Klass>())
|
||||
assertEquals("Int", simpleName<Int>())
|
||||
assertEquals("Array", simpleName<Array<Int>>())
|
||||
assertEquals("Error", simpleName<Error>())
|
||||
assertEquals("Klass, Other", twoReifiedParams<Klass, Other>())
|
||||
|
||||
assertEquals(javaClass<String>(), myJavaClass<String>())
|
||||
assertEquals(javaClass<IntArray>(), myJavaClass<IntArray>())
|
||||
assertEquals(javaClass<Klass>(), myJavaClass<Klass>())
|
||||
assertEquals(javaClass<Error>(), myJavaClass<Error>())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import kotlin.reflect.jvm.java
|
||||
|
||||
class Klass
|
||||
|
||||
fun foo() {
|
||||
val c0 = (Klass::class).java // prevent intrinsic .java for class literal
|
||||
val c1 = Klass::class.java
|
||||
val c2 = Int::class.java
|
||||
val c3 = Integer::class.java
|
||||
|
||||
}
|
||||
|
||||
// 2 LDC LKlass;.class
|
||||
// 1 GETSTATIC java/lang/Integer.TYPE : Ljava/lang/Class;
|
||||
// 1 INVOKESTATIC kotlin/reflect/jvm.*\.getJava
|
||||
// 1 LDC Ljava/lang/Integer;.class
|
||||
@@ -131,6 +131,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("javaExtensionPropertyIntrinsic.kt")
|
||||
public void testJavaExtensionPropertyIntrinsic() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/javaExtensionPropertyIntrinsic.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt2202.kt")
|
||||
public void testKt2202() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/kt2202.kt");
|
||||
|
||||
+21
@@ -2886,6 +2886,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedTypeClassLiteral.kt")
|
||||
public void testReifiedTypeClassLiteral() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals/reifiedTypeClassLiteral.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simpleClassLiteral.kt")
|
||||
public void testSimpleClassLiteral() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals/simpleClassLiteral.kt");
|
||||
@@ -3331,6 +3337,21 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/noKotlinReflect")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class NoKotlinReflect extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInNoKotlinReflect() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection/noKotlinReflect"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("simpleClassLiterals.kt")
|
||||
public void testSimpleClassLiterals() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/noKotlinReflect/simpleClassLiterals.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/packages")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Modifier
|
||||
import kotlin.jvm.internal.Intrinsic
|
||||
import kotlin.reflect.*
|
||||
import kotlin.reflect.jvm.internal.*
|
||||
|
||||
@@ -28,6 +29,7 @@ import kotlin.reflect.jvm.internal.*
|
||||
/**
|
||||
* Returns a Java [Class] instance corresponding to the given [KClass] instance.
|
||||
*/
|
||||
@Intrinsic("kotlin.KClass.java.property")
|
||||
public val <T> KClass<T>.java: Class<T>
|
||||
get() = (this as KClassImpl<T>).jClass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user