Supported nested reified parameter declarations
Also switched to using type names as identifiers instead of their indices
This commit is contained in:
@@ -207,28 +207,24 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
);
|
);
|
||||||
literalCodegen.generate();
|
literalCodegen.generate();
|
||||||
|
|
||||||
if (containsReifiedParametersInSupertypes(classDescriptor)) {
|
addReifiedParametersFromSignature(literalCodegen, classDescriptor);
|
||||||
literalCodegen.setWereReifierMarkers(true);
|
propagateChildReifiedTypeParametersUsages(literalCodegen.getReifiedTypeParametersUsages());
|
||||||
}
|
|
||||||
|
|
||||||
if (literalCodegen.wereReifierMarkers()) {
|
return new ObjectLiteralResult(
|
||||||
getParentCodegen().setWereReifierMarkers(true);
|
literalCodegen.getReifiedTypeParametersUsages().wereUsedReifiedParameters(),
|
||||||
}
|
classDescriptor
|
||||||
|
);
|
||||||
return new ObjectLiteralResult(literalCodegen.wereReifierMarkers(), 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 (JetType type : descriptor.getTypeConstructor().getSupertypes()) {
|
||||||
for (TypeProjection supertypeArgument : type.getArguments()) {
|
for (TypeProjection supertypeArgument : type.getArguments()) {
|
||||||
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(supertypeArgument.getType());
|
TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(supertypeArgument.getType());
|
||||||
if (parameterDescriptor != null && parameterDescriptor.isReified()) {
|
if (parameterDescriptor != null && parameterDescriptor.isReified()) {
|
||||||
return true;
|
member.getReifiedTypeParametersUsages().addUsedReifiedParameter(parameterDescriptor.getName().asString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ObjectLiteralResult {
|
private static class ObjectLiteralResult {
|
||||||
@@ -1404,8 +1400,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
closureCodegen.generate();
|
closureCodegen.generate();
|
||||||
|
|
||||||
if (closureCodegen.wereReifierMarkers()) {
|
if (closureCodegen.getReifiedTypeParametersUsages().wereUsedReifiedParameters()) {
|
||||||
ReifiedTypeInliner.putNeedClassReificationMarker(v);
|
ReifiedTypeInliner.putNeedClassReificationMarker(v);
|
||||||
|
propagateChildReifiedTypeParametersUsages(closureCodegen.getReifiedTypeParametersUsages());
|
||||||
}
|
}
|
||||||
|
|
||||||
return closureCodegen.putInstanceOnStack(this);
|
return closureCodegen.putInstanceOnStack(this);
|
||||||
@@ -2304,7 +2301,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
@NotNull
|
@NotNull
|
||||||
private CallGenerator getOrCreateCallGenerator(@NotNull ResolvedCall<?> resolvedCall) {
|
private CallGenerator getOrCreateCallGenerator(@NotNull ResolvedCall<?> resolvedCall) {
|
||||||
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
|
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
|
||||||
ReifiedTypeParameterMappings mappings = new ReifiedTypeParameterMappings(typeArguments.size());
|
ReifiedTypeParameterMappings mappings = new ReifiedTypeParameterMappings();
|
||||||
for (Map.Entry<TypeParameterDescriptor, JetType> entry : typeArguments.entrySet()) {
|
for (Map.Entry<TypeParameterDescriptor, JetType> entry : typeArguments.entrySet()) {
|
||||||
TypeParameterDescriptor key = entry.getKey();
|
TypeParameterDescriptor key = entry.getKey();
|
||||||
if (!key.isReified()) continue;
|
if (!key.isReified()) continue;
|
||||||
@@ -2314,16 +2311,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
// type is not generic
|
// type is not generic
|
||||||
// boxType call needed because inlined method is compiled for T as java/lang/Object
|
// boxType call needed because inlined method is compiled for T as java/lang/Object
|
||||||
mappings.addParameterMappingToType(
|
mappings.addParameterMappingToType(
|
||||||
key.getIndex(),
|
|
||||||
key.getName().getIdentifier(),
|
key.getName().getIdentifier(),
|
||||||
boxType(asmType(entry.getValue()))
|
boxType(asmType(entry.getValue()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mappings.addParameterMappingToNewParameter(
|
mappings.addParameterMappingToNewParameter(
|
||||||
key.getIndex(),
|
|
||||||
key.getName().getIdentifier(),
|
key.getName().getIdentifier(),
|
||||||
parameterDescriptor.getIndex(),
|
|
||||||
parameterDescriptor.getName().getIdentifier()
|
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) {
|
public void putReifierMarkerIfTypeIsReifiedParameter(@NotNull JetType type, @NotNull String markerMethodName) {
|
||||||
TypeParameterDescriptor typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type);
|
TypeParameterDescriptor typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type);
|
||||||
if (typeParameterDescriptor != null && typeParameterDescriptor.isReified()) {
|
if (typeParameterDescriptor != null && typeParameterDescriptor.isReified()) {
|
||||||
parentCodegen.setWereReifierMarkers(true);
|
if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) {
|
||||||
v.iconst(typeParameterDescriptor.getIndex());
|
parentCodegen.getReifiedTypeParametersUsages().
|
||||||
|
addUsedReifiedParameter(typeParameterDescriptor.getName().asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
v.visitLdcInsn(typeParameterDescriptor.getName().asString());
|
||||||
v.invokestatic(
|
v.invokestatic(
|
||||||
IntrinsicMethods.INTRINSICS_CLASS_NAME, markerMethodName,
|
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
|
@Override
|
||||||
public StackValue visitWhenExpression(@NotNull JetWhenExpression expression, StackValue receiver) {
|
public StackValue visitWhenExpression(@NotNull JetWhenExpression expression, StackValue receiver) {
|
||||||
return generateWhenExpression(expression, false);
|
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.context.FieldOwnerContext;
|
||||||
import org.jetbrains.jet.codegen.inline.InlineCodegenUtil;
|
import org.jetbrains.jet.codegen.inline.InlineCodegenUtil;
|
||||||
import org.jetbrains.jet.codegen.inline.NameGenerator;
|
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.codegen.state.GenerationState;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
|
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.InstructionAdapter;
|
||||||
import org.jetbrains.org.objectweb.asm.commons.Method;
|
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
|
import static org.jetbrains.jet.codegen.AsmUtil.isPrimitive;
|
||||||
import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
|
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;
|
protected ExpressionCodegen clInit;
|
||||||
private NameGenerator inlineNameGenerator;
|
private NameGenerator inlineNameGenerator;
|
||||||
private boolean wereReifierMarkers;
|
private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
|
||||||
|
|
||||||
public MemberCodegen(
|
public MemberCodegen(
|
||||||
@NotNull GenerationState state,
|
@NotNull GenerationState state,
|
||||||
@@ -385,11 +384,8 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
|
|||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean wereReifierMarkers() {
|
@NotNull
|
||||||
return wereReifierMarkers;
|
public ReifiedTypeParametersUsages getReifiedTypeParametersUsages() {
|
||||||
}
|
return reifiedTypeParametersUsages;
|
||||||
|
|
||||||
public void setWereReifierMarkers(boolean wereReifierMarkers) {
|
|
||||||
this.wereReifierMarkers = wereReifierMarkers;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -90,7 +90,7 @@ public class AnonymousObjectTransformer {
|
|||||||
if (signature != null) {
|
if (signature != null) {
|
||||||
ReifiedTypeInliner.SignatureReificationResult signatureResult = inliningContext.reifedTypeInliner.reifySignature(signature);
|
ReifiedTypeInliner.SignatureReificationResult signatureResult = inliningContext.reifedTypeInliner.reifySignature(signature);
|
||||||
signature = signatureResult.getNewSignature();
|
signature = signatureResult.getNewSignature();
|
||||||
result.markAsNeededFurtherReificationIf(signatureResult.getNeedFurtherReification());
|
result.getReifiedTypeParametersUsages().mergeAll(signatureResult.getTypeParametersUsages());
|
||||||
}
|
}
|
||||||
super.visit(version, access, name, signature, superName, interfaces);
|
super.visit(version, access, name, signature, superName, interfaces);
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ public class AnonymousObjectTransformer {
|
|||||||
MethodVisitor visitor = newMethod(classBuilder, next);
|
MethodVisitor visitor = newMethod(classBuilder, next);
|
||||||
InlineResult funResult = inlineMethod(anonymousObjectGen, parentRemapper, visitor, next, allCapturedParamBuilder);
|
InlineResult funResult = inlineMethod(anonymousObjectGen, parentRemapper, visitor, next, allCapturedParamBuilder);
|
||||||
result.addAllClassesToRemove(funResult);
|
result.addAllClassesToRemove(funResult);
|
||||||
result.markAsNeededFurtherReificationIf(funResult.needFurtherReification());
|
result.getReifiedTypeParametersUsages().mergeAll(funResult.getReifiedTypeParametersUsages());
|
||||||
}
|
}
|
||||||
|
|
||||||
InlineResult constructorResult =
|
InlineResult constructorResult =
|
||||||
@@ -170,7 +170,7 @@ public class AnonymousObjectTransformer {
|
|||||||
@NotNull MethodNode sourceNode,
|
@NotNull MethodNode sourceNode,
|
||||||
@NotNull ParametersBuilder capturedBuilder
|
@NotNull ParametersBuilder capturedBuilder
|
||||||
) {
|
) {
|
||||||
boolean neededFurtherReification = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode.instructions);
|
ReifiedTypeParametersUsages typeParametersToReify = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode.instructions);
|
||||||
Parameters parameters = getMethodParametersWithCaptured(capturedBuilder, sourceNode);
|
Parameters parameters = getMethodParametersWithCaptured(capturedBuilder, sourceNode);
|
||||||
|
|
||||||
RegeneratedLambdaFieldRemapper remapper =
|
RegeneratedLambdaFieldRemapper remapper =
|
||||||
@@ -182,7 +182,7 @@ public class AnonymousObjectTransformer {
|
|||||||
remapper, isSameModule, "Transformer for " + anonymousObjectGen.getOwnerInternalName());
|
remapper, isSameModule, "Transformer for " + anonymousObjectGen.getOwnerInternalName());
|
||||||
|
|
||||||
InlineResult result = inliner.doInline(resultVisitor, new LocalVarRemapper(parameters, 0), false, LabelOwner.NOT_APPLICABLE);
|
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.visitMaxs(-1, -1);
|
||||||
resultVisitor.visitEnd();
|
resultVisitor.visitEnd();
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import org.jetbrains.jet.codegen.state.GenerationState;
|
|||||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedSimpleFunctionDescriptor;
|
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedSimpleFunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
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.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
@@ -142,6 +141,8 @@ public class InlineCodegen implements CallGenerator {
|
|||||||
private void endCall(@NotNull InlineResult result) {
|
private void endCall(@NotNull InlineResult result) {
|
||||||
leaveTemps();
|
leaveTemps();
|
||||||
|
|
||||||
|
codegen.propagateChildReifiedTypeParametersUsages(result.getReifiedTypeParametersUsages());
|
||||||
|
|
||||||
state.getFactory().removeInlinedClasses(result.getClassesToRemove());
|
state.getFactory().removeInlinedClasses(result.getClassesToRemove());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +202,7 @@ public class InlineCodegen implements CallGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private InlineResult inlineCall(MethodNode node) {
|
private InlineResult inlineCall(MethodNode node) {
|
||||||
reifiedTypeInliner.reifyInstructions(node.instructions);
|
ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node.instructions);
|
||||||
generateClosuresBodies();
|
generateClosuresBodies();
|
||||||
|
|
||||||
//through generation captured parameters will be added to invocationParamBuilder
|
//through generation captured parameters will be added to invocationParamBuilder
|
||||||
@@ -226,6 +227,7 @@ public class InlineCodegen implements CallGenerator {
|
|||||||
|
|
||||||
MethodNode adapter = InlineCodegenUtil.createEmptyMethodNode();
|
MethodNode adapter = InlineCodegenUtil.createEmptyMethodNode();
|
||||||
InlineResult result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL);
|
InlineResult result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL);
|
||||||
|
result.getReifiedTypeParametersUsages().mergeAll(reificationResult);
|
||||||
|
|
||||||
LabelOwner labelOwner = new LabelOwner() {
|
LabelOwner labelOwner = new LabelOwner() {
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import java.util.Set;
|
|||||||
public class InlineResult {
|
public class InlineResult {
|
||||||
|
|
||||||
private final Set<String> classesToRemove = new HashSet<String>();
|
private final Set<String> classesToRemove = new HashSet<String>();
|
||||||
private boolean needFurtherReification = false;
|
private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
|
||||||
|
|
||||||
private InlineResult() {
|
private InlineResult() {
|
||||||
|
|
||||||
@@ -50,11 +50,8 @@ public class InlineResult {
|
|||||||
return classesToRemove;
|
return classesToRemove;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean needFurtherReification() {
|
@NotNull
|
||||||
return needFurtherReification;
|
public ReifiedTypeParametersUsages getReifiedTypeParametersUsages() {
|
||||||
}
|
return reifiedTypeParametersUsages;
|
||||||
|
|
||||||
public void markAsNeededFurtherReificationIf(boolean condtition) {
|
|
||||||
this.needFurtherReification |= condtition;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,9 +172,9 @@ public class MethodInliner {
|
|||||||
result.addClassToRemove(anonymousObjectGen.getOwnerInternalName());
|
result.addClassToRemove(anonymousObjectGen.getOwnerInternalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transformResult.needFurtherReification()) {
|
if (transformResult.getReifiedTypeParametersUsages().wereUsedReifiedParameters()) {
|
||||||
ReifiedTypeInliner.putNeedClassReificationMarker(mv);
|
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.signature.SignatureWriter
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||||
import com.google.common.collect.ImmutableSet
|
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?) {
|
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
|
* e.g. when we're generating inline function containing reified T
|
||||||
* and another function containing reifiable parts is inlined into that function
|
* and another function containing reifiable parts is inlined into that function
|
||||||
*/
|
*/
|
||||||
public fun reifyInstructions(instructions: InsnList): Boolean {
|
public fun reifyInstructions(instructions: InsnList): ReifiedTypeParametersUsages {
|
||||||
if (parametersMapping == null) return false
|
if (parametersMapping == null) return ReifiedTypeParametersUsages()
|
||||||
var needFurtherReification = false
|
var result = ReifiedTypeParametersUsages()
|
||||||
for (insn in instructions.toArray()) {
|
for (insn in instructions.toArray()) {
|
||||||
if (isParametrisedReifiedMarker(insn)) {
|
if (isParametrisedReifiedMarker(insn)) {
|
||||||
if (processReifyMarker(insn as MethodInsnNode, instructions)) {
|
val newName: String? = processReifyMarker(insn as MethodInsnNode, instructions)
|
||||||
needFurtherReification = true
|
if (newName != null) {
|
||||||
|
result.addUsedReifiedParameter(newName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return needFurtherReification
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun reifySignature(oldSignature: String): SignatureReificationResult {
|
public fun reifySignature(oldSignature: String): SignatureReificationResult {
|
||||||
if (parametersMapping == null) return SignatureReificationResult(oldSignature, false)
|
if (parametersMapping == null) return SignatureReificationResult(oldSignature, ReifiedTypeParametersUsages())
|
||||||
|
|
||||||
val signatureRemapper = object : SignatureWriter() {
|
val signatureRemapper = object : SignatureWriter() {
|
||||||
var needFurtherReification = false
|
var typeParamsToReify = ReifiedTypeParametersUsages()
|
||||||
override fun visitTypeVariable(name: String?) {
|
override fun visitTypeVariable(name: String?) {
|
||||||
val mapping = getMappingByName(name) ?:
|
val mapping = getMappingByName(name) ?:
|
||||||
return super.visitTypeArgument()
|
return super.visitTypeVariable(name)
|
||||||
if (mapping.newName != null) {
|
if (mapping.newName != null) {
|
||||||
needFurtherReification = true
|
typeParamsToReify.addUsedReifiedParameter(mapping.newName)
|
||||||
return super.visitTypeVariable(mapping.newName)
|
return super.visitTypeVariable(mapping.newName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +113,7 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
|||||||
val mapping = getMappingByName(name) ?:
|
val mapping = getMappingByName(name) ?:
|
||||||
return super.visitFormalTypeParameter(name)
|
return super.visitFormalTypeParameter(name)
|
||||||
if (mapping.newName != null) {
|
if (mapping.newName != null) {
|
||||||
needFurtherReification = true
|
typeParamsToReify.addUsedReifiedParameter(mapping.newName)
|
||||||
super.visitFormalTypeParameter(mapping.newName)
|
super.visitFormalTypeParameter(mapping.newName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,35 +123,38 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
|||||||
|
|
||||||
SignatureReader(oldSignature).accept(signatureRemapper)
|
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 {
|
private fun processReifyMarker(insn: MethodInsnNode, instructions: InsnList): String? {
|
||||||
val mapping = getTypeParameterMapping(insn) ?: return false
|
val mapping = getTypeParameterMapping(insn) ?: return null
|
||||||
|
|
||||||
val asmType = mapping.asmType
|
val asmType = mapping.asmType
|
||||||
if (asmType != null) {
|
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)
|
NEW_ARRAY_MARKER_METHOD_NAME -> processNewArray(insn, asmType)
|
||||||
CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, asmType)
|
CHECKCAST_MARKER_METHOD_NAME -> processCheckcast(insn, asmType)
|
||||||
INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, asmType)
|
INSTANCEOF_MARKER_METHOD_NAME -> processInstanceof(insn, asmType)
|
||||||
JAVA_CLASS_MARKER_METHOD_NAME -> processJavaClass(insn, asmType)
|
JAVA_CLASS_MARKER_METHOD_NAME -> processJavaClass(insn, asmType)
|
||||||
else -> false
|
else -> false
|
||||||
}) {
|
}) {
|
||||||
return false
|
instructions.remove(insn.getPrevious()!!)
|
||||||
|
instructions.remove(insn)
|
||||||
}
|
}
|
||||||
instructions.remove(insn.getPrevious()!!)
|
|
||||||
instructions.remove(insn)
|
|
||||||
|
|
||||||
return false
|
return null
|
||||||
} else {
|
} else {
|
||||||
instructions.set(insn.getPrevious()!!, iconstInsn(mapping.newIndex!!))
|
instructions.set(insn.getPrevious()!!, LdcInsnNode(mapping.newName))
|
||||||
return true
|
return mapping.newName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,51 +180,61 @@ public class ReifiedTypeInliner(private val parametersMapping: ReifiedTypeParame
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getParameterIndex(insn: MethodInsnNode): Int? {
|
private fun getParameterName(insn: MethodInsnNode): String? {
|
||||||
val prev = insn.getPrevious()!!
|
val prev = insn.getPrevious()!!
|
||||||
|
|
||||||
return when (prev.getOpcode()) {
|
return when (prev.getOpcode()) {
|
||||||
Opcodes.ICONST_0 -> 0
|
Opcodes.LDC -> (prev as LdcInsnNode).cst as String
|
||||||
Opcodes.ICONST_1 -> 1
|
else -> null
|
||||||
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()}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTypeParameterMapping(insn: MethodInsnNode): ReifiedTypeParameterMapping? {
|
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) {
|
public class ReifiedTypeParameterMappings() {
|
||||||
private val mappingsByIndex = arrayOfNulls<ReifiedTypeParameterMapping>(size)
|
private val mappingsByName = hashMapOf<String, ReifiedTypeParameterMapping>()
|
||||||
private val indexByParameterName = hashMapOf<String, Int>()
|
|
||||||
|
|
||||||
public fun addParameterMappingToType(index: Int, name: String, asmType: Type) {
|
public fun addParameterMappingToType(name: String, asmType: Type) {
|
||||||
mappingsByIndex[index] = ReifiedTypeParameterMapping(name, asmType, null, null)
|
mappingsByName[name] = ReifiedTypeParameterMapping(name, asmType, null)
|
||||||
indexByParameterName[name] = index
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun addParameterMappingToNewParameter(index: Int, name: String, newIndex: Int, newName: String) {
|
public fun addParameterMappingToNewParameter(name: String, newName: String) {
|
||||||
mappingsByIndex[index] = ReifiedTypeParameterMapping(name, null, newIndex, newName)
|
mappingsByName[name] = ReifiedTypeParameterMapping(name, null, newName)
|
||||||
indexByParameterName[name] = index
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun get(index: Int) = mappingsByIndex[index]
|
|
||||||
fun get(name: String): ReifiedTypeParameterMapping? {
|
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 {
|
public class ReifiedTypeParametersUsages {
|
||||||
val node = MethodNode()
|
val usedTypeParameters: MutableSet<String> = hashSetOf()
|
||||||
InstructionAdapter(node).iconst(n)
|
|
||||||
return node.instructions.getFirst()!!
|
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"
|
||||||
|
}
|
||||||
+28
@@ -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"
|
||||||
|
}
|
||||||
+30
@@ -2640,6 +2640,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
doTestWithStdlib(fileName);
|
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")
|
@TestMetadata("anonymousObjectReifiedSupertype.kt")
|
||||||
public void testAnonymousObjectReifiedSupertype() throws Exception {
|
public void testAnonymousObjectReifiedSupertype() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/anonymousObjectReifiedSupertype.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/anonymousObjectReifiedSupertype.kt");
|
||||||
@@ -2688,6 +2694,18 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
doTestWithStdlib(fileName);
|
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")
|
@TestMetadata("newArrayInt.kt")
|
||||||
public void testNewArrayInt() throws Exception {
|
public void testNewArrayInt() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/newArrayInt.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/newArrayInt.kt");
|
||||||
@@ -2718,6 +2736,18 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
doTestWithStdlib(fileName);
|
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")
|
@TestMetadata("reifiedInlineIntoNonInlineableLambda.kt")
|
||||||
public void testReifiedInlineIntoNonInlineableLambda() throws Exception {
|
public void testReifiedInlineIntoNonInlineableLambda() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/reifiedInlineIntoNonInlineableLambda.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reified/reifiedInlineIntoNonInlineableLambda.kt");
|
||||||
|
|||||||
@@ -442,4 +442,12 @@ public class DescriptorUtils {
|
|||||||
}
|
}
|
||||||
return result;
|
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");
|
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();
|
throwUndefinedForReified();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void reifyCheckcast(int parameterTypeIndex) {
|
public static void reifyCheckcast(String typeParameterIdentifier) {
|
||||||
throwUndefinedForReified();
|
throwUndefinedForReified();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void reifyInstanceof(int parameterTypeIndex) {
|
public static void reifyInstanceof(String typeParameterIdentifier) {
|
||||||
throwUndefinedForReified();
|
throwUndefinedForReified();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void reifyJavaClass(int parameterTypeIndex) {
|
public static void reifyJavaClass(String typeParameterIdentifier) {
|
||||||
throwUndefinedForReified();
|
throwUndefinedForReified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user