Supported nested reified parameter declarations

Also switched to using type names as identifiers instead of their
indices
This commit is contained in:
Denis Zharkov
2014-11-21 12:07:08 +04:00
parent 080610c208
commit 3b2d0b88f3
15 changed files with 310 additions and 100 deletions
@@ -207,28 +207,24 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
);
literalCodegen.generate();
if (containsReifiedParametersInSupertypes(classDescriptor)) {
literalCodegen.setWereReifierMarkers(true);
}
addReifiedParametersFromSignature(literalCodegen, classDescriptor);
propagateChildReifiedTypeParametersUsages(literalCodegen.getReifiedTypeParametersUsages());
if (literalCodegen.wereReifierMarkers()) {
getParentCodegen().setWereReifierMarkers(true);
}
return new ObjectLiteralResult(literalCodegen.wereReifierMarkers(), classDescriptor);
return new ObjectLiteralResult(
literalCodegen.getReifiedTypeParametersUsages().wereUsedReifiedParameters(),
classDescriptor
);
}
private static boolean containsReifiedParametersInSupertypes(@NotNull ClassDescriptor descriptor) {
private static void addReifiedParametersFromSignature(@NotNull MemberCodegen member, @NotNull ClassDescriptor descriptor) {
for (JetType type : descriptor.getTypeConstructor().getSupertypes()) {
for (TypeProjection supertypeArgument : type.getArguments()) {
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(supertypeArgument.getType());
if (parameterDescriptor != null && parameterDescriptor.isReified()) {
return true;
member.getReifiedTypeParametersUsages().addUsedReifiedParameter(parameterDescriptor.getName().asString());
}
}
}
return false;
}
private static class ObjectLiteralResult {
@@ -1404,8 +1400,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
closureCodegen.generate();
if (closureCodegen.wereReifierMarkers()) {
if (closureCodegen.getReifiedTypeParametersUsages().wereUsedReifiedParameters()) {
ReifiedTypeInliner.putNeedClassReificationMarker(v);
propagateChildReifiedTypeParametersUsages(closureCodegen.getReifiedTypeParametersUsages());
}
return closureCodegen.putInstanceOnStack(this);
@@ -2304,7 +2301,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@NotNull
private CallGenerator getOrCreateCallGenerator(@NotNull ResolvedCall<?> resolvedCall) {
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
ReifiedTypeParameterMappings mappings = new ReifiedTypeParameterMappings(typeArguments.size());
ReifiedTypeParameterMappings mappings = new ReifiedTypeParameterMappings();
for (Map.Entry<TypeParameterDescriptor, JetType> entry : typeArguments.entrySet()) {
TypeParameterDescriptor key = entry.getKey();
if (!key.isReified()) continue;
@@ -2314,16 +2311,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
// type is not generic
// boxType call needed because inlined method is compiled for T as java/lang/Object
mappings.addParameterMappingToType(
key.getIndex(),
key.getName().getIdentifier(),
boxType(asmType(entry.getValue()))
);
}
else {
mappings.addParameterMappingToNewParameter(
key.getIndex(),
key.getName().getIdentifier(),
parameterDescriptor.getIndex(),
parameterDescriptor.getName().getIdentifier()
);
}
@@ -3901,15 +3895,23 @@ The "returned" value of try expression with no finally is either the last expres
public void putReifierMarkerIfTypeIsReifiedParameter(@NotNull JetType type, @NotNull String markerMethodName) {
TypeParameterDescriptor typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type);
if (typeParameterDescriptor != null && typeParameterDescriptor.isReified()) {
parentCodegen.setWereReifierMarkers(true);
v.iconst(typeParameterDescriptor.getIndex());
if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) {
parentCodegen.getReifiedTypeParametersUsages().
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
}
v.visitLdcInsn(typeParameterDescriptor.getName().asString());
v.invokestatic(
IntrinsicMethods.INTRINSICS_CLASS_NAME, markerMethodName,
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE), false
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false
);
}
}
public void propagateChildReifiedTypeParametersUsages(@NotNull ReifiedTypeParametersUsages usages) {
parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(usages, context);
}
@Override
public StackValue visitWhenExpression(@NotNull JetWhenExpression expression, StackValue receiver) {
return generateWhenExpression(expression, false);
@@ -25,6 +25,7 @@ import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.FieldOwnerContext;
import org.jetbrains.jet.codegen.inline.InlineCodegenUtil;
import org.jetbrains.jet.codegen.inline.NameGenerator;
import org.jetbrains.jet.codegen.inline.ReifiedTypeParametersUsages;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
@@ -46,9 +47,7 @@ import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.commons.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.*;
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
@@ -69,7 +68,7 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
protected ExpressionCodegen clInit;
private NameGenerator inlineNameGenerator;
private boolean wereReifierMarkers;
private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
public MemberCodegen(
@NotNull GenerationState state,
@@ -385,11 +384,8 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
return context;
}
public boolean wereReifierMarkers() {
return wereReifierMarkers;
}
public void setWereReifierMarkers(boolean wereReifierMarkers) {
this.wereReifierMarkers = wereReifierMarkers;
@NotNull
public ReifiedTypeParametersUsages getReifiedTypeParametersUsages() {
return reifiedTypeParametersUsages;
}
}
@@ -90,7 +90,7 @@ public class AnonymousObjectTransformer {
if (signature != null) {
ReifiedTypeInliner.SignatureReificationResult signatureResult = inliningContext.reifedTypeInliner.reifySignature(signature);
signature = signatureResult.getNewSignature();
result.markAsNeededFurtherReificationIf(signatureResult.getNeedFurtherReification());
result.getReifiedTypeParametersUsages().mergeAll(signatureResult.getTypeParametersUsages());
}
super.visit(version, access, name, signature, superName, interfaces);
}
@@ -148,7 +148,7 @@ public class AnonymousObjectTransformer {
MethodVisitor visitor = newMethod(classBuilder, next);
InlineResult funResult = inlineMethod(anonymousObjectGen, parentRemapper, visitor, next, allCapturedParamBuilder);
result.addAllClassesToRemove(funResult);
result.markAsNeededFurtherReificationIf(funResult.needFurtherReification());
result.getReifiedTypeParametersUsages().mergeAll(funResult.getReifiedTypeParametersUsages());
}
InlineResult constructorResult =
@@ -170,7 +170,7 @@ public class AnonymousObjectTransformer {
@NotNull MethodNode sourceNode,
@NotNull ParametersBuilder capturedBuilder
) {
boolean neededFurtherReification = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode.instructions);
ReifiedTypeParametersUsages typeParametersToReify = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode.instructions);
Parameters parameters = getMethodParametersWithCaptured(capturedBuilder, sourceNode);
RegeneratedLambdaFieldRemapper remapper =
@@ -182,7 +182,7 @@ public class AnonymousObjectTransformer {
remapper, isSameModule, "Transformer for " + anonymousObjectGen.getOwnerInternalName());
InlineResult result = inliner.doInline(resultVisitor, new LocalVarRemapper(parameters, 0), false, LabelOwner.NOT_APPLICABLE);
result.markAsNeededFurtherReificationIf(neededFurtherReification);
result.getReifiedTypeParametersUsages().mergeAll(typeParametersToReify);
resultVisitor.visitMaxs(-1, -1);
resultVisitor.visitEnd();
return result;
@@ -29,7 +29,6 @@ import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedSimpleFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
@@ -142,6 +141,8 @@ public class InlineCodegen implements CallGenerator {
private void endCall(@NotNull InlineResult result) {
leaveTemps();
codegen.propagateChildReifiedTypeParametersUsages(result.getReifiedTypeParametersUsages());
state.getFactory().removeInlinedClasses(result.getClassesToRemove());
}
@@ -201,7 +202,7 @@ public class InlineCodegen implements CallGenerator {
}
private InlineResult inlineCall(MethodNode node) {
reifiedTypeInliner.reifyInstructions(node.instructions);
ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node.instructions);
generateClosuresBodies();
//through generation captured parameters will be added to invocationParamBuilder
@@ -226,6 +227,7 @@ public class InlineCodegen implements CallGenerator {
MethodNode adapter = InlineCodegenUtil.createEmptyMethodNode();
InlineResult result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL);
result.getReifiedTypeParametersUsages().mergeAll(reificationResult);
LabelOwner labelOwner = new LabelOwner() {
@@ -24,7 +24,7 @@ import java.util.Set;
public class InlineResult {
private final Set<String> classesToRemove = new HashSet<String>();
private boolean needFurtherReification = false;
private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
private InlineResult() {
@@ -50,11 +50,8 @@ public class InlineResult {
return classesToRemove;
}
public boolean needFurtherReification() {
return needFurtherReification;
}
public void markAsNeededFurtherReificationIf(boolean condtition) {
this.needFurtherReification |= condtition;
@NotNull
public ReifiedTypeParametersUsages getReifiedTypeParametersUsages() {
return reifiedTypeParametersUsages;
}
}
@@ -172,9 +172,9 @@ public class MethodInliner {
result.addClassToRemove(anonymousObjectGen.getOwnerInternalName());
}
if (transformResult.needFurtherReification()) {
if (transformResult.getReifiedTypeParametersUsages().wereUsedReifiedParameters()) {
ReifiedTypeInliner.putNeedClassReificationMarker(mv);
result.markAsNeededFurtherReificationIf(true);
result.getReifiedTypeParametersUsages().mergeAll(transformResult.getReifiedTypeParametersUsages());
}
}
}
@@ -34,6 +34,8 @@ 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.jet.codegen.context.MethodContext
import org.jetbrains.jet.lang.resolve.DescriptorUtils
public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParameterMappings?) {
@@ -70,34 +72,35 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
}
/**
* @return true if there is something need to be reified further
* @return set of type parameters' identifiers contained in markers that should be reified further
* e.g. when we're generating inline function containing reified T
* and another function containing reifiable parts is inlined into that function
*/
public fun reifyInstructions(instructions: InsnList): Boolean {
if (parametersMapping == null) return false
var needFurtherReification = false
public fun reifyInstructions(instructions: InsnList): ReifiedTypeParametersUsages {
if (parametersMapping == null) return ReifiedTypeParametersUsages()
var result = ReifiedTypeParametersUsages()
for (insn in instructions.toArray()) {
if (isParametrisedReifiedMarker(insn)) {
if (processReifyMarker(insn as MethodInsnNode, instructions)) {
needFurtherReification = true
val newName: String? = processReifyMarker(insn as MethodInsnNode, instructions)
if (newName != null) {
result.addUsedReifiedParameter(newName)
}
}
}
return needFurtherReification
return result
}
public fun reifySignature(oldSignature: String): SignatureReificationResult {
if (parametersMapping == null) return SignatureReificationResult(oldSignature, false)
if (parametersMapping == null) return SignatureReificationResult(oldSignature, ReifiedTypeParametersUsages())
val signatureRemapper = object : SignatureWriter() {
var needFurtherReification = false
var typeParamsToReify = ReifiedTypeParametersUsages()
override fun visitTypeVariable(name: String?) {
val mapping = getMappingByName(name) ?:
return super.visitTypeArgument()
return super.visitTypeVariable(name)
if (mapping.newName != null) {
needFurtherReification = true
typeParamsToReify.addUsedReifiedParameter(mapping.newName)
return super.visitTypeVariable(mapping.newName)
}
@@ -110,7 +113,7 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
val mapping = getMappingByName(name) ?:
return super.visitFormalTypeParameter(name)
if (mapping.newName != null) {
needFurtherReification = true
typeParamsToReify.addUsedReifiedParameter(mapping.newName)
super.visitFormalTypeParameter(mapping.newName)
}
}
@@ -120,35 +123,38 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
SignatureReader(oldSignature).accept(signatureRemapper)
return SignatureReificationResult(signatureRemapper.toString(), signatureRemapper.needFurtherReification)
return SignatureReificationResult(signatureRemapper.toString(), signatureRemapper.typeParamsToReify)
}
data class SignatureReificationResult(val newSignature: String, val needFurtherReification: Boolean)
data class SignatureReificationResult(val newSignature: String, val typeParametersUsages: ReifiedTypeParametersUsages)
/**
* @return true if this marker should be reified further
* @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): Boolean {
val mapping = getTypeParameterMapping(insn) ?: return false
private fun processReifyMarker(insn: MethodInsnNode, instructions: InsnList): String? {
val mapping = getTypeParameterMapping(insn) ?: return null
val asmType = mapping.asmType
if (asmType != null) {
if (!when (insn.name) {
// 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
if (when (insn.name) {
NEW_ARRAY_MARKER_METHOD_NAME -> processNewArray(insn, asmType)
CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, asmType)
INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, asmType)
JAVA_CLASS_MARKER_METHOD_NAME -> processJavaClass(insn, asmType)
else -> false
}) {
return false
instructions.remove(insn.getPrevious()!!)
instructions.remove(insn)
}
instructions.remove(insn.getPrevious()!!)
instructions.remove(insn)
return false
return null
} else {
instructions.set(insn.getPrevious()!!, iconstInsn(mapping.newIndex!!))
return true
instructions.set(insn.getPrevious()!!, LdcInsnNode(mapping.newName))
return mapping.newName
}
}
@@ -174,51 +180,61 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
return true
}
private fun getParameterIndex(insn: MethodInsnNode): Int? {
private fun getParameterName(insn: MethodInsnNode): String? {
val prev = insn.getPrevious()!!
return when (prev.getOpcode()) {
Opcodes.ICONST_0 -> 0
Opcodes.ICONST_1 -> 1
Opcodes.ICONST_2 -> 2
Opcodes.ICONST_3 -> 3
Opcodes.ICONST_4 -> 4
Opcodes.ICONST_5 -> 5
Opcodes.BIPUSH, Opcodes.SIPUSH -> (prev as IntInsnNode).operand
Opcodes.LDC -> (prev as LdcInsnNode).cst as Int
else -> throw AssertionError("Unexpected opcode ${prev.getOpcode()}")
Opcodes.LDC -> (prev as LdcInsnNode).cst as String
else -> null
}
}
private fun getTypeParameterMapping(insn: MethodInsnNode): ReifiedTypeParameterMapping? {
return parametersMapping?.get(getParameterIndex(insn) ?: return null)
return parametersMapping?.get(getParameterName(insn) ?: return null)
}
}
public class ReifiedTypeParameterMappings(private val size: Int) {
private val mappingsByIndex = arrayOfNulls<ReifiedTypeParameterMapping>(size)
private val indexByParameterName = hashMapOf<String, Int>()
public class ReifiedTypeParameterMappings() {
private val mappingsByName = hashMapOf<String, ReifiedTypeParameterMapping>()
public fun addParameterMappingToType(index: Int, name: String, asmType: Type) {
mappingsByIndex[index] = ReifiedTypeParameterMapping(name, asmType, null, null)
indexByParameterName[name] = index
public fun addParameterMappingToType(name: String, asmType: Type) {
mappingsByName[name] = ReifiedTypeParameterMapping(name, asmType, null)
}
public fun addParameterMappingToNewParameter(index: Int, name: String, newIndex: Int, newName: String) {
mappingsByIndex[index] = ReifiedTypeParameterMapping(name, null, newIndex, newName)
indexByParameterName[name] = index
public fun addParameterMappingToNewParameter(name: String, newName: String) {
mappingsByName[name] = ReifiedTypeParameterMapping(name, null, newName)
}
fun get(index: Int) = mappingsByIndex[index]
fun get(name: String): ReifiedTypeParameterMapping? {
return this[indexByParameterName[name] ?: return null]
return mappingsByName[name]
}
}
public class ReifiedTypeParameterMapping(val name: String, val asmType: Type?, val newIndex: Int?, val newName: String?)
public class ReifiedTypeParameterMapping(val name: String, val asmType: Type?, val newName: String?)
private fun iconstInsn(n: Int): AbstractInsnNode {
val node = MethodNode()
InstructionAdapter(node).iconst(n)
return node.instructions.getFirst()!!
public class ReifiedTypeParametersUsages {
val usedTypeParameters: MutableSet<String> = hashSetOf()
public fun wereUsedReifiedParameters(): Boolean = usedTypeParameters.isNotEmpty()
public fun addUsedReifiedParameter(name: String) {
usedTypeParameters.add(name)
}
public fun propagateChildUsagesWithinContext(child: ReifiedTypeParametersUsages, context: MethodContext) {
if (!child.wereUsedReifiedParameters()) return
// used for propagating reified TP usages from children member codegen to parent's
// mark enclosing object-literal/lambda as needed reification iff
// 1. at least one of it's method contains operations to reify
// 2. reified type parameter of these operations is not from current method signature
// i.e. from outer scope
child.usedTypeParameters.filterNot {
DescriptorUtils.containsReifiedTypeParameterWithName(context.getContextDescriptor(), it)
}.forEach { usedTypeParameters.add(it) }
}
public fun mergeAll(other: ReifiedTypeParametersUsages) {
if (!other.wereUsedReifiedParameters()) return
usedTypeParameters.addAll(other.usedTypeParameters)
}
}
@@ -0,0 +1,36 @@
import kotlin.test.assertEquals
trait A {
fun f1(): String
fun f2(): String
fun f3(): String
}
fun doWork(block: () -> String) = block()
inline fun doWorkInline(block: () -> String) = block()
fun box(): String {
val x = object {
inline fun <reified T> bar1(): A = object : A {
override fun f1(): String = javaClass<T>().getName()
override fun f2(): String = doWork { javaClass<T>().getName() }
override fun f3(): String = doWorkInline { javaClass<T>().getName() }
}
inline fun <reified T> bar2() = javaClass<T>().getName()
inline fun <reified T> bar3() = doWork { javaClass<T>().getName() }
inline fun <reified T> bar4() = doWorkInline { javaClass<T>().getName() }
}
val y: A = x.bar1<String>()
assertEquals("java.lang.String", y.f1())
assertEquals("java.lang.String", y.f2())
assertEquals("java.lang.String", y.f3())
assertEquals("java.lang.Integer", x.bar2<Int>())
assertEquals("java.lang.Double", x.bar3<Double>())
assertEquals("java.lang.Long", x.bar4<Long>())
return "OK"
}
@@ -0,0 +1,42 @@
import kotlin.test.assertEquals
inline fun <reified T, reified R> foo(): Array<String> {
val x = object {
inline fun <reified T1, reified T> bar(): Array<String> = array(
javaClass<T1>().getName(), javaClass<T>().getName(), javaClass<R>().getName()
)
fun f1() = bar<T, R>()
fun f2() = bar<R, T>()
fun f3() = bar<Boolean, T>()
fun f4() = bar<T, Boolean>()
}
val x1 = x.f1()
val x2 = x.f2()
val x3 = x.f3()
val x4 = x.f4()
return array(
x1[0], x1[1], x1[2],
x2[0], x2[1], x2[2],
x3[0], x3[1], x3[2],
x4[0], x4[1], x4[2]
)
}
fun box(): String {
val result = foo<Double, Int>()
val expected = array(
"java.lang.Double", "java.lang.Integer", "java.lang.Integer",
"java.lang.Integer", "java.lang.Double", "java.lang.Integer",
"java.lang.Boolean", "java.lang.Double", "java.lang.Integer",
"java.lang.Double", "java.lang.Boolean", "java.lang.Integer"
)
for (i in expected.indices) {
assertEquals(expected[i], result[i], "$i-th element")
}
return "OK"
}
@@ -0,0 +1,32 @@
import kotlin.test.assertEquals
open class A<T1, T2, T3>
inline fun <reified T, reified R> foo(): Array<A<*,*,*>> {
val x = object {
inline fun <reified T1, reified T> bar(): A<*,*,*> = object : A<T1,T,R>() {}
fun f1() = bar<T, R>()
fun f2() = bar<R, T>()
fun f3() = bar<Boolean, T>()
fun f4() = bar<T, Boolean>()
}
return array(x.f1(), x.f2(), x.f3(), x.f4())
}
fun box(): String {
val result = foo<Double, Int>()
val expected = array(
Triple("java.lang.Double", "java.lang.Integer", "java.lang.Integer"),
Triple("java.lang.Integer", "java.lang.Double", "java.lang.Integer"),
Triple("java.lang.Boolean", "java.lang.Double", "java.lang.Integer"),
Triple("java.lang.Double", "java.lang.Boolean", "java.lang.Integer")
).map { "A<${it.first}, ${it.second}, ${it.third}>" }
for (i in expected.indices) {
assertEquals(expected[i], result[i].javaClass.getGenericSuperclass()?.toString(), "$i-th element")
}
return "OK"
}
@@ -0,0 +1,21 @@
import kotlin.test.assertEquals
fun foo(block: () -> String) = block()
trait A {
fun f(): String
fun g(): String
}
fun box(): String {
val x: A = object : A {
private inline fun <reified T> localClassName(): String = javaClass<T>().getName()
override fun f(): String = foo { localClassName<String>() }
override fun g(): String = foo { localClassName<Int>() }
}
assertEquals("java.lang.String", x.f())
assertEquals("java.lang.Integer", x.g())
return "OK"
}
@@ -0,0 +1,28 @@
import kotlin.test.assertEquals
fun foo(block: () -> String) = block()
inline fun <reified T> className(): String = javaClass<T>().getName()
inline fun <reified T> lambdaShouldBeReified(): String = foo { className<T>() }
trait A {
fun f(): String
fun g(): String
}
inline fun<reified T1, reified T2> AFactory(): A = object : A {
override fun f(): String = className<T1>()
override fun g(): String = foo { className<T2>() }
}
fun box(): String {
assertEquals("java.lang.String", lambdaShouldBeReified<String>())
assertEquals("java.lang.Integer", lambdaShouldBeReified<Int>())
val x: A = AFactory<String, Int>()
assertEquals("java.lang.String", x.f())
assertEquals("java.lang.Integer", x.g())
return "OK"
}
@@ -2640,6 +2640,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib(fileName);
}
@TestMetadata("anonymousObjectNoPropagate.kt")
public void testAnonymousObjectNoPropagate() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/anonymousObjectNoPropagate.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("anonymousObjectReifiedSupertype.kt")
public void testAnonymousObjectReifiedSupertype() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/anonymousObjectReifiedSupertype.kt");
@@ -2688,6 +2694,18 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib(fileName);
}
@TestMetadata("nestedReified.kt")
public void testNestedReified() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/nestedReified.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("nestedReifiedSignature.kt")
public void testNestedReifiedSignature() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/nestedReifiedSignature.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("newArrayInt.kt")
public void testNewArrayInt() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/newArrayInt.kt");
@@ -2718,6 +2736,18 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib(fileName);
}
@TestMetadata("reifiedInlineFunOfObject.kt")
public void testReifiedInlineFunOfObject() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/reifiedInlineFunOfObject.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("reifiedInlineFunOfObjectWithinReified.kt")
public void testReifiedInlineFunOfObjectWithinReified() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/reifiedInlineFunOfObjectWithinReified.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("reifiedInlineIntoNonInlineableLambda.kt")
public void testReifiedInlineIntoNonInlineableLambda() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/reifiedInlineIntoNonInlineableLambda.kt");
@@ -442,4 +442,12 @@ public class DescriptorUtils {
}
return result;
}
public static boolean containsReifiedTypeParameterWithName(@NotNull CallableDescriptor descriptor, @NotNull String name) {
for (TypeParameterDescriptor typeParameterDescriptor : descriptor.getTypeParameters()) {
if (typeParameterDescriptor.isReified() && typeParameterDescriptor.getName().asString().equals(name)) return true;
}
return false;
}
}
@@ -109,19 +109,19 @@ public class Intrinsics {
throw new UnsupportedOperationException("You should not use functions with reified parameter without inline");
}
public static void reifyNewArray(int parameterTypeIndex) {
public static void reifyNewArray(String typeParameterIdentifier) {
throwUndefinedForReified();
}
public static void reifyCheckcast(int parameterTypeIndex) {
public static void reifyCheckcast(String typeParameterIdentifier) {
throwUndefinedForReified();
}
public static void reifyInstanceof(int parameterTypeIndex) {
public static void reifyInstanceof(String typeParameterIdentifier) {
throwUndefinedForReified();
}
public static void reifyJavaClass(int parameterTypeIndex) {
public static void reifyJavaClass(String typeParameterIdentifier) {
throwUndefinedForReified();
}