Fix for KT-7017: Reified type referenced in object literal crashes at runtime
#KT-7017 Fixed
This commit is contained in:
+29
-28
@@ -43,6 +43,8 @@ public class AnonymousObjectTransformer {
|
|||||||
|
|
||||||
protected final JetTypeMapper typeMapper;
|
protected final JetTypeMapper typeMapper;
|
||||||
|
|
||||||
|
private final InlineResult transformationResult;
|
||||||
|
|
||||||
private MethodNode constructor;
|
private MethodNode constructor;
|
||||||
|
|
||||||
private String sourceInfo;
|
private String sourceInfo;
|
||||||
@@ -80,6 +82,7 @@ public class AnonymousObjectTransformer {
|
|||||||
|
|
||||||
reader = InlineCodegenUtil.buildClassReaderByInternalName(state, objectInternalName);
|
reader = InlineCodegenUtil.buildClassReaderByInternalName(state, objectInternalName);
|
||||||
typeRemapper = new TypeRemapper(inliningContext.typeMapping);
|
typeRemapper = new TypeRemapper(inliningContext.typeMapping);
|
||||||
|
transformationResult = InlineResult.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -87,14 +90,13 @@ public class AnonymousObjectTransformer {
|
|||||||
ClassBuilder classBuilder = createClassBuilder();
|
ClassBuilder classBuilder = createClassBuilder();
|
||||||
final List<MethodNode> methodsToTransform = new ArrayList<MethodNode>();
|
final List<MethodNode> methodsToTransform = new ArrayList<MethodNode>();
|
||||||
|
|
||||||
final InlineResult result = InlineResult.create();
|
|
||||||
reader.accept(new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) {
|
reader.accept(new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) {
|
||||||
@Override
|
@Override
|
||||||
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
|
public void visit(int version, int access, @NotNull String name, String signature, String superName, String[] interfaces) {
|
||||||
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.getReifiedTypeParametersUsages().mergeAll(signatureResult.getTypeParametersUsages());
|
transformationResult.getReifiedTypeParametersUsages().mergeAll(signatureResult.getTypeParametersUsages());
|
||||||
}
|
}
|
||||||
super.visit(version, access, name, signature, superName, interfaces);
|
super.visit(version, access, name, signature, superName, interfaces);
|
||||||
}
|
}
|
||||||
@@ -182,9 +184,8 @@ public class AnonymousObjectTransformer {
|
|||||||
|
|
||||||
for (MethodNode next : methodsToTransform) {
|
for (MethodNode next : methodsToTransform) {
|
||||||
MethodVisitor deferringVisitor = newMethod(classBuilder, next);
|
MethodVisitor deferringVisitor = newMethod(classBuilder, next);
|
||||||
InlineResult funResult = inlineMethod(anonymousObjectGen, parentRemapper, deferringVisitor, next, allCapturedParamBuilder);
|
InlineResult funResult =
|
||||||
result.addAllClassesToRemove(funResult);
|
inlineMethodAndUpdateGlobalResult(anonymousObjectGen, parentRemapper, deferringVisitor, next, allCapturedParamBuilder, false);
|
||||||
result.getReifiedTypeParametersUsages().mergeAll(funResult.getReifiedTypeParametersUsages());
|
|
||||||
|
|
||||||
Type returnType = Type.getReturnType(next.desc);
|
Type returnType = Type.getReturnType(next.desc);
|
||||||
if (!AsmUtil.isPrimitive(returnType)) {
|
if (!AsmUtil.isPrimitive(returnType)) {
|
||||||
@@ -201,17 +202,29 @@ public class AnonymousObjectTransformer {
|
|||||||
method.visitEnd();
|
method.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
InlineResult constructorResult =
|
generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, anonymousObjectGen, parentRemapper, additionalFakeParams);
|
||||||
generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, anonymousObjectGen, parentRemapper, additionalFakeParams);
|
|
||||||
|
|
||||||
result.addAllClassesToRemove(constructorResult);
|
|
||||||
|
|
||||||
SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder);
|
SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder);
|
||||||
|
|
||||||
classBuilder.done();
|
classBuilder.done();
|
||||||
|
|
||||||
anonymousObjectGen.setNewLambdaType(newLambdaType);
|
anonymousObjectGen.setNewLambdaType(newLambdaType);
|
||||||
return result;
|
return transformationResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private InlineResult inlineMethodAndUpdateGlobalResult(
|
||||||
|
@NotNull AnonymousObjectGeneration anonymousObjectGen,
|
||||||
|
@NotNull FieldRemapper parentRemapper,
|
||||||
|
@NotNull MethodVisitor deferringVisitor,
|
||||||
|
@NotNull MethodNode next,
|
||||||
|
@NotNull ParametersBuilder allCapturedParamBuilder,
|
||||||
|
boolean isConstructor
|
||||||
|
) {
|
||||||
|
InlineResult funResult = inlineMethod(anonymousObjectGen, parentRemapper, deferringVisitor, next, allCapturedParamBuilder, isConstructor);
|
||||||
|
transformationResult.addAllClassesToRemove(funResult);
|
||||||
|
transformationResult.getReifiedTypeParametersUsages().mergeAll(funResult.getReifiedTypeParametersUsages());
|
||||||
|
return funResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -220,15 +233,16 @@ public class AnonymousObjectTransformer {
|
|||||||
@NotNull FieldRemapper parentRemapper,
|
@NotNull FieldRemapper parentRemapper,
|
||||||
@NotNull MethodVisitor deferringVisitor,
|
@NotNull MethodVisitor deferringVisitor,
|
||||||
@NotNull MethodNode sourceNode,
|
@NotNull MethodNode sourceNode,
|
||||||
@NotNull ParametersBuilder capturedBuilder
|
@NotNull ParametersBuilder capturedBuilder,
|
||||||
|
boolean isConstructor
|
||||||
) {
|
) {
|
||||||
ReifiedTypeParametersUsages typeParametersToReify = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode.instructions);
|
ReifiedTypeParametersUsages typeParametersToReify = inliningContext.reifedTypeInliner.reifyInstructions(sourceNode.instructions);
|
||||||
Parameters parameters = getMethodParametersWithCaptured(capturedBuilder, sourceNode);
|
Parameters parameters = isConstructor ? capturedBuilder.buildParameters() : getMethodParametersWithCaptured(capturedBuilder, sourceNode);
|
||||||
|
|
||||||
RegeneratedLambdaFieldRemapper remapper =
|
RegeneratedLambdaFieldRemapper remapper =
|
||||||
new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(),
|
new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(),
|
||||||
parameters, anonymousObjectGen.getCapturedLambdasToInline(),
|
parameters, anonymousObjectGen.getCapturedLambdasToInline(),
|
||||||
parentRemapper, false);
|
parentRemapper, isConstructor);
|
||||||
|
|
||||||
MethodInliner inliner = new MethodInliner(sourceNode, parameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")),
|
MethodInliner inliner = new MethodInliner(sourceNode, parameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")),
|
||||||
remapper, isSameModule, "Transformer for " + anonymousObjectGen.getOwnerInternalName(),
|
remapper, isSameModule, "Transformer for " + anonymousObjectGen.getOwnerInternalName(),
|
||||||
@@ -240,7 +254,7 @@ public class AnonymousObjectTransformer {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InlineResult generateConstructorAndFields(
|
private void generateConstructorAndFields(
|
||||||
@NotNull ClassBuilder classBuilder,
|
@NotNull ClassBuilder classBuilder,
|
||||||
@NotNull ParametersBuilder allCapturedBuilder,
|
@NotNull ParametersBuilder allCapturedBuilder,
|
||||||
@NotNull ParametersBuilder constructorInlineBuilder,
|
@NotNull ParametersBuilder constructorInlineBuilder,
|
||||||
@@ -311,25 +325,12 @@ public class AnonymousObjectTransformer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Parameters constructorParameters = constructorInlineBuilder.buildParameters();
|
inlineMethodAndUpdateGlobalResult(anonymousObjectGen, parentRemapper, capturedFieldInitializer, constructor, constructorInlineBuilder, true);
|
||||||
|
|
||||||
RegeneratedLambdaFieldRemapper remapper =
|
|
||||||
new RegeneratedLambdaFieldRemapper(oldObjectType.getInternalName(), newLambdaType.getInternalName(),
|
|
||||||
constructorParameters, anonymousObjectGen.getCapturedLambdasToInline(),
|
|
||||||
parentRemapper, true);
|
|
||||||
|
|
||||||
MethodInliner inliner = new MethodInliner(constructor, constructorParameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")),
|
|
||||||
remapper, isSameModule, "Transformer for constructor of " + anonymousObjectGen.getOwnerInternalName(),
|
|
||||||
sourceMapper);
|
|
||||||
InlineResult result = inliner.doInline(capturedFieldInitializer, new LocalVarRemapper(constructorParameters, 0), false,
|
|
||||||
LabelOwner.NOT_APPLICABLE);
|
|
||||||
constructorVisitor.visitMaxs(-1, -1);
|
|
||||||
constructorVisitor.visitEnd();
|
constructorVisitor.visitEnd();
|
||||||
|
|
||||||
AsmUtil.genClosureFields(capturedFieldsToGenerate, classBuilder);
|
AsmUtil.genClosureFields(capturedFieldsToGenerate, classBuilder);
|
||||||
//TODO for inline method make public class
|
//TODO for inline method make public class
|
||||||
anonymousObjectGen.setNewConstructorDescriptor(constructorDescriptor);
|
anonymousObjectGen.setNewConstructorDescriptor(constructorDescriptor);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (!test<String>("OK")) return "fail 1"
|
||||||
|
|
||||||
|
if (test<Int>("OK")) return "fail 2"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
inline fun test<reified T>(x: Any): Boolean {
|
||||||
|
val x = object {
|
||||||
|
val y = x is T
|
||||||
|
}
|
||||||
|
|
||||||
|
return x.y
|
||||||
|
}
|
||||||
+6
@@ -1084,6 +1084,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
doTestMultiFileWithInlineCheck(fileName);
|
doTestMultiFileWithInlineCheck(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt7017.1.kt")
|
||||||
|
public void testKt7017() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt7017.1.kt");
|
||||||
|
doTestMultiFileWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("packages.1.kt")
|
@TestMetadata("packages.1.kt")
|
||||||
public void testPackages() throws Exception {
|
public void testPackages() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt");
|
||||||
|
|||||||
+6
@@ -1084,6 +1084,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
doBoxTestWithInlineCheck(fileName);
|
doBoxTestWithInlineCheck(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt7017.1.kt")
|
||||||
|
public void testKt7017() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/kt7017.1.kt");
|
||||||
|
doBoxTestWithInlineCheck(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("packages.1.kt")
|
@TestMetadata("packages.1.kt")
|
||||||
public void testPackages() throws Exception {
|
public void testPackages() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/reified/packages.1.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user