KT-5076 Error on inlining into object

#KT-5076 Fixed
This commit is contained in:
Mikhael Bogdanov
2014-05-23 11:17:42 +04:00
parent 0bd482d271
commit 950840b8c7
4 changed files with 59 additions and 21 deletions
@@ -146,7 +146,8 @@ public class AnonymousObjectTransformer {
ParametersBuilder allCapturedParamBuilder = ParametersBuilder.newBuilder();
ParametersBuilder constructorParamBuilder = ParametersBuilder.newBuilder();
extractParametersMappingAndPatchConstructor(constructor, allCapturedParamBuilder, constructorParamBuilder, invocation);
List<CapturedParamInfo> additionalFakeParams =
extractParametersMappingAndPatchConstructor(constructor, allCapturedParamBuilder, constructorParamBuilder, invocation);
InlineResult result = InlineResult.create();
for (MethodNode next : methodsToTransform) {
@@ -156,7 +157,7 @@ public class AnonymousObjectTransformer {
}
InlineResult constructorResult =
generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, invocation, parentRemapper);
generateConstructorAndFields(classBuilder, allCapturedParamBuilder, constructorParamBuilder, invocation, parentRemapper, additionalFakeParams);
result.addAllClassesToRemove(constructorResult);
@@ -194,7 +195,8 @@ public class AnonymousObjectTransformer {
@NotNull ParametersBuilder allCapturedBuilder,
@NotNull ParametersBuilder constructorInlineBuilder,
@NotNull ConstructorInvocation invocation,
@NotNull FieldRemapper parentRemapper
@NotNull FieldRemapper parentRemapper,
@NotNull List<CapturedParamInfo> constructorAdditionalFakeParams
) {
List<Type> descTypes = new ArrayList<Type>();
@@ -242,6 +244,23 @@ public class AnonymousObjectTransformer {
}
//then transform constructor
//HACK: in inlinining into constructor we access original captured fields with field access not local var
//but this fields added to general params (this assumes local var access) not captured one,
//so we need to add them to captured params
for (CapturedParamInfo info : constructorAdditionalFakeParams) {
CapturedParamInfo fake = constructorInlineBuilder.addCapturedParamCopy(info);
if (fake.getLambda() != null) {
//set remap value to skip this fake (captured with lambda already skipped)
StackValue composed = StackValue.composed(StackValue.local(0, oldObjectType),
StackValue.field(fake.getType(),
oldObjectType,
fake.getNewFieldName(), false)
);
fake.setRemapValue(composed);
}
}
Parameters constructorParameters = constructorInlineBuilder.buildParameters();
RegeneratedLambdaFieldRemapper remapper =
@@ -291,7 +310,7 @@ public class AnonymousObjectTransformer {
);
}
private void extractParametersMappingAndPatchConstructor(
private List<CapturedParamInfo> extractParametersMappingAndPatchConstructor(
@NotNull MethodNode constructor,
@NotNull ParametersBuilder capturedParamBuilder,
@NotNull ParametersBuilder constructorParamBuilder,
@@ -306,7 +325,7 @@ public class AnonymousObjectTransformer {
};
List<LambdaInfo> capturedLambdas = new ArrayList<LambdaInfo>(); //captured var of inlined parameter
List<CapturedParamInfo> capturedToInline = new ArrayList<CapturedParamInfo>();
List<CapturedParamInfo> constructorAdditionalFakeParams = new ArrayList<CapturedParamInfo>();
Map<Integer, LambdaInfo> indexToLambda = invocation.getLambdasToInline();
Set<Integer> capturedParams = new HashSet<Integer>();
@@ -330,8 +349,8 @@ public class AnonymousObjectTransformer {
if (lambdaInfo != null) {
info.setLambda(lambdaInfo);
capturedLambdas.add(lambdaInfo);
capturedToInline.add(info);
}
constructorAdditionalFakeParams.add(info);
capturedParams.add(varIndex);
constructor.instructions.remove(previous.getPrevious());
@@ -381,14 +400,12 @@ public class AnonymousObjectTransformer {
capturedLambdasToInline.put(info.getLambdaClassType().getInternalName(), info);
}
//HACK: in inlinining into constructor we access inlined lambda with field access not local var but this lambda added no general params not captured one,
//so we need to add them to captured params
for (CapturedParamInfo info : capturedToInline) {
constructorParamBuilder.addCapturedParamCopy(info);
}
invocation.setAllRecapturedParameters(allRecapturedParameters);
invocation.setCapturedLambdasToInline(capturedLambdasToInline);
return constructorAdditionalFakeParams;
}
@NotNull
@@ -2,9 +2,13 @@ import test.*
fun box() : String {
val o = "O"
return doWork {
val p = "GOOD"
val result = doWork {
val k = "K"
val s = object : A<String>() {
val param = p;
override fun getO(): String {
return o;
}
@@ -14,7 +18,11 @@ fun box() : String {
}
}
s.getO() + s.getK()
s.getO() + s.getK() + s.param
}
if (result != "OKGOOD") return "fail $result"
return "OK"
}
@@ -3,9 +3,9 @@ import test.*
fun test1(): String {
val o = "O"
val result = doWork ({o}, {"K"})
val result = doWork ({o}, {"K"}, "GOOD")
return result.getO() + result.getK()
return result.getO() + result.getK() + result.getParam()
}
fun test2() : String {
@@ -13,17 +13,17 @@ fun test2() : String {
val o1 = "O"
val k1 = "K"
val result = doWorkInConstructor ({o1}, {k1})
val result = doWorkInConstructor ({o1}, {k1}, "GOOD")
return result.getO() + result.getK()
return result.getO() + result.getK() + result.getParam()
}
fun box() : String {
val result1 = test1();
if (result1 != "OK") return "fail1 $result1"
if (result1 != "OKGOOD") return "fail1 $result1"
val result2 = test2();
if (result2 != "OK") return "fail2 $result2"
if (result2 != "OKGOOD") return "fail2 $result2"
return "OK"
}
@@ -4,9 +4,11 @@ abstract class A<R> {
abstract fun getO() : R
abstract fun getK() : R
abstract fun getParam() : R
}
inline fun <R> doWork(jobO: ()-> R, jobK: ()-> R) : A<R> {
inline fun <R> doWork(jobO: ()-> R, jobK: ()-> R, param: R) : A<R> {
val s = object : A<R>() {
override fun getO(): R {
@@ -15,12 +17,19 @@ inline fun <R> doWork(jobO: ()-> R, jobK: ()-> R) : A<R> {
override fun getK(): R {
return jobK()
}
override fun getParam(): R {
return param
}
}
return s;
}
inline fun <R> doWorkInConstructor(jobO: ()-> R, jobK: ()-> R) : A<R> {
inline fun <R> doWorkInConstructor(jobO: ()-> R, jobK: ()-> R, param: R) : A<R> {
val s = object : A<R>() {
val p = param;
val o1 = jobO()
val k1 = jobK()
@@ -31,6 +40,10 @@ inline fun <R> doWorkInConstructor(jobO: ()-> R, jobK: ()-> R) : A<R> {
override fun getK(): R {
return k1
}
override fun getParam(): R {
return p
}
}
return s;
}