Type parameters mapping
#KT-10429 Fixed
This commit is contained in:
@@ -2429,7 +2429,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected CallGenerator getOrCreateCallGenerator(
|
private CallGenerator getOrCreateCallGenerator(
|
||||||
@NotNull CallableDescriptor descriptor,
|
@NotNull CallableDescriptor descriptor,
|
||||||
@Nullable KtElement callElement,
|
@Nullable KtElement callElement,
|
||||||
@Nullable TypeParameterMappings typeParameterMappings
|
@Nullable TypeParameterMappings typeParameterMappings
|
||||||
@@ -2448,7 +2448,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public CallGenerator getOrCreateCallGenerator(@NotNull FunctionDescriptor descriptor, @Nullable KtNamedFunction function) {
|
protected CallGenerator getOrCreateCallGeneratorForDefaultImplBody(@NotNull FunctionDescriptor descriptor, @Nullable KtNamedFunction function) {
|
||||||
return getOrCreateCallGenerator(descriptor, function, null);
|
return getOrCreateCallGenerator(descriptor, function, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import com.intellij.psi.PsiElement;
|
|||||||
import com.intellij.util.ArrayUtil;
|
import com.intellij.util.ArrayUtil;
|
||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import kotlin.Unit;
|
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -29,7 +28,6 @@ import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
|||||||
import org.jetbrains.kotlin.backend.common.bridges.ImplKt;
|
import org.jetbrains.kotlin.backend.common.bridges.ImplKt;
|
||||||
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithOnlyTargetedAnnotations;
|
import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithOnlyTargetedAnnotations;
|
||||||
import org.jetbrains.kotlin.codegen.context.*;
|
import org.jetbrains.kotlin.codegen.context.*;
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics;
|
|
||||||
import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor;
|
import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||||
@@ -699,7 +697,7 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, signature.getReturnType(), methodContext, state, parentCodegen);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, signature.getReturnType(), methodContext, state, parentCodegen);
|
||||||
|
|
||||||
CallGenerator generator = codegen.getOrCreateCallGenerator(functionDescriptor, function);
|
CallGenerator generator = codegen.getOrCreateCallGeneratorForDefaultImplBody(functionDescriptor, function);
|
||||||
|
|
||||||
loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator);
|
loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -347,7 +347,7 @@ public class AnonymousObjectTransformer {
|
|||||||
|
|
||||||
return new RemappingClassBuilder(
|
return new RemappingClassBuilder(
|
||||||
classBuilder,
|
classBuilder,
|
||||||
new AsmTypeRemapper(inliningContext.typeRemapper, inliningContext.getRoot().typeParameterMappings, transformationResult)
|
new AsmTypeRemapper(inliningContext.typeRemapper, inliningContext.getRoot().typeParameterMappings == null, transformationResult)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,24 +21,22 @@ import org.jetbrains.org.objectweb.asm.commons.RemappingSignatureAdapter
|
|||||||
import org.jetbrains.org.objectweb.asm.signature.SignatureReader
|
import org.jetbrains.org.objectweb.asm.signature.SignatureReader
|
||||||
import org.jetbrains.org.objectweb.asm.signature.SignatureVisitor
|
import org.jetbrains.org.objectweb.asm.signature.SignatureVisitor
|
||||||
|
|
||||||
class AsmTypeRemapper(val typeRemapper: TypeRemapper, val mappings: TypeParameterMappings?, val result: InlineResult) : Remapper() {
|
class AsmTypeRemapper(val typeRemapper: TypeRemapper, val isDefaultGeneration: Boolean, val result: InlineResult) : Remapper() {
|
||||||
|
|
||||||
override fun map(type: String): String {
|
override fun map(type: String): String {
|
||||||
return typeRemapper.map(type)
|
return typeRemapper.map(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun createRemappingSignatureAdapter(v: SignatureVisitor?): SignatureVisitor {
|
override fun createRemappingSignatureAdapter(v: SignatureVisitor?): SignatureVisitor {
|
||||||
if (mappings == null) {
|
if (isDefaultGeneration) {
|
||||||
//don't remap default generation
|
|
||||||
return super.createRemappingSignatureAdapter(v);
|
return super.createRemappingSignatureAdapter(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
return object : RemappingSignatureAdapter(v, this) {
|
return object : RemappingSignatureAdapter(v, this) {
|
||||||
|
|
||||||
override fun visitTypeVariable(name: String) {
|
override fun visitTypeVariable(name: String) {
|
||||||
val mapping = getMappingByName(name) ?:
|
/*TODO try to erase absent type variable*/
|
||||||
return super.visitTypeVariable(name)
|
val mapping = typeRemapper.mapTypeParameter(name) ?: return super.visitTypeVariable(name)
|
||||||
|
|
||||||
if (mapping.newName != null) {
|
if (mapping.newName != null) {
|
||||||
if (mapping.isReified) {
|
if (mapping.isReified) {
|
||||||
@@ -51,19 +49,9 @@ class AsmTypeRemapper(val typeRemapper: TypeRemapper, val mappings: TypeParamete
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFormalTypeParameter(name: String) {
|
override fun visitFormalTypeParameter(name: String) {
|
||||||
val mapping: TypeParameterMapping = getMappingByName(name) ?:
|
typeRemapper.registerTypeParameter(name)
|
||||||
return super.visitFormalTypeParameter(name)
|
super.visitFormalTypeParameter(name)
|
||||||
if (mapping.newName != null ) {
|
|
||||||
if (mapping.isReified) {
|
|
||||||
result.reifiedTypeParametersUsages.addUsedReifiedParameter(mapping.newName)
|
|
||||||
}
|
|
||||||
super.visitFormalTypeParameter(mapping.newName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMappingByName(name: String): TypeParameterMapping? = mappings[name]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ public class InliningContext {
|
|||||||
@NotNull AnonymousObjectGeneration anonymousObjectGeneration
|
@NotNull AnonymousObjectGeneration anonymousObjectGeneration
|
||||||
) {
|
) {
|
||||||
return new RegeneratedClassContext(this, expressionMap, state, generator,
|
return new RegeneratedClassContext(this, expressionMap, state, generator,
|
||||||
new TypeRemapper(typeRemapper, newTypeMappings),
|
TypeRemapper.createFrom(typeRemapper, newTypeMappings),
|
||||||
reifedTypeInliner, isInliningLambda, anonymousObjectGeneration);
|
reifedTypeInliner, isInliningLambda, anonymousObjectGeneration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ public class InliningContext {
|
|||||||
boolean isRegeneration
|
boolean isRegeneration
|
||||||
) {
|
) {
|
||||||
return new InliningContext(this, expressionMap, state, generator,
|
return new InliningContext(this, expressionMap, state, generator,
|
||||||
new TypeRemapper(typeRemapper, additionalTypeMappings), reifedTypeInliner, isInliningLambda, isRegeneration);
|
TypeRemapper.createFrom(typeRemapper, additionalTypeMappings), reifedTypeInliner, isInliningLambda, isRegeneration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRoot() {
|
public boolean isRoot() {
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ public class MethodInliner {
|
|||||||
resultNode.access,
|
resultNode.access,
|
||||||
resultNode.desc,
|
resultNode.desc,
|
||||||
resultNode,
|
resultNode,
|
||||||
new AsmTypeRemapper(remapper, inliningContext.getRoot().typeParameterMappings, result)
|
new AsmTypeRemapper(remapper, inliningContext.getRoot().typeParameterMappings == null, result)
|
||||||
);
|
);
|
||||||
|
|
||||||
final int markerShift = InlineCodegenUtil.calcMarkerShift(parameters, node);
|
final int markerShift = InlineCodegenUtil.calcMarkerShift(parameters, node);
|
||||||
|
|||||||
@@ -232,6 +232,10 @@ class TypeParameterMappings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun hasReifiedParameters() = mappingsByName.values.any { it.isReified }
|
fun hasReifiedParameters() = mappingsByName.values.any { it.isReified }
|
||||||
|
|
||||||
|
internal inline fun forEach(l: (TypeParameterMapping) -> Unit) {
|
||||||
|
mappingsByName.values.forEach(l)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TypeParameterMapping(
|
class TypeParameterMapping(
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class RootInliningContext extends InliningContext {
|
|||||||
@NotNull ReifiedTypeInliner inliner,
|
@NotNull ReifiedTypeInliner inliner,
|
||||||
@Nullable TypeParameterMappings typeParameterMappings
|
@Nullable TypeParameterMappings typeParameterMappings
|
||||||
) {
|
) {
|
||||||
super(null, map, state, nameGenerator, TypeRemapper.createEmpty(), inliner, false, false);
|
super(null, map, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), inliner, false, false);
|
||||||
this.callElement = callElement;
|
this.callElement = callElement;
|
||||||
this.startContext = startContext;
|
this.startContext = startContext;
|
||||||
this.classNameToInline = classNameToInline;
|
this.classNameToInline = classNameToInline;
|
||||||
|
|||||||
@@ -14,69 +14,76 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.inline;
|
package org.jetbrains.kotlin.codegen.inline
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import java.util.HashMap
|
||||||
|
|
||||||
import java.util.HashMap;
|
class TypeParameter(val oldName: String, val newName: String?, val isReified: Boolean, val signature: String?)
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class TypeRemapper {
|
//typeMapping data could be changed outside through method processing
|
||||||
//typeMapping field could be changed outside through method processing
|
class TypeRemapper private constructor(private val typeMapping: MutableMap<String, String>, val parent: TypeRemapper?) {
|
||||||
private final Map<String, String> typeMapping;
|
|
||||||
|
|
||||||
private Map<String, String> additionalMappings;
|
private var additionalMappings: MutableMap<String, String> = hashMapOf()
|
||||||
|
|
||||||
//typeMapping field could be changed outside through method processing
|
|
||||||
private TypeRemapper(@NotNull Map<String, String> typeMapping) {
|
private val typeParametersMapping: MutableMap<String, TypeParameter> = hashMapOf()
|
||||||
this.typeMapping = typeMapping;
|
|
||||||
|
fun addMapping(type: String, newType: String) {
|
||||||
|
typeMapping.put(type, newType)
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeRemapper(@NotNull TypeRemapper remapper, @NotNull Map<String, String> newTypeMappings) {
|
fun hasNoAdditionalMapping(type: String): Boolean {
|
||||||
this(createNewAndMerge(remapper, newTypeMappings));
|
return typeMapping.containsKey(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeRemapper createEmpty() {
|
fun map(type: String): String {
|
||||||
return new TypeRemapper(new HashMap<String, String>());
|
return typeMapping[type] ?: additionalMappings?.get(type) ?: type
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeRemapper createFrom(Map<String, String> mappings) {
|
fun addAdditionalMappings(oldName: String, newName: String) {
|
||||||
return new TypeRemapper(mappings);
|
additionalMappings!!.put(oldName, newName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
fun registerTypeParameter(name: String) {
|
||||||
private static Map<String, String> createNewAndMerge(@NotNull TypeRemapper remapper, @NotNull Map<String, String> additionalTypeMappings) {
|
assert(typeParametersMapping[name] == null) {
|
||||||
Map<String, String> map = new HashMap<String, String>(remapper.typeMapping);
|
"Type parameter already registered $name"
|
||||||
map.putAll(additionalTypeMappings);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addMapping(String type, String newType) {
|
|
||||||
typeMapping.put(type, newType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasNoAdditionalMapping(String type) {
|
|
||||||
return typeMapping.containsKey(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String map(String type) {
|
|
||||||
String newType = typeMapping.get(type);
|
|
||||||
if (newType != null) {
|
|
||||||
return newType;
|
|
||||||
}
|
}
|
||||||
|
typeParametersMapping[name] = TypeParameter(name, name, false, null)
|
||||||
|
}
|
||||||
|
|
||||||
if (additionalMappings != null) {
|
fun registerTypeParameter(mapping: TypeParameterMapping) {
|
||||||
newType = additionalMappings.get(type);
|
typeParametersMapping[mapping.name] = TypeParameter(mapping.name, mapping.newName, mapping.isReified, mapping.signature)
|
||||||
if (newType != null) {
|
}
|
||||||
return newType;
|
|
||||||
|
fun mapTypeParameter(name: String): TypeParameter? {
|
||||||
|
return typeParametersMapping[name] ?: parent?.mapTypeParameter(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun createRoot(formalTypeParameters: TypeParameterMappings?): TypeRemapper {
|
||||||
|
val typeRemapper = TypeRemapper(HashMap<String, String>(), null)
|
||||||
|
formalTypeParameters?.forEach {
|
||||||
|
typeRemapper.registerTypeParameter(it)
|
||||||
}
|
}
|
||||||
|
return typeRemapper
|
||||||
}
|
}
|
||||||
|
|
||||||
return type;
|
@JvmStatic
|
||||||
}
|
fun createFrom(mappings: MutableMap<String, String>): TypeRemapper {
|
||||||
|
return TypeRemapper(mappings, null)
|
||||||
|
}
|
||||||
|
|
||||||
public void addAdditionalMappings(String oldName, String newName) {
|
@JvmStatic
|
||||||
if (additionalMappings == null) additionalMappings = new HashMap<String, String>();
|
fun createFrom(remapper: TypeRemapper, mappings: MutableMap<String, String>): TypeRemapper {
|
||||||
additionalMappings.put(oldName, newName);
|
return TypeRemapper(createNewAndMerge(remapper, mappings), remapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNewAndMerge(remapper: TypeRemapper, additionalTypeMappings: Map<String, String>): MutableMap<String, String> {
|
||||||
|
val map = HashMap(remapper.typeMapping)
|
||||||
|
map += additionalTypeMappings
|
||||||
|
return map
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// NO_CHECK_LAMBDA_INLINING
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val result = Test().callInline()
|
||||||
|
val method = result.javaClass.getMethod("aTest", Any::class.java)
|
||||||
|
val genericReturnType = method.genericReturnType
|
||||||
|
if (genericReturnType.toString() != "test.B<T>") return "fail 1: ${genericReturnType}"
|
||||||
|
|
||||||
|
val genericParameterTypes = method.genericParameterTypes
|
||||||
|
if (genericParameterTypes.size != 1) return "fail 2: ${genericParameterTypes.size}"
|
||||||
|
if (genericParameterTypes[0].toString() != "T") return "fail 3: ${genericParameterTypes[0]}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class B<T>
|
||||||
|
|
||||||
|
interface A {
|
||||||
|
fun <T> aTest(p: T): B<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Test {
|
||||||
|
|
||||||
|
inline fun <T> test(crossinline z: () -> Int) = object : A {
|
||||||
|
override fun <T> aTest(p: T): B<T> {
|
||||||
|
z()
|
||||||
|
return B<T>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun callInline() = test<String> { 1 }
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// NO_CHECK_LAMBDA_INLINING
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val result = Test().callInline()
|
||||||
|
val method = result.javaClass.getMethod("aTest", Any::class.java)
|
||||||
|
val genericReturnType = method.genericReturnType
|
||||||
|
if (genericReturnType.toString() != "test.B<T>") return "fail 1: ${genericReturnType}"
|
||||||
|
|
||||||
|
val genericParameterTypes = method.genericParameterTypes
|
||||||
|
if (genericParameterTypes.size != 1) return "fail 2: ${genericParameterTypes.size}"
|
||||||
|
if (genericParameterTypes[0].toString() != "T") return "fail 3: ${genericParameterTypes[0]}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class B<T>
|
||||||
|
|
||||||
|
interface A {
|
||||||
|
fun <T> aTest(p: T): B<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
open class Test {
|
||||||
|
|
||||||
|
inline fun <reified T> test(crossinline z: () -> Int) = object : A {
|
||||||
|
override fun <T> aTest(p: T): B<T> {
|
||||||
|
z()
|
||||||
|
return B<T>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun callInline() = test<String> { 1 }
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
//NO_CHECK_LAMBDA_INLINING
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
|
||||||
|
val comparable = CustomerService().comparator<String>()
|
||||||
|
val method = comparable.javaClass.getMethod("compare", Any::class.java, Any::class.java)
|
||||||
|
val genericParameterTypes = method.genericParameterTypes
|
||||||
|
if (genericParameterTypes.size != 2) return "fail 1: ${genericParameterTypes.size}"
|
||||||
|
if (genericParameterTypes[0].toString() != "T") return "fail 2: ${genericParameterTypes[0]}"
|
||||||
|
if (genericParameterTypes[1].toString() != "T") return "fail 3: ${genericParameterTypes[1]}"
|
||||||
|
|
||||||
|
|
||||||
|
val comparable2 = CustomerService().callInline()
|
||||||
|
val method2 = comparable2.javaClass.getMethod("compare", Any::class.java, Any::class.java)
|
||||||
|
val genericParameterTypes2 = method2.genericParameterTypes
|
||||||
|
if (genericParameterTypes2.size != 2) return "fail 4: ${genericParameterTypes2.size}"
|
||||||
|
var name = (genericParameterTypes2[0] as Class<*>).name
|
||||||
|
if (name != "java.lang.String") return "fail 5: ${name}"
|
||||||
|
name = (genericParameterTypes2[1] as Class<*>).name
|
||||||
|
if (name != "java.lang.String") return "fail 6: ${name}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
open class CustomerService {
|
||||||
|
|
||||||
|
fun <T> comparator() = object : Comparator<T> {
|
||||||
|
override fun compare(o1: T, o2: T): Int {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T> comparator(crossinline z: () -> Int) = object : Comparator<T> {
|
||||||
|
|
||||||
|
override fun compare(o1: T, o2: T): Int {
|
||||||
|
return z()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun callInline() = comparator<String> { 1 }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
//NO_CHECK_LAMBDA_INLINING
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
|
||||||
|
val comparable = CustomerService().comparator<String>()
|
||||||
|
val method = comparable.javaClass.getMethod("compare", Any::class.java, Any::class.java)
|
||||||
|
val genericParameterTypes = method.genericParameterTypes
|
||||||
|
if (genericParameterTypes.size != 2) return "fail 1: ${genericParameterTypes.size}"
|
||||||
|
if (genericParameterTypes[0].toString() != "T") return "fail 2: ${genericParameterTypes[0]}"
|
||||||
|
if (genericParameterTypes[1].toString() != "T") return "fail 3: ${genericParameterTypes[1]}"
|
||||||
|
|
||||||
|
|
||||||
|
val comparable2 = CustomerService().callInline()
|
||||||
|
val method2 = comparable2.javaClass.getMethod("compare", Any::class.java, Any::class.java)
|
||||||
|
val genericParameterTypes2 = method2.genericParameterTypes
|
||||||
|
if (genericParameterTypes2.size != 2) return "fail 1: ${genericParameterTypes2.size}"
|
||||||
|
|
||||||
|
var name = (genericParameterTypes2[0] as Class<*>).name
|
||||||
|
if (name != "java.lang.String") return "fail 5: ${name}"
|
||||||
|
name = (genericParameterTypes2[1] as Class<*>).name
|
||||||
|
if (name != "java.lang.String") return "fail 6: ${name}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
interface MComparator<T> {
|
||||||
|
fun compare(o1: T, o2: T): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
open class CustomerService {
|
||||||
|
|
||||||
|
fun <T> comparator() = object : MComparator<T> {
|
||||||
|
override fun compare(o1: T, o2: T): Int {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T> comparator(crossinline z: () -> Int) = object : MComparator<T> {
|
||||||
|
|
||||||
|
override fun compare(o1: T, o2: T): Int {
|
||||||
|
return z()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun callInline() = comparator<String> { 1 }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
+33
@@ -1382,6 +1382,39 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/boxInline/signature")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Signature extends AbstractBlackBoxInlineCodegenTest {
|
||||||
|
public void testAllFilesPresentInSignature() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/signature"), Pattern.compile("^(.+)\\.1.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sameFormalParameterName.1.kt")
|
||||||
|
public void testSameFormalParameterName() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/signature/sameFormalParameterName.1.kt");
|
||||||
|
doTestMultiFileWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sameReifiedFormalParameterName.1.kt")
|
||||||
|
public void testSameReifiedFormalParameterName() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/signature/sameReifiedFormalParameterName.1.kt");
|
||||||
|
doTestMultiFileWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParametersSubstitution.1.kt")
|
||||||
|
public void testTypeParametersSubstitution() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/signature/typeParametersSubstitution.1.kt");
|
||||||
|
doTestMultiFileWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParametersSubstitution2.1.kt")
|
||||||
|
public void testTypeParametersSubstitution2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/signature/typeParametersSubstitution2.1.kt");
|
||||||
|
doTestMultiFileWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/simple")
|
@TestMetadata("compiler/testData/codegen/boxInline/simple")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+33
@@ -1382,6 +1382,39 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/boxInline/signature")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Signature extends AbstractCompileKotlinAgainstInlineKotlinTest {
|
||||||
|
public void testAllFilesPresentInSignature() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/signature"), Pattern.compile("^(.+)\\.1.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sameFormalParameterName.1.kt")
|
||||||
|
public void testSameFormalParameterName() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/signature/sameFormalParameterName.1.kt");
|
||||||
|
doBoxTestWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sameReifiedFormalParameterName.1.kt")
|
||||||
|
public void testSameReifiedFormalParameterName() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/signature/sameReifiedFormalParameterName.1.kt");
|
||||||
|
doBoxTestWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParametersSubstitution.1.kt")
|
||||||
|
public void testTypeParametersSubstitution() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/signature/typeParametersSubstitution.1.kt");
|
||||||
|
doBoxTestWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("typeParametersSubstitution2.1.kt")
|
||||||
|
public void testTypeParametersSubstitution2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/signature/typeParametersSubstitution2.1.kt");
|
||||||
|
doBoxTestWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/simple")
|
@TestMetadata("compiler/testData/codegen/boxInline/simple")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user