From 1fe9c291f13d691d225b22ed920533ebd3a453aa Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 10 Jul 2012 21:20:53 +0200 Subject: [PATCH] ugly and incomplete solution for using correct bytecode instruction when accessing properties inherited from traits (KT-2391) --- .../jet/codegen/ExpressionCodegen.java | 21 ++++++++++++++++--- .../testData/codegen/regressions/kt2391.kt | 19 +++++++++++++++++ .../jetbrains/jet/codegen/ClassGenTest.java | 5 +++++ 3 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/codegen/regressions/kt2391.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 26987e2dcf2..d263d6de8eb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1228,6 +1228,7 @@ public class ExpressionCodegen extends JetVisitor { containingDeclaration = containingDeclaration.getOriginal(); boolean isStatic = containingDeclaration instanceof NamespaceDescriptor; + boolean overridesTrait = isOverrideForTrait(propertyDescriptor); propertyDescriptor = propertyDescriptor.getOriginal(); boolean isInsideClass = ((containingDeclaration == context.getThisDescriptor()) || (context.getParentContext() instanceof CodegenContexts.NamespaceContext) && context.getParentContext().getContextDescriptor() == containingDeclaration) @@ -1294,11 +1295,13 @@ public class ExpressionCodegen extends JetVisitor { boolean isInterface; if (isInsideClass || isStatic || propertyDescriptor.getGetter() == null) { owner = ownerParam = typeMapper.getOwner(propertyDescriptor, contextKind()); - isInterface = false; - invokeOpcode = isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL; + isInterface = overridesTrait; + invokeOpcode = isStatic ? Opcodes.INVOKESTATIC : + overridesTrait ? Opcodes.INVOKEINTERFACE + : Opcodes.INVOKEVIRTUAL; } else { - isInterface = CodegenUtil.isInterface(containingDeclaration); + isInterface = CodegenUtil.isInterface(containingDeclaration) || overridesTrait; // TODO ugly CallableMethod callableMethod = typeMapper.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper, contextKind()); invokeOpcode = callableMethod.getInvokeOpcode(); @@ -1309,6 +1312,18 @@ public class ExpressionCodegen extends JetVisitor { return StackValue.property(propertyDescriptor.getName().getName(), owner, ownerParam, asmType(propertyDescriptor.getType()), isStatic, isInterface, isSuper, getter, setter, invokeOpcode); } + static boolean isOverrideForTrait(CallableMemberDescriptor propertyDescriptor) { + if (propertyDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + final Set overriddenDescriptors = propertyDescriptor.getOverriddenDescriptors(); + for (CallableMemberDescriptor descriptor : overriddenDescriptors) { + if (CodegenUtil.isInterface(descriptor.getContainingDeclaration())) { + return true; + } + } + } + return false; + } + @Override public StackValue visitCallExpression(JetCallExpression expression, StackValue receiver) { final JetExpression callee = expression.getCalleeExpression(); diff --git a/compiler/testData/codegen/regressions/kt2391.kt b/compiler/testData/codegen/regressions/kt2391.kt new file mode 100644 index 00000000000..005c5715d29 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt2391.kt @@ -0,0 +1,19 @@ +public trait LoggerAware { + public val logger: StringBuilder +} + +public abstract class HttpServer(): LoggerAware { + public fun start() { + logger.append("OK") + } +} + +public class MyHttpServer(): HttpServer() { + public override val logger = StringBuilder() +} + +fun box(): String { + val server = MyHttpServer() + server.start() + return server.logger.toString()!! +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java index da89c2271e3..e09c7580502 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -461,4 +461,9 @@ public class ClassGenTest extends CodegenTestCase { createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); blackBoxFile("regressions/kt2390.kt"); } + + public void testKt2391() { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); + blackBoxFile("regressions/kt2391.kt"); + } }