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:
Michael Bogdanov
2014-10-06 17:09:45 +04:00
parent 989cae9f1f
commit d0d207f387
4 changed files with 33 additions and 5 deletions
@@ -25,6 +25,7 @@ import com.intellij.util.containers.ContainerUtil;
import kotlin.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.binding.CodegenBinding;
import org.jetbrains.jet.codegen.bridges.Bridge;
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.lang.descriptors.*;
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.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
@@ -514,9 +516,10 @@ public class FunctionCodegen extends ParentCodegenAware {
@NotNull GenerationState state,
@NotNull CallableMethod method,
@NotNull ConstructorDescriptor constructorDescriptor,
@NotNull ClassBuilder classBuilder
@NotNull ClassBuilder classBuilder,
@NotNull JetClassOrObject classOrObject
) {
if (!isDefaultConstructorNeeded(state.getBindingContext(), constructorDescriptor)) {
if (!isEmptyConstructorNeeded(state.getBindingContext(), constructorDescriptor, classOrObject)) {
return;
}
int flags = getVisibilityAccessFlag(constructorDescriptor);
@@ -550,7 +553,7 @@ public class FunctionCodegen extends ParentCodegenAware {
String desc = JetTypeMapper.getDefaultDescriptor(method.getAsmMethod(), false);
v.invokespecial(methodOwner.getInternalName(), "<init>", desc, false);
v.areturn(Type.VOID_TYPE);
endVisit(mv, "default constructor for " + methodOwner.getInternalName(), null);
endVisit(mv, "default constructor for " + methodOwner.getInternalName(), classOrObject);
}
void generateDefaultIfNeeded(
@@ -739,9 +742,15 @@ public class FunctionCodegen extends ParentCodegenAware {
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();
if (classOrObject.isLocal()) return false;
if (CodegenBinding.canHaveOuter(context, classDescriptor)) return false;
if (classDescriptor.getVisibility() == Visibilities.PRIVATE ||
@@ -1151,7 +1151,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
DefaultParameterValueLoader.DEFAULT, null);
CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor);
FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v);
FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v, myClass);
if (isClassObject(descriptor)) {
context.recordSyntheticAccessorIfNeeded(constructorDescriptor, bindingContext);