diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java index e73a1aec5fd..4f43789ef85 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java @@ -35,6 +35,7 @@ import org.jetbrains.org.objectweb.asm.tree.VarInsnNode; import java.util.*; +import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.isThis0; import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN; public class AnonymousObjectTransformer { @@ -399,7 +400,8 @@ public class AnonymousObjectTransformer { while (cur != null) { if (cur instanceof FieldInsnNode) { FieldInsnNode fieldNode = (FieldInsnNode) cur; - if (fieldNode.getOpcode() == Opcodes.PUTFIELD && InlineCodegenUtil.isCapturedFieldName(fieldNode.name)) { + String fieldName = fieldNode.name; + if (fieldNode.getOpcode() == Opcodes.PUTFIELD && InlineCodegenUtil.isCapturedFieldName(fieldName)) { boolean isPrevVarNode = fieldNode.getPrevious() instanceof VarInsnNode; boolean isPrevPrevVarNode = isPrevVarNode && fieldNode.getPrevious().getPrevious() instanceof VarInsnNode; @@ -410,7 +412,8 @@ public class AnonymousObjectTransformer { VarInsnNode previous = (VarInsnNode) fieldNode.getPrevious(); int varIndex = previous.var; LambdaInfo lambdaInfo = indexToLambda.get(varIndex); - CapturedParamInfo info = capturedParamBuilder.addCapturedParam(owner, fieldNode.name, Type.getType(fieldNode.desc), lambdaInfo != null, null); + String newFieldName = isThis0(fieldName) && shouldRenameThis0(parentFieldRemapper, indexToLambda.values()) ? getNewFieldName(fieldName, true) : fieldName; + CapturedParamInfo info = capturedParamBuilder.addCapturedParam(owner, fieldName, newFieldName, Type.getType(fieldNode.desc), lambdaInfo != null, null); if (lambdaInfo != null) { info.setLambda(lambdaInfo); capturedLambdas.add(lambdaInfo); @@ -459,7 +462,7 @@ public class AnonymousObjectTransformer { for (LambdaInfo info : capturedLambdas) { if (addCapturedNotAddOuter) { for (CapturedParamDesc desc : info.getCapturedVars()) { - CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, getNewFieldName(desc.getFieldName())); + CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, getNewFieldName(desc.getFieldName(), false)); StackValue composed = StackValue.field(desc.getType(), oldObjectType, /*TODO owner type*/ recapturedParamInfo.getNewFieldName(), @@ -486,7 +489,7 @@ public class AnonymousObjectTransformer { return ownerType; } }, InlineCodegenUtil.THIS, ownerType); - CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, InlineCodegenUtil.THIS$0); + CapturedParamInfo recapturedParamInfo = capturedParamBuilder.addCapturedParam(desc, InlineCodegenUtil.THIS$0/*outer lambda/object*/); StackValue composed = StackValue.LOCAL_0; recapturedParamInfo.setRemapValue(composed); allRecapturedParameters.add(desc); @@ -494,19 +497,34 @@ public class AnonymousObjectTransformer { constructorParamBuilder.addCapturedParam(recapturedParamInfo, recapturedParamInfo.getNewFieldName()).setRemapValue(composed); } - - anonymousObjectGen.setAllRecapturedParameters(allRecapturedParameters); anonymousObjectGen.setCapturedLambdasToInline(capturedLambdasToInline); return constructorAdditionalFakeParams; } + private static boolean shouldRenameThis0(@NotNull FieldRemapper parentFieldRemapper, Collection values) { + if (isFirstDeclSiteLambdaFieldRemapper(parentFieldRemapper)) { + for (LambdaInfo value : values) { + for (CapturedParamDesc desc : value.getCapturedVars()) { + if (isThis0(desc.getFieldName())) { + return true; + } + } + } + } + return false; + } + @NotNull - public String getNewFieldName(@NotNull String oldName) { + public String getNewFieldName(@NotNull String oldName, boolean originalField) { if (InlineCodegenUtil.THIS$0.equals(oldName)) { - //"this$0" couldn't clash and we should keep this name invariant for further transformations - return oldName; + if (!originalField) { + return oldName; + } else { + //rename original 'this$0' in declaration site lambda (inside inline function) to use this$0 only for outer lambda/object access on call site + return addUniqueField(oldName + InlineCodegenUtil.INLINE_FUN_THIS_0_SUFFIX); + } } return addUniqueField(oldName + InlineCodegenUtil.INLINE_TRANSFORMATION_SUFFIX); } @@ -523,4 +541,8 @@ public class AnonymousObjectTransformer { existNames.add(newName); return newName; } + + private static boolean isFirstDeclSiteLambdaFieldRemapper(FieldRemapper parentRemapper) { + return !(parentRemapper instanceof RegeneratedLambdaFieldRemapper) && !(parentRemapper instanceof InlinedLambdaRemapper); + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java index ec4f58b8a8d..b34e5f7a2ad 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java @@ -73,6 +73,7 @@ public class InlineCodegenUtil { public static final String INLINE_MARKER_FINALLY_START = "finallyStart"; public static final String INLINE_MARKER_FINALLY_END = "finallyEnd"; public static final String INLINE_TRANSFORMATION_SUFFIX = "$inlined"; + public static final String INLINE_FUN_THIS_0_SUFFIX = "$inline_fun"; @Nullable public static SMAPAndMethodNode getMethodNode( @@ -487,4 +488,8 @@ public class InlineCodegenUtil { public static boolean isFakeLocalVariableForInline(@NotNull String name) { return name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION) || name.startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT); } + + public static boolean isThis0(String name) { + return THIS$0.equals(name); + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt index 53768f8531d..44d2ffb5f54 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ParametersBuilder.kt @@ -77,10 +77,11 @@ internal class ParametersBuilder private constructor(){ fun addCapturedParam( containingLambda: CapturedParamOwner, fieldName: String, + newFieldName: String, type: Type, skipped: Boolean, original: ParameterInfo?): CapturedParamInfo { - val info = CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), skipped, nextCapturedIndex(), + val info = CapturedParamInfo(CapturedParamDesc.createDesc(containingLambda, fieldName, type), newFieldName, skipped, nextCapturedIndex(), if (original != null) original.getIndex() else -1) if (original != null) { info.setLambda(original.getLambda())