Fix for duplicated fields in regenerated lambda
This commit is contained in:
@@ -19,7 +19,6 @@ package org.jetbrains.jet.codegen.inline;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
||||
|
||||
public class CapturedParamInfo extends ParameterInfo {
|
||||
|
||||
@@ -34,17 +33,31 @@ public class CapturedParamInfo extends ParameterInfo {
|
||||
|
||||
private int shift = 0;
|
||||
|
||||
private final String newFieldName;
|
||||
|
||||
public CapturedParamInfo(@NotNull CapturedParamDesc desc, boolean skipped, int index, int remapIndex) {
|
||||
super(desc.getType(), skipped, index, remapIndex);
|
||||
this.desc = desc;
|
||||
this(desc, desc.getFieldName(), skipped, index, remapIndex);
|
||||
}
|
||||
|
||||
public CapturedParamInfo(@NotNull CapturedParamDesc desc, boolean skipped, int index, StackValue remapIndex) {
|
||||
public CapturedParamInfo(@NotNull CapturedParamDesc desc, @NotNull String newFieldName, boolean skipped, int index, int remapIndex) {
|
||||
super(desc.getType(), skipped, index, remapIndex);
|
||||
this.desc = desc;
|
||||
this.newFieldName = newFieldName;
|
||||
}
|
||||
|
||||
public String getFieldName() {
|
||||
public CapturedParamInfo(@NotNull CapturedParamDesc desc, @NotNull String newFieldName, boolean skipped, int index, StackValue remapIndex) {
|
||||
super(desc.getType(), skipped, index, remapIndex);
|
||||
this.desc = desc;
|
||||
this.newFieldName = newFieldName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getNewFieldName() {
|
||||
return newFieldName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getOriginalFieldName() {
|
||||
return desc.getFieldName();
|
||||
}
|
||||
|
||||
@@ -57,16 +70,19 @@ public class CapturedParamInfo extends ParameterInfo {
|
||||
this.shift = shift;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CapturedParamInfo newIndex(int newIndex) {
|
||||
return clone(newIndex, getRemapValue());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CapturedParamInfo clone(int newIndex, StackValue newRamapIndex) {
|
||||
CapturedParamInfo capturedParamInfo = new CapturedParamInfo(desc, isSkipped, newIndex, newRamapIndex);
|
||||
CapturedParamInfo capturedParamInfo = new CapturedParamInfo(desc, newFieldName, isSkipped, newIndex, newRamapIndex);
|
||||
capturedParamInfo.setLambda(lambda);
|
||||
return capturedParamInfo;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getContainingLambdaName() {
|
||||
return desc.getContainingLambda().getType().getInternalName();
|
||||
}
|
||||
|
||||
@@ -41,13 +41,7 @@ public class FieldRemapper {
|
||||
params = methodParams;
|
||||
}
|
||||
|
||||
public void addCapturedFields(LambdaInfo lambdaInfo, ParametersBuilder builder) {
|
||||
for (CapturedParamInfo info : lambdaInfo.getCapturedVars()) {
|
||||
builder.addCapturedParam(info, info);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canProcess(@NotNull String fieldOwner) {
|
||||
public boolean canProcess(@NotNull String fieldOwner, boolean forTransformation) {
|
||||
return fieldOwner.equals(getLambdaInternalName());
|
||||
}
|
||||
|
||||
@@ -79,7 +73,7 @@ public class FieldRemapper {
|
||||
if (transformed == null) {
|
||||
//if parent couldn't transform
|
||||
FieldInsnNode insnNode = (FieldInsnNode) capturedFieldAccess.get(currentInstruction);
|
||||
if (canProcess(insnNode.owner)) {
|
||||
if (canProcess(insnNode.owner, true)) {
|
||||
insnNode.name = "$$$" + insnNode.name;
|
||||
insnNode.setOpcode(Opcodes.GETSTATIC);
|
||||
|
||||
@@ -102,9 +96,9 @@ public class FieldRemapper {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CapturedParamInfo findField(@NotNull FieldInsnNode fieldInsnNode, @NotNull Collection<CapturedParamInfo> captured) {
|
||||
protected CapturedParamInfo findField(@NotNull FieldInsnNode fieldInsnNode, @NotNull Collection<CapturedParamInfo> captured) {
|
||||
for (CapturedParamInfo valueDescriptor : captured) {
|
||||
if (valueDescriptor.getFieldName().equals(fieldInsnNode.name) && fieldInsnNode.owner.equals(valueDescriptor.getContainingLambdaName())) {
|
||||
if (valueDescriptor.getOriginalFieldName().equals(fieldInsnNode.name) && fieldInsnNode.owner.equals(valueDescriptor.getContainingLambdaName())) {
|
||||
return valueDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ public class InlineCodegen implements ParentCodegenAware, CallGenerator {
|
||||
|
||||
VarRemapper.ParamRemapper remapper = new VarRemapper.ParamRemapper(parameters, initialFrameSize);
|
||||
|
||||
return inliner.doInline(codegen.v, remapper, new FieldRemapper(null, null, parameters));
|
||||
return inliner.doInline(codegen.v, remapper);
|
||||
}
|
||||
|
||||
private void generateClosuresBodies() {
|
||||
|
||||
@@ -34,13 +34,10 @@ public class InlinedLambdaRemapper extends FieldRemapper {
|
||||
|
||||
|
||||
@Override
|
||||
public void addCapturedFields(
|
||||
LambdaInfo lambdaInfo, ParametersBuilder builder
|
||||
) {
|
||||
parent.addCapturedFields(lambdaInfo, builder);
|
||||
public boolean canProcess(@NotNull String fieldOwner, boolean forTransformation) {
|
||||
return forTransformation ? super.canProcess(fieldOwner, forTransformation) : false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public CapturedParamInfo findField(
|
||||
@@ -50,13 +47,4 @@ public class InlinedLambdaRemapper extends FieldRemapper {
|
||||
return parent.findField(fieldInsnNode, captured);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldRemapper getParent() {
|
||||
return parent.getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRoot() {
|
||||
return parent.isRoot();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ public class LambdaInfo implements CapturedParamOwner {
|
||||
return Arrays.asList(types);
|
||||
}
|
||||
|
||||
public Parameters addAllParameters(@NotNull FieldRemapper remapper) {
|
||||
public Parameters addAllParameters() {
|
||||
ParametersBuilder builder = ParametersBuilder.newBuilder();
|
||||
//add skipped this cause inlined lambda doesn't have it
|
||||
builder.addThis(AsmTypeConstants.OBJECT_TYPE, true).setLambda(this);
|
||||
@@ -149,7 +149,9 @@ public class LambdaInfo implements CapturedParamOwner {
|
||||
builder.addNextParameter(type, false, null);
|
||||
}
|
||||
|
||||
remapper.addCapturedFields(this, builder);
|
||||
for (CapturedParamInfo info : getCapturedVars()) {
|
||||
builder.addCapturedParam(info, info.getOriginalFieldName());
|
||||
}
|
||||
|
||||
return builder.buildParameters();
|
||||
}
|
||||
|
||||
@@ -32,10 +32,7 @@ import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.asm4.Opcodes.ASM4;
|
||||
import static org.jetbrains.asm4.Opcodes.V1_6;
|
||||
@@ -64,6 +61,8 @@ public class LambdaTransformer {
|
||||
private String[] interfaces;
|
||||
private final boolean isSameModule;
|
||||
|
||||
private Map<String, List<String>> fieldNames = new HashMap<String, List<String>>();
|
||||
|
||||
public LambdaTransformer(String lambdaInternalName, InliningContext inliningContext, boolean isSameModule, Type newLambdaType) {
|
||||
this.isSameModule = isSameModule;
|
||||
this.state = inliningContext.state;
|
||||
@@ -133,7 +132,7 @@ public class LambdaTransformer {
|
||||
|
||||
MethodInliner inliner = new MethodInliner(invoke, parameters, inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")),
|
||||
remapper, isSameModule, "Transformer for " + invocation.getOwnerInternalName());
|
||||
InlineResult result = inliner.doInline(invokeVisitor, new VarRemapper.ParamRemapper(parameters, 0), remapper, false);
|
||||
InlineResult result = inliner.doInline(invokeVisitor, new VarRemapper.ParamRemapper(parameters, 0), false);
|
||||
invokeVisitor.visitMaxs(-1, -1);
|
||||
|
||||
generateConstructorAndFields(classBuilder, builder, invocation);
|
||||
@@ -163,7 +162,7 @@ public class LambdaTransformer {
|
||||
List<Pair<String, Type>> newConstructorSignature = new ArrayList<Pair<String, Type>>();
|
||||
for (CapturedParamInfo capturedParamInfo : infos) {
|
||||
if (capturedParamInfo.getLambda() == null) { //not inlined
|
||||
newConstructorSignature.add(new Pair<String, Type>(capturedParamInfo.getFieldName(), capturedParamInfo.getType()));
|
||||
newConstructorSignature.add(new Pair<String, Type>(capturedParamInfo.getNewFieldName(), capturedParamInfo.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +223,8 @@ public class LambdaTransformer {
|
||||
info.setLambda(lambdaInfo);
|
||||
capturedLambdas.add(lambdaInfo);
|
||||
}
|
||||
|
||||
addUniqueField(info.getOriginalFieldName());
|
||||
}
|
||||
cur = cur.getNext();
|
||||
}
|
||||
@@ -234,11 +235,11 @@ public class LambdaTransformer {
|
||||
List<CapturedParamInfo> allRecapturedParameters = new ArrayList<CapturedParamInfo>();
|
||||
for (LambdaInfo info : capturedLambdas) {
|
||||
for (CapturedParamInfo var : info.getCapturedVars()) {
|
||||
CapturedParamInfo recapturedParamInfo = builder.addCapturedParam(getNewFieldName(var.getFieldName()), var.getType(), var.isSkipped, var, info);
|
||||
CapturedParamInfo recapturedParamInfo = builder.addCapturedParam(var, getNewFieldName(var.getOriginalFieldName()));
|
||||
StackValue composed = StackValue.composed(StackValue.local(0, oldLambdaType),
|
||||
StackValue.field(var.getType(),
|
||||
oldLambdaType, /*TODO owner type*/
|
||||
getNewFieldName(var.getFieldName()), false)
|
||||
recapturedParamInfo.getNewFieldName(), false)
|
||||
);
|
||||
recapturedParamInfo.setRemapValue(composed);
|
||||
allRecapturedParameters.add(var);
|
||||
@@ -283,11 +284,25 @@ public class LambdaTransformer {
|
||||
return methodNode[0];
|
||||
}
|
||||
|
||||
public static String getNewFieldName(String oldName) {
|
||||
@NotNull
|
||||
public String getNewFieldName(@NotNull String oldName) {
|
||||
if (oldName.equals("this$0")) {
|
||||
//"this$0" couldn't clash and we should keep this name invariant for further transformations
|
||||
return oldName;
|
||||
}
|
||||
return oldName + "$inlined";
|
||||
return addUniqueField(oldName + "$inlined");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String addUniqueField(@NotNull String name) {
|
||||
List<String> existNames = fieldNames.get(name);
|
||||
if (existNames == null) {
|
||||
existNames = new LinkedList<String>();
|
||||
fieldNames.put(name, existNames);
|
||||
}
|
||||
String suffix = existNames.isEmpty() ? "" : "$" + existNames.size();
|
||||
String newName = name + suffix;
|
||||
existNames.add(newName);
|
||||
return newName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,19 +72,19 @@ public class MethodInliner {
|
||||
}
|
||||
|
||||
|
||||
public InlineResult doInline(MethodVisitor adapter, VarRemapper.ParamRemapper remapper, FieldRemapper capturedRemapper) {
|
||||
return doInline(adapter, remapper, capturedRemapper, true);
|
||||
public InlineResult doInline(MethodVisitor adapter, VarRemapper.ParamRemapper remapper) {
|
||||
return doInline(adapter, remapper, true);
|
||||
}
|
||||
|
||||
public InlineResult doInline(
|
||||
MethodVisitor adapter,
|
||||
VarRemapper.ParamRemapper remapper,
|
||||
FieldRemapper capturedRemapper, boolean remapReturn
|
||||
boolean remapReturn
|
||||
) {
|
||||
//analyze body
|
||||
MethodNode transformedNode = markPlacesForInlineAndRemoveInlinable(node);
|
||||
|
||||
transformedNode = doInline(transformedNode, capturedRemapper);
|
||||
transformedNode = doInline(transformedNode);
|
||||
removeClosureAssertions(transformedNode);
|
||||
transformedNode.instructions.resetLabels();
|
||||
|
||||
@@ -102,7 +102,7 @@ public class MethodInliner {
|
||||
return result;
|
||||
}
|
||||
|
||||
private MethodNode doInline(MethodNode node, final FieldRemapper capturedRemapper) {
|
||||
private MethodNode doInline(MethodNode node) {
|
||||
|
||||
final Deque<InvokeCall> currentInvokes = new LinkedList<InvokeCall>(invokeCalls);
|
||||
|
||||
@@ -129,7 +129,7 @@ public class MethodInliner {
|
||||
inliningContext.subInline(inliningContext.nameGenerator, currentTypeMapping).classRegeneration(),
|
||||
isSameModule, newLambdaType);
|
||||
|
||||
InlineResult transformResult = transformer.doTransform(invocation, capturedRemapper);
|
||||
InlineResult transformResult = transformer.doTransform(invocation, nodeRemapper);
|
||||
result.addAllClassesToRemove(transformResult);
|
||||
|
||||
if (inliningContext.isInliningLambda) {
|
||||
@@ -159,22 +159,19 @@ public class MethodInliner {
|
||||
int valueParamShift = getNextLocalIndex();//NB: don't inline cause it changes
|
||||
putStackValuesIntoLocals(info.getParamsWithoutCapturedValOrVar(), valueParamShift, this, desc);
|
||||
|
||||
Parameters lambdaParameters = info.addAllParameters(capturedRemapper);
|
||||
Parameters lambdaParameters = info.addAllParameters();
|
||||
|
||||
InlinedLambdaRemapper newCapturedRemapper =
|
||||
new InlinedLambdaRemapper(info.getLambdaClassType().getInternalName(), capturedRemapper, lambdaParameters);
|
||||
|
||||
FieldRemapper fieldRemapper =
|
||||
new FieldRemapper(info.getLambdaClassType().getInternalName(), capturedRemapper, lambdaParameters);
|
||||
new InlinedLambdaRemapper(info.getLambdaClassType().getInternalName(), nodeRemapper, lambdaParameters);
|
||||
|
||||
setInlining(true);
|
||||
MethodInliner inliner = new MethodInliner(info.getNode(), lambdaParameters,
|
||||
inliningContext.subInlineLambda(info),
|
||||
fieldRemapper, true /*cause all calls in same module as lambda*/,
|
||||
newCapturedRemapper, true /*cause all calls in same module as lambda*/,
|
||||
"Lambda inlining " + info.getLambdaClassType().getInternalName());
|
||||
|
||||
VarRemapper.ParamRemapper remapper = new VarRemapper.ParamRemapper(lambdaParameters, valueParamShift);
|
||||
InlineResult lambdaResult = inliner.doInline(this.mv, remapper, newCapturedRemapper);//TODO add skipped this and receiver
|
||||
InlineResult lambdaResult = inliner.doInline(this.mv, remapper);//TODO add skipped this and receiver
|
||||
result.addAllClassesToRemove(lambdaResult);
|
||||
|
||||
//return value boxing/unboxing
|
||||
@@ -188,7 +185,7 @@ public class MethodInliner {
|
||||
if (invocation.shouldRegenerate()) {
|
||||
//put additional captured parameters on stack
|
||||
for (CapturedParamInfo capturedParamInfo : invocation.getAllRecapturedParameters()) {
|
||||
visitFieldInsn(Opcodes.GETSTATIC, capturedParamInfo.getContainingLambdaName(), "$$$" + capturedParamInfo.getFieldName(), capturedParamInfo.getType().getDescriptor());
|
||||
visitFieldInsn(Opcodes.GETSTATIC, capturedParamInfo.getContainingLambdaName(), "$$$" + capturedParamInfo.getOriginalFieldName(), capturedParamInfo.getType().getDescriptor());
|
||||
}
|
||||
super.visitMethodInsn(opcode, invocation.getNewLambdaType().getInternalName(), name, invocation.getNewConstructorDescriptor());
|
||||
invocation = null;
|
||||
|
||||
@@ -42,20 +42,23 @@ public class ParametersBuilder {
|
||||
return info;
|
||||
}
|
||||
|
||||
public ParametersBuilder addNextParameter(Type type, boolean skipped, @Nullable ParameterInfo original) {
|
||||
@NotNull
|
||||
public ParametersBuilder addNextParameter(@NotNull Type type, boolean skipped, @Nullable ParameterInfo original) {
|
||||
addParameter(new ParameterInfo(type, skipped, nextIndex, original != null ? original.getIndex() : -1));
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CapturedParamInfo addCapturedParam(
|
||||
@NotNull CapturedParamInfo param,
|
||||
@Nullable CapturedParamInfo originalField
|
||||
@NotNull CapturedParamInfo original,
|
||||
@NotNull String newFieldName
|
||||
) {
|
||||
CapturedParamInfo info = new CapturedParamInfo(param.desc, param.isSkipped, nextCaptured, originalField != null ? originalField.getIndex() : -1);
|
||||
info.setLambda(param.getLambda());
|
||||
CapturedParamInfo info = new CapturedParamInfo(original.desc, newFieldName, original.isSkipped, nextCaptured, original.getIndex());
|
||||
info.setLambda(original.getLambda());
|
||||
return addCapturedParameter(info);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CapturedParamInfo addCapturedParam(
|
||||
@NotNull String fieldName,
|
||||
@NotNull Type type,
|
||||
|
||||
+7
-48
@@ -24,7 +24,6 @@ import org.jetbrains.asm4.tree.FieldInsnNode;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
|
||||
@@ -52,35 +51,8 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCapturedFields(LambdaInfo lambdaInfo, ParametersBuilder builder) {
|
||||
if (canProcess(lambdaInfo.getLambdaClassType().getInternalName())) {
|
||||
List<CapturedParamInfo> captured = parameters.getCaptured();
|
||||
for (CapturedParamInfo originalField : lambdaInfo.getCapturedVars()) {
|
||||
CapturedParamInfo foundField = null;
|
||||
for (CapturedParamInfo capturedParamInfo : captured) {
|
||||
if (capturedParamInfo.getContainingLambdaName().equals(originalField.getContainingLambdaName())) {
|
||||
if (capturedParamInfo.getFieldName().equals(LambdaTransformer.getNewFieldName(originalField.getFieldName()))) {
|
||||
foundField = originalField;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundField == null) {
|
||||
throw new IllegalStateException("Captured parameter should exists in outer context: " + originalField.getFieldName());
|
||||
}
|
||||
|
||||
builder.addCapturedParam(foundField, foundField);
|
||||
}
|
||||
} else {
|
||||
//in case when inlining lambda into another one inside inline function
|
||||
parent.addCapturedFields(lambdaInfo, builder);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess(@NotNull String fieldOwner) {
|
||||
return super.canProcess(fieldOwner) || isRecapturedLambdaType(fieldOwner);
|
||||
public boolean canProcess(@NotNull String fieldOwner, boolean forTransformation) {
|
||||
return super.canProcess(fieldOwner, forTransformation) || isRecapturedLambdaType(fieldOwner);
|
||||
}
|
||||
|
||||
private boolean isRecapturedLambdaType(String owner) {
|
||||
@@ -90,27 +62,17 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
|
||||
@Nullable
|
||||
@Override
|
||||
public CapturedParamInfo findField(@NotNull FieldInsnNode fieldInsnNode, @NotNull Collection<CapturedParamInfo> captured) {
|
||||
boolean searchInParent = !canProcess(fieldInsnNode.owner);
|
||||
boolean searchInParent = !canProcess(fieldInsnNode.owner, false);
|
||||
if (searchInParent) {
|
||||
return parent.findField(fieldInsnNode);
|
||||
} else if (isRecapturedLambdaType(fieldInsnNode.owner)) {
|
||||
LambdaInfo info = recapturedLambdas.get(fieldInsnNode.owner);
|
||||
return super.findField(fieldInsnNode, info.getCapturedVars());
|
||||
}
|
||||
else {
|
||||
return super.findField(fieldInsnNode, captured);
|
||||
} else {
|
||||
return findFieldInMyCaptured(fieldInsnNode);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CapturedParamInfo findFieldInMyCaptured(@NotNull FieldInsnNode fieldInsnNode) {
|
||||
if (isRecapturedLambdaType(fieldInsnNode.owner)) {
|
||||
LambdaInfo info = recapturedLambdas.get(fieldInsnNode.owner);
|
||||
return super.findField(fieldInsnNode, info.getCapturedVars());
|
||||
}
|
||||
else {
|
||||
return super.findField(fieldInsnNode, parameters.getCaptured());
|
||||
}
|
||||
return super.findField(fieldInsnNode, parameters.getCaptured());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -129,14 +91,11 @@ public class RegeneratedLambdaFieldRemapper extends FieldRemapper {
|
||||
}
|
||||
}
|
||||
|
||||
String newName = field.getContainingLambdaName().equals(getLambdaInternalName())
|
||||
? field.getFieldName()
|
||||
: LambdaTransformer.getNewFieldName(field.getFieldName());
|
||||
StackValue result =
|
||||
StackValue.composed(prefix == null ? StackValue.local(0, Type.getObjectType(getLambdaInternalName())) : prefix,
|
||||
StackValue.field(field.getType(),
|
||||
Type.getObjectType(newOwnerType), /*TODO owner type*/
|
||||
newName, false)
|
||||
field.getNewFieldName(), false)
|
||||
);
|
||||
|
||||
return searchInParent ? parent.getFieldForInline(node, result) : result;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import test.*
|
||||
|
||||
fun testSameCaptured() : String {
|
||||
var result = 0;
|
||||
result = doWork({result+=1; result}, {result += 11; result})
|
||||
return if (result == 12) "OK" else "fail ${result}"
|
||||
}
|
||||
|
||||
inline fun testSameCaptured(lambdaWithResultCaptured: () -> Unit) : String {
|
||||
var result = 1;
|
||||
result = doWork({result+=11; lambdaWithResultCaptured(); result})
|
||||
return if (result == 12) "OK" else "fail ${result}"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
if (testSameCaptured() != "OK") return "test1 : ${testSameCaptured()}"
|
||||
|
||||
var result = 0;
|
||||
if (testSameCaptured{result += 1111} != "OK") return "test2 : ${testSameCaptured{result = 1111}}"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package test
|
||||
|
||||
inline fun <R> doWork(job: ()-> R) : R {
|
||||
val k = 10;
|
||||
return notInline({k; job()})
|
||||
}
|
||||
|
||||
inline fun <R> doWork(job: ()-> R, job2: () -> R) : R {
|
||||
val k = 10;
|
||||
return notInline({k; job(); job2()})
|
||||
}
|
||||
|
||||
fun <R> notInline(job: ()-> R) : R {
|
||||
return job()
|
||||
}
|
||||
|
||||
+5
@@ -176,6 +176,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxCodegenT
|
||||
doTestMultiFile("compiler/testData/codegen/boxInline/rootConstructor");
|
||||
}
|
||||
|
||||
@TestMetadata("sameCaptured")
|
||||
public void testSameCaptured() throws Exception {
|
||||
doTestMultiFile("compiler/testData/codegen/boxInline/sameCaptured");
|
||||
}
|
||||
|
||||
@TestMetadata("severalClosures")
|
||||
public void testSeveralClosures() throws Exception {
|
||||
doTestMultiFile("compiler/testData/codegen/boxInline/severalClosures");
|
||||
|
||||
+5
@@ -176,6 +176,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
doBoxTest("compiler/testData/codegen/boxInline/rootConstructor");
|
||||
}
|
||||
|
||||
@TestMetadata("sameCaptured")
|
||||
public void testSameCaptured() throws Exception {
|
||||
doBoxTest("compiler/testData/codegen/boxInline/sameCaptured");
|
||||
}
|
||||
|
||||
@TestMetadata("severalClosures")
|
||||
public void testSeveralClosures() throws Exception {
|
||||
doBoxTest("compiler/testData/codegen/boxInline/severalClosures");
|
||||
|
||||
Reference in New Issue
Block a user