JVM: partially reify typeOf and signatures as soon as possible
E.g. when substituting T -> Array<T>, write the bytecode for the Array<...> part for typeOf. This fixes various issues where either Array nesting levels, nullability information (for typeOf), or entire reification markers were missing, causing incorrect outputs ranging from missing `?`s to missing `[]`s to just reified types not really being reified. ^KT-53761 Fixed
This commit is contained in:
@@ -2928,33 +2928,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
@NotNull
|
||||
CallGenerator getOrCreateCallGenerator(@NotNull ResolvedCall<?> resolvedCall, @NotNull CallableDescriptor descriptor) {
|
||||
Map<TypeParameterDescriptor, KotlinType> typeArguments = getTypeArgumentsForResolvedCall(resolvedCall, descriptor);
|
||||
|
||||
TypeParameterMappings<KotlinType> mappings = new TypeParameterMappings<>();
|
||||
for (Map.Entry<TypeParameterDescriptor, KotlinType> entry : typeArguments.entrySet()) {
|
||||
TypeParameterDescriptor key = entry.getKey();
|
||||
KotlinType type = entry.getValue();
|
||||
|
||||
boolean isReified = key.isReified() || InlineUtil.isArrayConstructorWithLambda(resolvedCall.getResultingDescriptor());
|
||||
|
||||
Pair<TypeParameterMarker, ReificationArgument> typeParameterAndReificationArgument =
|
||||
extractReificationArgument(typeSystem, type);
|
||||
if (typeParameterAndReificationArgument == null) {
|
||||
KotlinType approximatedType = approximateCapturedType(type);
|
||||
JvmSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE);
|
||||
Type asmType = typeMapper.mapTypeArgument(approximatedType, signatureWriter);
|
||||
|
||||
mappings.addParameterMappingToType(
|
||||
key.getName().getIdentifier(), approximatedType, asmType, signatureWriter.toString(), isReified
|
||||
);
|
||||
}
|
||||
else {
|
||||
mappings.addParameterMappingForFurtherReification(
|
||||
key.getName().getIdentifier(), type, typeParameterAndReificationArgument.getSecond(), isReified
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TypeParameterMappings<KotlinType> mappings = new TypeParameterMappings<>(
|
||||
typeSystem,
|
||||
getTypeArgumentsForResolvedCall(resolvedCall, descriptor),
|
||||
InlineUtil.isArrayConstructorWithLambda(resolvedCall.getResultingDescriptor()),
|
||||
(KotlinType type, BothSignatureWriter sw) -> typeMapper.mapTypeArgument(approximateCapturedType(type), sw)
|
||||
);
|
||||
return getOrCreateCallGenerator(descriptor, resolvedCall.getCall().getCallElement(), mappings, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_ASM_TYPE
|
||||
import org.jetbrains.kotlin.codegen.coroutines.unwrapInitialDescriptorForSuspendFunction
|
||||
import org.jetbrains.kotlin.codegen.inline.NUMBERED_FUNCTION_PREFIX
|
||||
import org.jetbrains.kotlin.codegen.inline.ReificationArgument
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
@@ -386,6 +387,7 @@ fun TypeSystemCommonBackendContext.extractReificationArgument(initialType: Kotli
|
||||
val isNullable = type.isMarkedNullable()
|
||||
while (type.isArrayOrNullableArray()) {
|
||||
arrayDepth++
|
||||
// TODO: warn that nullability info on argument will be lost?
|
||||
val argument = type.getArgument(0)
|
||||
if (argument.isStarProjection()) return null
|
||||
type = argument.getType()
|
||||
@@ -396,6 +398,24 @@ fun TypeSystemCommonBackendContext.extractReificationArgument(initialType: Kotli
|
||||
return Pair(typeParameter, ReificationArgument(typeParameter.getName().asString(), isNullable, arrayDepth))
|
||||
}
|
||||
|
||||
fun TypeSystemCommonBackendContext.extractUsedReifiedParameters(type: KotlinTypeMarker): ReifiedTypeParametersUsages =
|
||||
ReifiedTypeParametersUsages().apply {
|
||||
fun KotlinTypeMarker.visit() {
|
||||
val typeParameter = typeConstructor().getTypeParameterClassifier()
|
||||
if (typeParameter == null) {
|
||||
for (argument in getArguments()) {
|
||||
if (!argument.isStarProjection()) {
|
||||
argument.getType().visit()
|
||||
}
|
||||
}
|
||||
} else if (typeParameter.isReified()) {
|
||||
addUsedReifiedParameter(typeParameter.getName().asString())
|
||||
}
|
||||
}
|
||||
|
||||
type.visit()
|
||||
}
|
||||
|
||||
fun unwrapInitialSignatureDescriptor(function: FunctionDescriptor): FunctionDescriptor =
|
||||
function.initialSignatureDescriptor ?: function
|
||||
|
||||
|
||||
@@ -30,16 +30,16 @@ class AsmTypeRemapper(val typeRemapper: TypeRemapper, val result: InlineResult)
|
||||
return object : SignatureRemapper(v, this) {
|
||||
override fun visitTypeVariable(name: String) {
|
||||
/*TODO try to erase absent type variable*/
|
||||
val mapping = typeRemapper.mapTypeParameter(name) ?: return super.visitTypeVariable(name)
|
||||
|
||||
if (mapping.newName != null) {
|
||||
val mapping = typeRemapper.mapTypeParameter(name)
|
||||
if (mapping != null) {
|
||||
// TODO: what is this condition
|
||||
if (mapping.isReified) {
|
||||
result.reifiedTypeParametersUsages.addUsedReifiedParameter(mapping.newName)
|
||||
result.reifiedTypeParametersUsages.mergeAll(mapping.reifiedTypeParametersUsages)
|
||||
}
|
||||
return super.visitTypeVariable(mapping.newName)
|
||||
SignatureReader(mapping.signature).accept(v)
|
||||
return
|
||||
}
|
||||
// else TypeVariable is replaced by concrete type
|
||||
SignatureReader(mapping.signature).accept(v)
|
||||
return super.visitTypeVariable(name)
|
||||
}
|
||||
|
||||
override fun visitFormalTypeParameter(name: String) {
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.codegen.extractReificationArgument
|
||||
import org.jetbrains.kotlin.codegen.extractUsedReifiedParameters
|
||||
import org.jetbrains.kotlin.codegen.generateAsCast
|
||||
import org.jetbrains.kotlin.codegen.generateIsCheck
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.intConstant
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -147,9 +150,9 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
||||
val result = ReifiedTypeParametersUsages()
|
||||
for (insn in instructions.toArray()) {
|
||||
if (isOperationReifiedMarker(insn)) {
|
||||
val newName: String? = processReifyMarker(insn as MethodInsnNode, instructions)
|
||||
if (newName != null) {
|
||||
result.addUsedReifiedParameter(newName)
|
||||
val newNames = processReifyMarker(insn as MethodInsnNode, instructions)
|
||||
if (newNames != null) {
|
||||
result.mergeAll(newNames)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,33 +161,34 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @return new type parameter identifier if this marker should be reified further
|
||||
* or null if it shouldn't
|
||||
*/
|
||||
private fun processReifyMarker(insn: MethodInsnNode, instructions: InsnList): String? {
|
||||
private fun processReifyMarker(insn: MethodInsnNode, instructions: InsnList): ReifiedTypeParametersUsages? {
|
||||
val operationKind = insn.operationKind ?: return null
|
||||
val reificationArgument = insn.reificationArgument ?: return null
|
||||
val mapping = parametersMapping?.get(reificationArgument.parameterName) ?: return null
|
||||
|
||||
if (mapping.asmType != 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
|
||||
val (asmType, type) = reify(reificationArgument, mapping.asmType, mapping.type)
|
||||
|
||||
val kotlinType = intrinsicsSupport.toKotlinType(type)
|
||||
|
||||
var processed = if (isPluginNext(insn)) processPlugin(insn, instructions, type) else false
|
||||
|
||||
if (!processed) processed = when (operationKind) {
|
||||
val asmType = mapping.asmType.reify(reificationArgument)
|
||||
val type = mapping.type.reify(reificationArgument)
|
||||
// Runtime-available types on the JVM are:
|
||||
// 1. Array<T?> for some runtime-available type T
|
||||
// 2. C<*, ...> and C<*, ...>? for some classifier C
|
||||
// `typeOf`-like intrinsics are special in that they can handle a bigger set of types, including
|
||||
// 1. Array<T> where T is not nullable
|
||||
// 2. C<A, B, ...> with non-star projections A, B, ...
|
||||
// To properly support those cases, we need to partially reify them even if we don't know the entire type yet.
|
||||
// Otherwise nullability on all but the innermost dimension of a multidimensional array will be lost,
|
||||
// and reified type parameters used as arguments to classifier types will never be reified.
|
||||
if (mapping.reificationArgument == null || operationKind == OperationKind.TYPE_OF) {
|
||||
val processed = (isPluginNext(insn) && processPlugin(insn, instructions, type)) || when (operationKind) {
|
||||
// TODO: if `process*` returns false, then the marked sequence is invalid - simply leaving the marker in place
|
||||
// will lead to an exception at runtime. What to do instead? Possible that the bytecode has been removed by
|
||||
// dead code elimination (e.g. result of `T::class.java` was unused) and now we only need to erase the marker.
|
||||
OperationKind.NEW_ARRAY -> processNewArray(insn, asmType)
|
||||
OperationKind.AS -> processAs(insn, instructions, kotlinType, asmType, safe = false)
|
||||
OperationKind.SAFE_AS -> processAs(insn, instructions, kotlinType, asmType, safe = true)
|
||||
OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType)
|
||||
OperationKind.AS -> processAs(insn, instructions, type, asmType, safe = false)
|
||||
OperationKind.SAFE_AS -> processAs(insn, instructions, type, asmType, safe = true)
|
||||
OperationKind.IS -> processIs(insn, instructions, type, asmType)
|
||||
OperationKind.JAVA_CLASS -> processJavaClass(insn, asmType)
|
||||
OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, instructions, asmType)
|
||||
OperationKind.TYPE_OF -> processTypeOfOrPlugin(insn, instructions, type)
|
||||
OperationKind.TYPE_OF -> processTypeOf(insn, instructions, type)
|
||||
}
|
||||
|
||||
if (processed) {
|
||||
@@ -192,24 +196,22 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
||||
instructions.remove(insn.previous!!) // PUSH type parameter
|
||||
instructions.remove(insn) // INVOKESTATIC marker method
|
||||
}
|
||||
|
||||
return null
|
||||
} else {
|
||||
val newReificationArgument = reificationArgument.combine(mapping.reificationArgument!!)
|
||||
val newReificationArgument = reificationArgument.combine(mapping.reificationArgument)
|
||||
instructions.set(insn.previous!!, LdcInsnNode(newReificationArgument.asString()))
|
||||
return mapping.reificationArgument.parameterName
|
||||
}
|
||||
return mapping.reifiedTypeParametersUsages
|
||||
}
|
||||
|
||||
private fun reify(argument: ReificationArgument, replacementAsmType: Type, type: KT): Pair<Type, KT> =
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun KT.reify(argument: ReificationArgument): KT =
|
||||
with(typeSystem) {
|
||||
val arrayType = type.arrayOf(argument.arrayDepth)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
Pair(
|
||||
Type.getType("[".repeat(argument.arrayDepth) + replacementAsmType),
|
||||
(if (argument.nullable) arrayType.makeNullable() else arrayType) as KT
|
||||
)
|
||||
}
|
||||
val withArrays = arrayOf(argument.arrayDepth)
|
||||
if (argument.nullable) withArrays.makeNullable() else withArrays
|
||||
} as KT
|
||||
|
||||
private fun Type.reify(argument: ReificationArgument): Type =
|
||||
Type.getType("[".repeat(argument.arrayDepth) + this)
|
||||
|
||||
private fun KotlinTypeMarker.arrayOf(arrayDepth: Int): KotlinTypeMarker {
|
||||
var currentType = this
|
||||
@@ -228,14 +230,14 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
||||
private fun processAs(
|
||||
insn: MethodInsnNode,
|
||||
instructions: InsnList,
|
||||
kotlinType: KotlinType,
|
||||
type: KT,
|
||||
asmType: Type,
|
||||
safe: Boolean
|
||||
) = rewriteNextTypeInsn(insn, Opcodes.CHECKCAST) { stubCheckcast: AbstractInsnNode ->
|
||||
if (stubCheckcast !is TypeInsnNode) return false
|
||||
|
||||
val newMethodNode = MethodNode(Opcodes.API_VERSION)
|
||||
generateAsCast(InstructionAdapter(newMethodNode), kotlinType, asmType, safe, unifiedNullChecks)
|
||||
generateAsCast(InstructionAdapter(newMethodNode), intrinsicsSupport.toKotlinType(type), asmType, safe, unifiedNullChecks)
|
||||
|
||||
instructions.insert(insn, newMethodNode.instructions)
|
||||
// Keep stubCheckcast to avoid VerifyErrors on 1.8+ bytecode,
|
||||
@@ -253,13 +255,13 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
||||
private fun processIs(
|
||||
insn: MethodInsnNode,
|
||||
instructions: InsnList,
|
||||
kotlinType: KotlinType,
|
||||
type: KT,
|
||||
asmType: Type
|
||||
) = rewriteNextTypeInsn(insn, Opcodes.INSTANCEOF) { stubInstanceOf: AbstractInsnNode ->
|
||||
if (stubInstanceOf !is TypeInsnNode) return false
|
||||
|
||||
val newMethodNode = MethodNode(Opcodes.API_VERSION)
|
||||
generateIsCheck(InstructionAdapter(newMethodNode), kotlinType, asmType)
|
||||
generateIsCheck(InstructionAdapter(newMethodNode), intrinsicsSupport.toKotlinType(type), asmType)
|
||||
|
||||
instructions.insert(insn, newMethodNode.instructions)
|
||||
instructions.remove(stubInstanceOf)
|
||||
@@ -269,7 +271,7 @@ class ReifiedTypeInliner<KT : KotlinTypeMarker>(
|
||||
return true
|
||||
}
|
||||
|
||||
private fun processTypeOfOrPlugin(
|
||||
private fun processTypeOf(
|
||||
insn: MethodInsnNode,
|
||||
instructions: InsnList,
|
||||
type: KT
|
||||
@@ -385,37 +387,43 @@ val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind?
|
||||
ReifiedTypeInliner.OperationKind.values().getOrNull(it)
|
||||
}
|
||||
|
||||
class TypeParameterMappings<KT : KotlinTypeMarker> {
|
||||
class TypeParameterMappings<KT : KotlinTypeMarker>(
|
||||
typeSystem: TypeSystemCommonBackendContext,
|
||||
typeArguments: Map<out TypeParameterMarker, KT>,
|
||||
allReified: Boolean,
|
||||
mapType: (KT, BothSignatureWriter) -> Type
|
||||
) {
|
||||
private val mappingsByName = hashMapOf<String, TypeParameterMapping<KT>>()
|
||||
|
||||
fun addParameterMappingToType(name: String, type: KT, asmType: Type, signature: String, isReified: Boolean) {
|
||||
mappingsByName[name] = TypeParameterMapping(
|
||||
name, type, asmType, reificationArgument = null, signature = signature, isReified = isReified
|
||||
)
|
||||
}
|
||||
|
||||
fun addParameterMappingForFurtherReification(name: String, type: KT, reificationArgument: ReificationArgument, isReified: Boolean) {
|
||||
mappingsByName[name] = TypeParameterMapping(
|
||||
name, type, asmType = null, reificationArgument = reificationArgument, signature = null, isReified = isReified
|
||||
)
|
||||
init {
|
||||
with(typeSystem) {
|
||||
for ((parameter, type) in typeArguments.entries) {
|
||||
val name = parameter.getName().identifier
|
||||
val sw = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
|
||||
mappingsByName[name] = TypeParameterMapping(
|
||||
type, mapType(type, sw), sw.toString(), allReified || parameter.isReified(),
|
||||
typeSystem.extractReificationArgument(type)?.second,
|
||||
typeSystem.extractUsedReifiedParameters(type)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
operator fun get(name: String): TypeParameterMapping<KT>? = mappingsByName[name]
|
||||
|
||||
fun hasReifiedParameters() = mappingsByName.values.any { it.isReified }
|
||||
|
||||
internal inline fun forEach(l: (TypeParameterMapping<KT>) -> Unit) {
|
||||
mappingsByName.values.forEach(l)
|
||||
}
|
||||
internal inline fun forEach(block: (String, TypeParameterMapping<KT>) -> Unit) =
|
||||
mappingsByName.entries.forEach { (name, mapping) -> block(name, mapping) }
|
||||
}
|
||||
|
||||
class TypeParameterMapping<KT : KotlinTypeMarker>(
|
||||
val name: String,
|
||||
val type: KT,
|
||||
val asmType: Type?,
|
||||
val asmType: Type,
|
||||
val signature: String,
|
||||
val isReified: Boolean,
|
||||
val reificationArgument: ReificationArgument?,
|
||||
val signature: String?,
|
||||
val isReified: Boolean
|
||||
val reifiedTypeParametersUsages: ReifiedTypeParametersUsages,
|
||||
)
|
||||
|
||||
class ReifiedTypeParametersUsages {
|
||||
|
||||
@@ -18,8 +18,6 @@ package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import java.util.*
|
||||
|
||||
class TypeParameter(val oldName: String, val newName: String?, val isReified: Boolean, val signature: String?)
|
||||
|
||||
//typeMapping data could be changed outside through method processing
|
||||
class TypeRemapper private constructor(
|
||||
private val typeMapping: MutableMap<String, String?>,
|
||||
@@ -27,7 +25,7 @@ class TypeRemapper private constructor(
|
||||
private val isRootInlineLambda: Boolean = false
|
||||
) {
|
||||
private val additionalMappings = hashMapOf<String, String>()
|
||||
private val typeParametersMapping = hashMapOf<String, TypeParameter>()
|
||||
private val typeParametersMapping = hashMapOf<String, TypeParameterMapping<*>?>()
|
||||
|
||||
fun addMapping(type: String, newType: String) {
|
||||
typeMapping[type] = newType
|
||||
@@ -50,26 +48,24 @@ class TypeRemapper private constructor(
|
||||
// assert(typeParametersMapping[name] == null) {
|
||||
// "Type parameter already registered $name"
|
||||
// }
|
||||
typeParametersMapping[name] = TypeParameter(name, name, false, null)
|
||||
typeParametersMapping[name] = null
|
||||
}
|
||||
|
||||
fun registerTypeParameter(mapping: TypeParameterMapping<*>) {
|
||||
typeParametersMapping[mapping.name] = TypeParameter(
|
||||
mapping.name, mapping.reificationArgument?.parameterName, mapping.isReified, mapping.signature
|
||||
)
|
||||
fun registerTypeParameter(name: String, mapping: TypeParameterMapping<*>) {
|
||||
typeParametersMapping[name] = mapping
|
||||
}
|
||||
|
||||
fun mapTypeParameter(name: String): TypeParameter? {
|
||||
return typeParametersMapping[name] ?: if (!isRootInlineLambda) parent?.mapTypeParameter(name) else null
|
||||
fun mapTypeParameter(name: String): TypeParameterMapping<*>? = when {
|
||||
name in typeParametersMapping -> typeParametersMapping[name]
|
||||
!isRootInlineLambda -> parent?.mapTypeParameter(name)
|
||||
else -> null
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun createRoot(formalTypeParameters: TypeParameterMappings<*>?): TypeRemapper {
|
||||
fun createRoot(formalTypeParameters: TypeParameterMappings<*>): TypeRemapper {
|
||||
return TypeRemapper(HashMap()).apply {
|
||||
formalTypeParameters?.forEach {
|
||||
registerTypeParameter(it)
|
||||
}
|
||||
formalTypeParameters.forEach(::registerTypeParameter)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,73 +22,62 @@ import kotlin.reflect.KVariance
|
||||
internal fun TypeSystemCommonBackendContext.createTypeOfMethodBody(typeParameter: TypeParameterMarker): MethodNode {
|
||||
val node = MethodNode(Opcodes.API_VERSION, Opcodes.ACC_STATIC, "fake", Type.getMethodDescriptor(K_TYPE), null, null)
|
||||
val v = InstructionAdapter(node)
|
||||
|
||||
putTypeOfReifiedTypeParameter(v, typeParameter, false)
|
||||
val argument = ReificationArgument(typeParameter.getName().asString(), false, 0)
|
||||
ReifiedTypeInliner.putReifiedOperationMarker(ReifiedTypeInliner.OperationKind.TYPE_OF, argument, v)
|
||||
v.aconst(null)
|
||||
v.areturn(K_TYPE)
|
||||
|
||||
v.visitMaxs(2, 0)
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
private fun TypeSystemCommonBackendContext.putTypeOfReifiedTypeParameter(
|
||||
v: InstructionAdapter, typeParameter: TypeParameterMarker, isNullable: Boolean
|
||||
) {
|
||||
ReifiedTypeInliner.putReifiedOperationMarkerIfNeeded(typeParameter, isNullable, ReifiedTypeInliner.OperationKind.TYPE_OF, v, this)
|
||||
v.aconst(null)
|
||||
private inline fun InstructionAdapter.unrollArrayIfFewerThan(n: Int, limit: Int, type: Type, element: (Int) -> Unit): Array<Type> {
|
||||
if (n < limit) {
|
||||
return Array(n) { i ->
|
||||
element(i)
|
||||
type
|
||||
}
|
||||
}
|
||||
iconst(n)
|
||||
newarray(type)
|
||||
for (i in 0 until n) {
|
||||
dup()
|
||||
iconst(i)
|
||||
element(i)
|
||||
astore(type)
|
||||
}
|
||||
return arrayOf(AsmUtil.getArrayType(type))
|
||||
}
|
||||
|
||||
fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateTypeOf(
|
||||
v: InstructionAdapter, type: KT, intrinsicsSupport: ReifiedTypeInliner.IntrinsicsSupport<KT>
|
||||
) = generateTypeOf(v, type, intrinsicsSupport, isTypeParameterBound = false)
|
||||
|
||||
private fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateTypeOf(
|
||||
v: InstructionAdapter, type: KT, intrinsicsSupport: ReifiedTypeInliner.IntrinsicsSupport<KT>, isTypeParameterBound: Boolean
|
||||
) {
|
||||
val typeParameter = type.typeConstructor().getTypeParameterClassifier()
|
||||
if (typeParameter != null) {
|
||||
if (!doesTypeContainTypeParametersWithRecursiveBounds(type)) {
|
||||
intrinsicsSupport.reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameter.getName())
|
||||
v.aconst(null)
|
||||
return
|
||||
}
|
||||
|
||||
generateNonReifiedTypeParameter(v, typeParameter, intrinsicsSupport)
|
||||
} else {
|
||||
val methodArguments = if (typeParameter == null) {
|
||||
intrinsicsSupport.putClassInstance(v, type)
|
||||
}
|
||||
|
||||
val argumentsSize = type.argumentsCount()
|
||||
val useArray = argumentsSize >= 3
|
||||
|
||||
if (useArray) {
|
||||
v.iconst(argumentsSize)
|
||||
v.newarray(K_TYPE_PROJECTION)
|
||||
}
|
||||
|
||||
for (i in 0 until argumentsSize) {
|
||||
if (useArray) {
|
||||
v.dup()
|
||||
v.iconst(i)
|
||||
}
|
||||
|
||||
doGenerateTypeProjection(v, type.getArgument(i), intrinsicsSupport)
|
||||
|
||||
if (useArray) {
|
||||
v.astore(K_TYPE_PROJECTION)
|
||||
val arguments = v.unrollArrayIfFewerThan(type.argumentsCount(), 3, K_TYPE_PROJECTION) { i ->
|
||||
generateTypeOfArgument(v, type.getArgument(i), intrinsicsSupport, isTypeParameterBound)
|
||||
}
|
||||
arrayOf(JAVA_CLASS_TYPE, *arguments)
|
||||
} else if (!isTypeParameterBound && typeParameter.isReified()) {
|
||||
val argument = ReificationArgument(typeParameter.getName().asString(), type.isMarkedNullable(), 0)
|
||||
ReifiedTypeInliner.putReifiedOperationMarker(ReifiedTypeInliner.OperationKind.TYPE_OF, argument, v)
|
||||
v.aconst(null)
|
||||
return
|
||||
} else if (typeReferencesParameterWithRecursiveBound(type)) {
|
||||
intrinsicsSupport.reportNonReifiedTypeParameterWithRecursiveBoundUnsupported(typeParameter.getName())
|
||||
v.aconst(null)
|
||||
return
|
||||
} else {
|
||||
generateNonReifiedTypeParameter(v, typeParameter, intrinsicsSupport)
|
||||
arrayOf(K_CLASSIFIER_TYPE)
|
||||
}
|
||||
|
||||
val methodName = if (type.isMarkedNullable()) "nullableTypeOf" else "typeOf"
|
||||
|
||||
val signature = if (typeParameter != null) {
|
||||
Type.getMethodDescriptor(K_TYPE, K_CLASSIFIER_TYPE)
|
||||
} else {
|
||||
val projections = when (argumentsSize) {
|
||||
0 -> emptyArray()
|
||||
1 -> arrayOf(K_TYPE_PROJECTION)
|
||||
2 -> arrayOf(K_TYPE_PROJECTION, K_TYPE_PROJECTION)
|
||||
else -> arrayOf(AsmUtil.getArrayType(K_TYPE_PROJECTION))
|
||||
}
|
||||
Type.getMethodDescriptor(K_TYPE, JAVA_CLASS_TYPE, *projections)
|
||||
}
|
||||
|
||||
val signature = Type.getMethodDescriptor(K_TYPE, *methodArguments)
|
||||
v.invokestatic(REFLECTION, methodName, signature, false)
|
||||
|
||||
if (intrinsicsSupport.toKotlinType(type).isSuspendFunctionType) {
|
||||
@@ -106,7 +95,7 @@ fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateTypeOf(
|
||||
// If this is a flexible type, we've just generated its lower bound and have it on the stack.
|
||||
// Let's generate the upper bound now and call the method that takes lower and upper bound and constructs a flexible KType.
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
generateTypeOf(v, type.upperBoundIfFlexible() as KT, intrinsicsSupport)
|
||||
generateTypeOf(v, type.upperBoundIfFlexible() as KT, intrinsicsSupport, isTypeParameterBound)
|
||||
|
||||
v.invokestatic(REFLECTION, "platformType", Type.getMethodDescriptor(K_TYPE, K_TYPE, K_TYPE), false)
|
||||
}
|
||||
@@ -132,76 +121,54 @@ private fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateNonRe
|
||||
false,
|
||||
)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val bounds = (0 until typeParameter.upperBoundCount()).map { typeParameter.getUpperBound(it) as KT }
|
||||
if (bounds.isEmpty()) return
|
||||
if (typeParameter.upperBoundCount() == 0) return
|
||||
|
||||
v.dup()
|
||||
|
||||
if (bounds.size == 1) {
|
||||
generateTypeOf(v, bounds.single(), intrinsicsSupport)
|
||||
} else {
|
||||
v.iconst(bounds.size)
|
||||
v.newarray(K_TYPE)
|
||||
for ((i, bound) in bounds.withIndex()) {
|
||||
v.dup()
|
||||
v.iconst(i)
|
||||
generateTypeOf(v, bound, intrinsicsSupport)
|
||||
v.astore(K_TYPE)
|
||||
}
|
||||
val argumentsForBounds = v.unrollArrayIfFewerThan(typeParameter.upperBoundCount(), 2, K_TYPE) { i ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
generateTypeOf(v, typeParameter.getUpperBound(i) as KT, intrinsicsSupport, isTypeParameterBound = true)
|
||||
}
|
||||
|
||||
v.invokestatic(
|
||||
REFLECTION, "setUpperBounds", Type.getMethodDescriptor(
|
||||
Type.VOID_TYPE, K_TYPE_PARAMETER,
|
||||
if (bounds.size == 1) K_TYPE else AsmUtil.getArrayType(K_TYPE)
|
||||
),
|
||||
REFLECTION, "setUpperBounds", Type.getMethodDescriptor(Type.VOID_TYPE, K_TYPE_PARAMETER, *argumentsForBounds),
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
private fun TypeSystemCommonBackendContext.doesTypeContainTypeParametersWithRecursiveBounds(
|
||||
private fun TypeSystemCommonBackendContext.typeReferencesParameterWithRecursiveBound(
|
||||
type: KotlinTypeMarker,
|
||||
used: MutableSet<TypeParameterMarker> = linkedSetOf()
|
||||
): Boolean {
|
||||
val typeParameter = type.typeConstructor().getTypeParameterClassifier()
|
||||
if (typeParameter != null) {
|
||||
if (!used.add(typeParameter)) return false
|
||||
if (!used.add(typeParameter)) return true
|
||||
for (i in 0 until typeParameter.upperBoundCount()) {
|
||||
if (!doesTypeContainTypeParametersWithRecursiveBounds(typeParameter.getUpperBound(i), used)) return false
|
||||
if (typeReferencesParameterWithRecursiveBound(typeParameter.getUpperBound(i), used)) return true
|
||||
}
|
||||
used.remove(typeParameter)
|
||||
} else {
|
||||
for (i in 0 until type.argumentsCount()) {
|
||||
val argument = type.getArgument(i)
|
||||
if (!argument.isStarProjection() && !doesTypeContainTypeParametersWithRecursiveBounds(argument.getType(), used)) return false
|
||||
if (!argument.isStarProjection() && typeReferencesParameterWithRecursiveBound(argument.getType(), used)) return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
private fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.doGenerateTypeProjection(
|
||||
private fun <KT : KotlinTypeMarker> TypeSystemCommonBackendContext.generateTypeOfArgument(
|
||||
v: InstructionAdapter,
|
||||
projection: TypeArgumentMarker,
|
||||
intrinsicsSupport: ReifiedTypeInliner.IntrinsicsSupport<KT>
|
||||
intrinsicsSupport: ReifiedTypeInliner.IntrinsicsSupport<KT>,
|
||||
isTypeParameterBound: Boolean,
|
||||
) {
|
||||
// KTypeProjection members could be static, see KT-30083 and KT-30084
|
||||
// KTypeProjection companion members could be made `@JvmStatic`, see KT-30083 and KT-30084
|
||||
v.getstatic(K_TYPE_PROJECTION.internalName, "Companion", K_TYPE_PROJECTION_COMPANION.descriptor)
|
||||
|
||||
if (projection.isStarProjection()) {
|
||||
v.invokevirtual(K_TYPE_PROJECTION_COMPANION.internalName, "getSTAR", Type.getMethodDescriptor(K_TYPE_PROJECTION), false)
|
||||
return
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val type = projection.getType() as KT
|
||||
val typeParameterClassifier = type.typeConstructor().getTypeParameterClassifier()
|
||||
if (typeParameterClassifier != null && typeParameterClassifier.isReified()) {
|
||||
putTypeOfReifiedTypeParameter(v, typeParameterClassifier, type.isMarkedNullable())
|
||||
} else {
|
||||
generateTypeOf(v, type, intrinsicsSupport)
|
||||
}
|
||||
|
||||
generateTypeOf(v, projection.getType() as KT, intrinsicsSupport, isTypeParameterBound)
|
||||
val methodName = when (projection.getVariance()) {
|
||||
TypeVariance.INV -> "invariant"
|
||||
TypeVariance.IN -> "contravariant"
|
||||
|
||||
+18
@@ -44586,6 +44586,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/annotatedType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOfNullableReified.kt")
|
||||
public void testArrayOfNullableReified() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/arrayOfNullableReified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("caching.kt")
|
||||
public void testCaching() throws Exception {
|
||||
@@ -44676,6 +44682,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/rawTypes_before.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reifiedAsNestedArgument.kt")
|
||||
public void testReifiedAsNestedArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/reifiedAsNestedArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeOfCapturedStar.kt")
|
||||
public void testTypeOfCapturedStar() throws Exception {
|
||||
@@ -45989,6 +46001,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/reified/spreads.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeTokenWrapper.kt")
|
||||
public void testTypeTokenWrapper() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/typeTokenWrapper.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("varargs.kt")
|
||||
public void testVarargs() throws Exception {
|
||||
|
||||
+3
-22
@@ -57,7 +57,6 @@ import org.jetbrains.kotlin.types.computeExpandedTypeForInlineClass
|
||||
import org.jetbrains.kotlin.types.model.TypeParameterMarker
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -1455,30 +1454,12 @@ class ExpressionCodegen(
|
||||
if (element.typeArgumentsCount == 0) {
|
||||
//avoid ambiguity with type constructor type parameters
|
||||
emptyMap()
|
||||
} else typeArgumentContainer.typeParameters.keysToMap {
|
||||
element.getTypeArgumentOrDefault(it)
|
||||
} else typeArgumentContainer.typeParameters.associate {
|
||||
it.symbol to element.getTypeArgumentOrDefault(it)
|
||||
}
|
||||
|
||||
val mappings = TypeParameterMappings<IrType>()
|
||||
for ((key, type) in typeArguments.entries) {
|
||||
val reificationArgument = typeMapper.typeSystem.extractReificationArgument(type)
|
||||
if (reificationArgument == null) {
|
||||
// type is not generic
|
||||
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
|
||||
val asmType = typeMapper.mapTypeParameter(type, signatureWriter)
|
||||
|
||||
mappings.addParameterMappingToType(
|
||||
key.name.identifier, type, asmType, signatureWriter.toString(), key.isReified
|
||||
)
|
||||
} else {
|
||||
mappings.addParameterMappingForFurtherReification(
|
||||
key.name.identifier, type, reificationArgument.second, key.isReified
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val mappings = TypeParameterMappings(typeMapper.typeSystem, typeArguments, allReified = false, typeMapper::mapTypeParameter)
|
||||
val sourceCompiler = IrSourceCompilerForInline(state, element, callee, this, data)
|
||||
|
||||
val reifiedTypeInliner = ReifiedTypeInliner(
|
||||
mappings,
|
||||
IrInlineIntrinsicsSupport(classCodegen, element, irFunction.fileParent),
|
||||
|
||||
+4
-6
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.IrInlineIntrinsicsSupport
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.fileParent
|
||||
import org.jetbrains.kotlin.codegen.extractUsedReifiedParameters
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
|
||||
import org.jetbrains.kotlin.codegen.inline.generateTypeOf
|
||||
import org.jetbrains.kotlin.codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter
|
||||
@@ -17,12 +18,9 @@ import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
object TypeOf : IntrinsicMethod() {
|
||||
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo) = with(codegen) {
|
||||
val type = expression.getTypeArgument(0)!!
|
||||
if (putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.TYPE_OF)) {
|
||||
mv.aconst(null) // see ReifiedTypeInliner.processTypeOf
|
||||
} else {
|
||||
val support = IrInlineIntrinsicsSupport(codegen.classCodegen, expression, codegen.irFunction.fileParent)
|
||||
typeMapper.typeSystem.generateTypeOf(mv, type, support)
|
||||
}
|
||||
val support = IrInlineIntrinsicsSupport(codegen.classCodegen, expression, codegen.irFunction.fileParent)
|
||||
typeMapper.typeSystem.generateTypeOf(mv, type, support)
|
||||
codegen.propagateChildReifiedTypeParametersUsages(codegen.typeMapper.typeSystem.extractUsedReifiedParameters(type))
|
||||
expression.onStack
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS_IR_ES6
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.typeOf
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
inline fun <reified T> typeOfArrayOfNArrayOf() =
|
||||
typeOf<Array<Array<T>?>>()
|
||||
|
||||
inline fun <reified T> myTypeOf() =
|
||||
typeOf<T>()
|
||||
|
||||
inline fun <reified T> myTypeOfArrayOfNArrayOf() =
|
||||
typeOf<Array<Array<T>?>>()
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(typeOf<Array<Array<String>?>>(), typeOfArrayOfNArrayOf<String>())
|
||||
assertEquals(typeOf<Array<Array<String>?>>(), myTypeOf<Array<Array<String>?>>())
|
||||
assertEquals(typeOf<Array<Array<String>?>>(), myTypeOfArrayOfNArrayOf<String>())
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.typeOf
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
inline fun <reified T> foo() =
|
||||
object { val x = typeOf<T>() }.x
|
||||
|
||||
inline fun <reified T> bar(expected: KType) {
|
||||
assertEquals(expected, foo<List<T>>())
|
||||
assertEquals(expected, object { val x = typeOf<List<T>>() }.x)
|
||||
assertEquals(expected, typeOf<List<T>>())
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
bar<Int>(typeOf<List<Int>>())
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// ISSUE: KT-53761
|
||||
// WITH_STDLIB
|
||||
// IGNORE_BACKEND: ANDROID
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
open class TypeToken<T> {
|
||||
val type = javaClass.genericSuperclass
|
||||
}
|
||||
|
||||
inline fun <reified E> myTypeOf() =
|
||||
object : TypeToken<E>() {}.type
|
||||
|
||||
inline fun <reified T> myTypeOfArrayOf() =
|
||||
object : TypeToken<Array<T>>() {}.type
|
||||
|
||||
inline fun <reified T> myTypeOfArrayOf2() =
|
||||
myTypeOf<Array<T>>()
|
||||
|
||||
inline fun <reified T> myTypeOfListOf() =
|
||||
object : TypeToken<List<T>>() {}.type
|
||||
|
||||
inline fun <reified T> myTypeOfListOf2() =
|
||||
myTypeOf<List<T>>()
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(myTypeOf<Array<String>>(), myTypeOfArrayOf<String>())
|
||||
assertEquals(myTypeOf<Array<String>>(), myTypeOfArrayOf2<String>())
|
||||
assertEquals(myTypeOf<List<String>>(), myTypeOfListOf<String>())
|
||||
assertEquals(myTypeOf<List<String>>(), myTypeOfListOf2<String>())
|
||||
return "OK"
|
||||
}
|
||||
+18
@@ -43104,6 +43104,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/annotatedType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOfNullableReified.kt")
|
||||
public void testArrayOfNullableReified() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/arrayOfNullableReified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classes.kt")
|
||||
public void testClasses() throws Exception {
|
||||
@@ -43188,6 +43194,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/rawTypes_before.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reifiedAsNestedArgument.kt")
|
||||
public void testReifiedAsNestedArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/reifiedAsNestedArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeOfCapturedStar.kt")
|
||||
public void testTypeOfCapturedStar() throws Exception {
|
||||
@@ -44501,6 +44513,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/reified/spreads.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeTokenWrapper.kt")
|
||||
public void testTypeTokenWrapper() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/typeTokenWrapper.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("varargs.kt")
|
||||
public void testVarargs() throws Exception {
|
||||
|
||||
+18
@@ -44586,6 +44586,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/annotatedType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOfNullableReified.kt")
|
||||
public void testArrayOfNullableReified() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/arrayOfNullableReified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("caching.kt")
|
||||
public void testCaching() throws Exception {
|
||||
@@ -44676,6 +44682,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/rawTypes_before.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reifiedAsNestedArgument.kt")
|
||||
public void testReifiedAsNestedArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/reifiedAsNestedArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeOfCapturedStar.kt")
|
||||
public void testTypeOfCapturedStar() throws Exception {
|
||||
@@ -45989,6 +46001,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reified/spreads.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeTokenWrapper.kt")
|
||||
public void testTypeTokenWrapper() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/typeTokenWrapper.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("varargs.kt")
|
||||
public void testVarargs() throws Exception {
|
||||
|
||||
+15
@@ -34660,6 +34660,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/annotatedType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayOfNullableReified.kt")
|
||||
public void testArrayOfNullableReified() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/arrayOfNullableReified.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classes.kt")
|
||||
public void testClasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/classes.kt");
|
||||
@@ -34730,6 +34735,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/rawTypes_before.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedAsNestedArgument.kt")
|
||||
public void testReifiedAsNestedArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/reifiedAsNestedArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeOfCapturedStar.kt")
|
||||
public void testTypeOfCapturedStar() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/typeOfCapturedStar.kt");
|
||||
@@ -35871,6 +35881,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/reified/spreads.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeTokenWrapper.kt")
|
||||
public void testTypeTokenWrapper() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/typeTokenWrapper.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("varargs.kt")
|
||||
public void testVarargs() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reified/varargs.kt");
|
||||
|
||||
+12
@@ -32486,6 +32486,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/typeOf"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOfNullableReified.kt")
|
||||
public void testArrayOfNullableReified() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/arrayOfNullableReified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classes.kt")
|
||||
public void testClasses() throws Exception {
|
||||
@@ -32516,6 +32522,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reifiedAsNestedArgument.kt")
|
||||
public void testReifiedAsNestedArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/reifiedAsNestedArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeOfCapturedStar.kt")
|
||||
public void testTypeOfCapturedStar() throws Exception {
|
||||
|
||||
+12
@@ -32666,6 +32666,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/typeOf"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOfNullableReified.kt")
|
||||
public void testArrayOfNullableReified() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/arrayOfNullableReified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classes.kt")
|
||||
public void testClasses() throws Exception {
|
||||
@@ -32696,6 +32702,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reifiedAsNestedArgument.kt")
|
||||
public void testReifiedAsNestedArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/reifiedAsNestedArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeOfCapturedStar.kt")
|
||||
public void testTypeOfCapturedStar() throws Exception {
|
||||
|
||||
+10
@@ -29295,6 +29295,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/typeOf"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("arrayOfNullableReified.kt")
|
||||
public void testArrayOfNullableReified() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/arrayOfNullableReified.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classes.kt")
|
||||
public void testClasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/classes.kt");
|
||||
@@ -29320,6 +29325,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedAsNestedArgument.kt")
|
||||
public void testReifiedAsNestedArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/reifiedAsNestedArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeOfCapturedStar.kt")
|
||||
public void testTypeOfCapturedStar() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/typeOfCapturedStar.kt");
|
||||
|
||||
+12
@@ -35743,6 +35743,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/typeOf"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayOfNullableReified.kt")
|
||||
public void testArrayOfNullableReified() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/arrayOfNullableReified.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classes.kt")
|
||||
public void testClasses() throws Exception {
|
||||
@@ -35773,6 +35779,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("reifiedAsNestedArgument.kt")
|
||||
public void testReifiedAsNestedArgument() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/reifiedAsNestedArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeOfCapturedStar.kt")
|
||||
public void testTypeOfCapturedStar() throws Exception {
|
||||
|
||||
+2
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.intrinsics.IntrinsicMethod
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.representativeUpperBound
|
||||
import org.jetbrains.kotlin.backend.jvm.mapping.mapClass
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.extractUsedReifiedParameters
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.pluginIntrinsicsMarkerMethod
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.pluginIntrinsicsMarkerOwner
|
||||
@@ -92,6 +93,7 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
||||
mv,
|
||||
intrinsicType
|
||||
)
|
||||
codegen.propagateChildReifiedTypeParametersUsages(codegen.typeMapper.typeSystem.extractUsedReifiedParameters(argument))
|
||||
if (withModule) {
|
||||
frameMap.leaveTemp(serializersModuleType)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user