diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 17056191de3..bf5e985cfeb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -980,73 +980,76 @@ public class ExpressionCodegen extends JetVisitor { return StackValue.local(index, TYPE_OBJECT); } } - else if (descriptor instanceof PropertyDescriptor) { - PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; - PsiElement declaration = null; - if (((PropertyDescriptor) descriptor).getKind() == CallableMemberDescriptor.Kind.DECLARATION) { - declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); - } - if (declaration instanceof JetObjectDeclarationName) { - // todo: we have property here but not in containing class/namespace - JetObjectDeclaration objectDeclaration = PsiTreeUtil.getParentOfType(declaration, JetObjectDeclaration.class); - ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, objectDeclaration); - assert classDescriptor != null; - return StackValue.field(typeMapper.mapType(classDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION), - typeMapper.mapType(classDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), - "$instance", - true); - } - else { - boolean isStatic = container instanceof NamespaceDescriptor; - final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ; - JetExpression r = getReceiverForSelector(expression); - final boolean isSuper = r instanceof JetSuperExpression; - if(propertyDescriptor.getVisibility() == Visibility.PRIVATE && !CodegenUtil.isClassObject(propertyDescriptor.getContainingDeclaration())) { - if(context.getClassOrNamespaceDescriptor() != propertyDescriptor.getContainingDeclaration()) { - DeclarationDescriptor enclosed = propertyDescriptor.getContainingDeclaration(); - if(enclosed != null && enclosed != context.getThisDescriptor()) { - CodegenContext c = context; - while(c.getContextDescriptor() != enclosed) { - c = c.getParentContext(); - } - propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor); - } - } - } - final StackValue.Property iValue = intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression)r : null); - if(!directToField && resolvedCall != null && !isSuper) { - receiver.put(propertyDescriptor.getReceiverParameter().exists() || isStatic? receiver.type : Type.getObjectType(iValue.methodOwner), v); - pushTypeArguments(resolvedCall); + if (descriptor instanceof PropertyDescriptor) { + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; + + if(propertyDescriptor.isObjectDeclaration()) { + ClassDescriptor classDescriptor = (ClassDescriptor) propertyDescriptor.getReturnType().getConstructor().getDeclarationDescriptor(); + if(classDescriptor.getKind() == ClassKind.ENUM_ENTRY) { + ClassDescriptor containing = (ClassDescriptor) classDescriptor.getContainingDeclaration().getContainingDeclaration(); + Type type = typeMapper.mapType(containing.getDefaultType(), OwnerKind.IMPLEMENTATION); + StackValue.field(type, type.getInternalName(), classDescriptor.getName(), true).put(TYPE_OBJECT, v); + + // todo: for now we don't generate classes for enum entries, so we need this hack + type = typeMapper.mapType(classDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION); + return StackValue.onStack(type); } else { - if (!isStatic) { - if (receiver == StackValue.none()) { - if(resolvedCall == null) - receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration()); - else { - if(resolvedCall.getThisObject() instanceof ExtensionReceiver) - receiver = generateReceiver(((ExtensionReceiver)resolvedCall.getThisObject()).getDeclarationDescriptor()); - else - receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration()); - } + Type type = typeMapper.mapType(classDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION); + return StackValue.field(type, type.getInternalName(), "$instance", true); + } + } + + boolean isStatic = container instanceof NamespaceDescriptor; + final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ; + JetExpression r = getReceiverForSelector(expression); + final boolean isSuper = r instanceof JetSuperExpression; + if(propertyDescriptor.getVisibility() == Visibility.PRIVATE && !CodegenUtil.isClassObject(propertyDescriptor.getContainingDeclaration())) { + if(context.getClassOrNamespaceDescriptor() != propertyDescriptor.getContainingDeclaration()) { + DeclarationDescriptor enclosed = propertyDescriptor.getContainingDeclaration(); + if(enclosed != null && enclosed != context.getThisDescriptor()) { + CodegenContext c = context; + while(c.getContextDescriptor() != enclosed) { + c = c.getParentContext(); } - JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r); - receiver.put(receiverType != null && !isSuper? asmType(receiverType) : TYPE_OBJECT, v); - if(receiverType != null) { - ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration(); - if(!CodegenUtil.isInterface(propReceiverDescriptor) && CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor())) { - // I hope it happens only in case of required super class for traits - assert propReceiverDescriptor != null; - v.checkcast(asmType(propReceiverDescriptor.getDefaultType())); - } + propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor); + } + } + } + final StackValue.Property iValue = intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression)r : null); + if(!directToField && resolvedCall != null && !isSuper) { + receiver.put(propertyDescriptor.getReceiverParameter().exists() || isStatic? receiver.type : Type.getObjectType(iValue.methodOwner), v); + pushTypeArguments(resolvedCall); + } + else { + if (!isStatic) { + if (receiver == StackValue.none()) { + if(resolvedCall == null) + receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration()); + else { + if(resolvedCall.getThisObject() instanceof ExtensionReceiver) + receiver = generateReceiver(((ExtensionReceiver)resolvedCall.getThisObject()).getDeclarationDescriptor()); + else + receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration()); + } + } + JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r); + receiver.put(receiverType != null && !isSuper? asmType(receiverType) : TYPE_OBJECT, v); + if(receiverType != null) { + ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration(); + if(!CodegenUtil.isInterface(propReceiverDescriptor) && CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor())) { + // I hope it happens only in case of required super class for traits + assert propReceiverDescriptor != null; + v.checkcast(asmType(propReceiverDescriptor.getDefaultType())); } } } - return iValue; } + return iValue; } - else if (descriptor instanceof ClassDescriptor) { + + if (descriptor instanceof ClassDescriptor) { PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); if(declaration instanceof JetClass) { final JetClassObject classObject = ((JetClass) declaration).getClassObject(); @@ -1066,7 +1069,8 @@ public class ExpressionCodegen extends JetVisitor { return StackValue.none(); } } - else if (descriptor instanceof TypeParameterDescriptor) { + + if (descriptor instanceof TypeParameterDescriptor) { TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor; loadTypeParameterTypeInfo(typeParameterDescriptor, null); v.invokevirtual("jet/TypeInfo", "getClassObject", "()Ljava/lang/Object;"); @@ -1074,25 +1078,25 @@ public class ExpressionCodegen extends JetVisitor { return StackValue.onStack(TYPE_OBJECT); } - else { - // receiver - StackValue value = context.lookupInContext(descriptor, v, StackValue.local(0, TYPE_OBJECT)); - if (value == null) { - throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); - } - if(value instanceof StackValue.Composed) { - StackValue.Composed composed = (StackValue.Composed) value; - composed.prefix.put(TYPE_OBJECT, v); - value = composed.suffix; - } - if(value instanceof StackValue.FieldForSharedVar) { - StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value; - Type sharedType = StackValue.sharedTypeForType(value.type); - v.visitFieldInsn(Opcodes.GETFIELD, fieldForSharedVar.owner, fieldForSharedVar.name, sharedType.getDescriptor()); - } - return value; + StackValue value = context.lookupInContext(descriptor, v, StackValue.local(0, TYPE_OBJECT)); + if (value == null) { + throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); } + + if(value instanceof StackValue.Composed) { + StackValue.Composed composed = (StackValue.Composed) value; + composed.prefix.put(TYPE_OBJECT, v); + value = composed.suffix; + } + + if(value instanceof StackValue.FieldForSharedVar) { + StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value; + Type sharedType = StackValue.sharedTypeForType(value.type); + v.visitFieldInsn(Opcodes.GETFIELD, fieldForSharedVar.owner, fieldForSharedVar.name, sharedType.getDescriptor()); + } + + return value; } public int lookupLocal(DeclarationDescriptor descriptor) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableMemberDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableMemberDescriptor.java index d1b673f5833..b68e6ca4b8f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableMemberDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableMemberDescriptor.java @@ -12,7 +12,7 @@ public interface CallableMemberDescriptor extends CallableDescriptor, MemberDesc @Override Set getOverriddenDescriptors(); - public enum Kind { + enum Kind { DECLARATION, FAKE_OVERRIDE, DELEGATION, diff --git a/compiler/testData/codegen/regressions/kt694.kt b/compiler/testData/codegen/regressions/kt694.kt new file mode 100644 index 00000000000..9599fdc3ed5 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt694.kt @@ -0,0 +1,18 @@ +enum class Test { + A + B + C +} + +fun checkA(a: Test) = when(a) { + Test.B -> false + Test.A -> true + else -> false +} + +fun box() : String { + if(!checkA(Test.A)) return "fail" + if( checkA(Test.C)) return "fail" + if( checkA(Test.B)) return "fail" + return "OK" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java index 86b30cfd73a..9f24aef47ec 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java @@ -38,4 +38,8 @@ public class ObjectGenTest extends CodegenTestCase { public void testKt1047() throws Exception { blackBoxFile("regressions/kt1047.kt"); } + + public void testKt694() throws Exception { + blackBoxFile("regressions/kt694.kt"); + } }