Fix for KT-3584: Wrong bytecode generated for local class with default parameters and captured local val
#KT-3584 Fixed
This commit is contained in:
@@ -25,6 +25,7 @@ import com.intellij.util.containers.ContainerUtil;
|
|||||||
import kotlin.Function1;
|
import kotlin.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
||||||
import org.jetbrains.jet.codegen.binding.CodegenBinding;
|
import org.jetbrains.jet.codegen.binding.CodegenBinding;
|
||||||
import org.jetbrains.jet.codegen.bridges.Bridge;
|
import org.jetbrains.jet.codegen.bridges.Bridge;
|
||||||
import org.jetbrains.jet.codegen.bridges.BridgesPackage;
|
import org.jetbrains.jet.codegen.bridges.BridgesPackage;
|
||||||
@@ -36,6 +37,7 @@ import org.jetbrains.jet.codegen.state.GenerationState;
|
|||||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
@@ -514,9 +516,10 @@ public class FunctionCodegen extends ParentCodegenAware {
|
|||||||
@NotNull GenerationState state,
|
@NotNull GenerationState state,
|
||||||
@NotNull CallableMethod method,
|
@NotNull CallableMethod method,
|
||||||
@NotNull ConstructorDescriptor constructorDescriptor,
|
@NotNull ConstructorDescriptor constructorDescriptor,
|
||||||
@NotNull ClassBuilder classBuilder
|
@NotNull ClassBuilder classBuilder,
|
||||||
|
@NotNull JetClassOrObject classOrObject
|
||||||
) {
|
) {
|
||||||
if (!isDefaultConstructorNeeded(state.getBindingContext(), constructorDescriptor)) {
|
if (!isEmptyConstructorNeeded(state.getBindingContext(), constructorDescriptor, classOrObject)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int flags = getVisibilityAccessFlag(constructorDescriptor);
|
int flags = getVisibilityAccessFlag(constructorDescriptor);
|
||||||
@@ -550,7 +553,7 @@ public class FunctionCodegen extends ParentCodegenAware {
|
|||||||
String desc = JetTypeMapper.getDefaultDescriptor(method.getAsmMethod(), false);
|
String desc = JetTypeMapper.getDefaultDescriptor(method.getAsmMethod(), false);
|
||||||
v.invokespecial(methodOwner.getInternalName(), "<init>", desc, false);
|
v.invokespecial(methodOwner.getInternalName(), "<init>", desc, false);
|
||||||
v.areturn(Type.VOID_TYPE);
|
v.areturn(Type.VOID_TYPE);
|
||||||
endVisit(mv, "default constructor for " + methodOwner.getInternalName(), null);
|
endVisit(mv, "default constructor for " + methodOwner.getInternalName(), classOrObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
void generateDefaultIfNeeded(
|
void generateDefaultIfNeeded(
|
||||||
@@ -739,9 +742,15 @@ public class FunctionCodegen extends ParentCodegenAware {
|
|||||||
return needed;
|
return needed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isDefaultConstructorNeeded(@NotNull BindingContext context, @NotNull ConstructorDescriptor constructorDescriptor) {
|
private static boolean isEmptyConstructorNeeded(
|
||||||
|
@NotNull BindingContext context,
|
||||||
|
@NotNull ConstructorDescriptor constructorDescriptor,
|
||||||
|
@NotNull JetClassOrObject classOrObject
|
||||||
|
) {
|
||||||
ClassDescriptor classDescriptor = constructorDescriptor.getContainingDeclaration();
|
ClassDescriptor classDescriptor = constructorDescriptor.getContainingDeclaration();
|
||||||
|
|
||||||
|
if (classOrObject.isLocal()) return false;
|
||||||
|
|
||||||
if (CodegenBinding.canHaveOuter(context, classDescriptor)) return false;
|
if (CodegenBinding.canHaveOuter(context, classDescriptor)) return false;
|
||||||
|
|
||||||
if (classDescriptor.getVisibility() == Visibilities.PRIVATE ||
|
if (classDescriptor.getVisibility() == Visibilities.PRIVATE ||
|
||||||
|
|||||||
@@ -1151,7 +1151,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
DefaultParameterValueLoader.DEFAULT, null);
|
DefaultParameterValueLoader.DEFAULT, null);
|
||||||
|
|
||||||
CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor);
|
CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor);
|
||||||
FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v);
|
FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v, myClass);
|
||||||
|
|
||||||
if (isClassObject(descriptor)) {
|
if (isClassObject(descriptor)) {
|
||||||
context.recordSyntheticAccessorIfNeeded(constructorDescriptor, bindingContext);
|
context.recordSyntheticAccessorIfNeeded(constructorDescriptor, bindingContext);
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
fun box(): String {
|
||||||
|
val s = "captured";
|
||||||
|
|
||||||
|
class A(val param: String = "OK") {
|
||||||
|
val s2 = s + param
|
||||||
|
}
|
||||||
|
|
||||||
|
if (A().s2 != "capturedOK") return "fail 1: ${A().s2}"
|
||||||
|
|
||||||
|
if (A("Test").s2 != "capturedTest") return "fail 1: ${A("Test").s2}"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -4151,6 +4151,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt3584.kt")
|
||||||
|
public void testKt3584() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/kt3584.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("localClass.kt")
|
@TestMetadata("localClass.kt")
|
||||||
public void testLocalClass() throws Exception {
|
public void testLocalClass() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/localClass.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/localClasses/localClass.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user