Correctly map declaration owner in JVM codegen

"context.contextKind()" was incorrect in
ExpressionCodegen.intermediateValueForProperty(), because it represents the
context of the call site, not the context of the property declaration

 #KT-4878 Fixed
This commit is contained in:
Alexander Udalov
2014-04-18 20:37:06 +04:00
parent fbf9f5f7d0
commit d913dfb1aa
9 changed files with 57 additions and 38 deletions
@@ -27,11 +27,6 @@ import com.intellij.util.Function;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.commons.Method;
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.binding.CodegenBinding;
import org.jetbrains.jet.codegen.binding.MutableClosure;
@@ -63,10 +58,14 @@ import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.renderer.DescriptorRenderer;
import org.jetbrains.org.objectweb.asm.Label;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import org.jetbrains.org.objectweb.asm.commons.Method;
import java.util.*;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
import static org.jetbrains.jet.codegen.FunctionTypesUtil.functionTypeToImpl;
@@ -78,6 +77,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedIn
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implements LocalLookup, ParentCodegenAware {
private static final Set<DeclarationDescriptor> INTEGRAL_RANGES = KotlinBuiltIns.getInstance().getIntegralRanges();
@@ -1803,8 +1803,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@Nullable JetSuperExpression superExpression,
@NotNull MethodKind methodKind
) {
JetTypeMapper typeMapper = state.getTypeMapper();
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
@@ -1812,10 +1810,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
boolean isSuper = superExpression != null;
boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
JetType delegateType = getPropertyDelegateType(propertyDescriptor, state.getBindingContext());
JetType delegateType = getPropertyDelegateType(propertyDescriptor, bindingContext);
boolean isDelegatedProperty = delegateType != null;
CallableMethod callableGetter = null;
CallableMethod callableSetter = null;
@@ -1841,7 +1838,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
else {
if (isSuper && !isInterface(containingDeclaration)) {
ClassDescriptor owner = getSuperCallLabelTarget(superExpression, state.getBindingContext(), context);
ClassDescriptor owner = getSuperCallLabelTarget(superExpression, bindingContext, context);
CodegenContext c = context.findParentContextWithDescriptor(owner);
assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor;
if (c != context.getParentContext()) {
@@ -1875,8 +1872,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
propertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor);
if (callableMethod == null) {
owner = typeMapper.getOwner(isBackingFieldInAnotherClass ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor,
context.getContextKind(), isCallInsideSameModuleAsDeclared(propertyDescriptor, context));
owner = typeMapper.mapOwner(isBackingFieldInAnotherClass ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor,
isCallInsideSameModuleAsDeclared(propertyDescriptor, context));
}
else {
owner = callableMethod.getOwner();
@@ -555,16 +555,16 @@ public class FunctionCodegen extends ParentCodegenAwareImpl {
Type ownerType;
if (contextClass instanceof PackageFragmentDescriptor) {
ownerType = state.getTypeMapper().getOwner(functionDescriptor, kind, true);
ownerType = typeMapper.mapOwner(functionDescriptor, true);
}
else if (contextClass instanceof ClassDescriptor) {
ownerType = state.getTypeMapper().mapClass((ClassDescriptor) contextClass);
ownerType = typeMapper.mapClass((ClassDescriptor) contextClass);
}
else if (isLocalNamedFun(functionDescriptor)) {
ownerType = asmTypeForAnonymousClass(state.getBindingContext(), functionDescriptor);
ownerType = asmTypeForAnonymousClass(bindingContext, functionDescriptor);
}
else {
throw new IllegalStateException("Couldn't obtain owner name for " + functionDescriptor);
throw new IllegalStateException("Couldn't obtain owner type for " + functionDescriptor);
}
String descriptor = jvmSignature.getDescriptor().replace(")", "I)");
@@ -19,7 +19,6 @@ package org.jetbrains.jet.codegen.state;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.codegen.binding.BindingTraceAware;
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
@@ -47,11 +46,11 @@ import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
import static org.jetbrains.jet.codegen.AsmUtil.getTraitImplThisParameterType;
import static org.jetbrains.jet.codegen.CodegenUtil.*;
@@ -59,6 +58,7 @@ import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.isVarCapturedInClosure;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class JetTypeMapper extends BindingTraceAware {
@@ -90,20 +90,19 @@ public class JetTypeMapper extends BindingTraceAware {
}
@NotNull
public Type getOwner(@NotNull DeclarationDescriptor descriptor, @NotNull OwnerKind kind, boolean isInsideModule) {
public Type mapOwner(@NotNull DeclarationDescriptor descriptor, boolean isInsideModule) {
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (containingDeclaration instanceof PackageFragmentDescriptor) {
return asmTypeForPackage((PackageFragmentDescriptor) containingDeclaration, descriptor, isInsideModule);
}
else if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
return kind == OwnerKind.TRAIT_IMPL ? mapTraitImpl(classDescriptor) : mapClass(classDescriptor);
return mapClass((ClassDescriptor) containingDeclaration);
}
else if (containingDeclaration instanceof ScriptDescriptor) {
return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) containingDeclaration);
}
else {
throw new UnsupportedOperationException("don't know how to generate owner for parent " + containingDeclaration);
throw new UnsupportedOperationException("Don't know how to map owner for " + descriptor);
}
}
@@ -1,10 +0,0 @@
class MyWrongClass : FieldAccess() {
}
fun box() : String {
val clazz = MyWrongClass()
clazz.fieldO = "O"
FieldAccess.fieldK = "K"
return clazz.fieldO!! + FieldAccess.fieldK!!
}
@@ -0,0 +1,3 @@
public class fieldAccessFromExtensionInTraitImpl {
public final String result = "OK";
}
@@ -0,0 +1,13 @@
// KT-4878
import fieldAccessFromExtensionInTraitImpl as D
trait T {
fun Int.foo(d: D) = d.result!!
}
class A : T {
fun bar() = 42.foo(D())
}
fun box() = A().bar()
@@ -1,5 +1,5 @@
class FieldAccess {
class fieldAccessViaSubclass {
public String fieldO;
public static String fieldK;
}
}
@@ -0,0 +1,12 @@
// KT-3492
class MyWrongClass : fieldAccessViaSubclass() {
}
fun box() : String {
val clazz = MyWrongClass()
clazz.fieldO = "O"
fieldAccessViaSubclass.fieldK = "K"
return clazz.fieldO!! + fieldAccessViaSubclass.fieldK!!
}
@@ -214,9 +214,14 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/codegen/boxWithJava/property"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("FieldAccess.kt")
public void testFieldAccess() throws Exception {
doTestWithJava("compiler/testData/codegen/boxWithJava/property/FieldAccess.kt");
@TestMetadata("fieldAccessFromExtensionInTraitImpl.kt")
public void testFieldAccessFromExtensionInTraitImpl() throws Exception {
doTestWithJava("compiler/testData/codegen/boxWithJava/property/fieldAccessFromExtensionInTraitImpl.kt");
}
@TestMetadata("fieldAccessViaSubclass.kt")
public void testFieldAccessViaSubclass() throws Exception {
doTestWithJava("compiler/testData/codegen/boxWithJava/property/fieldAccessViaSubclass.kt");
}
}