KT-5076 Error on inlining into object
#KT-5076 Fixed
This commit is contained in:
+28
-11
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user