diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java b/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java index fe479826648..82a5df68b05 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CallableMethod.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.codegen; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; @@ -16,24 +17,38 @@ import java.util.List; * @author alex.tkacman */ public class CallableMethod implements Callable { - private String owner; + @NotNull + private final String owner; + @NotNull + private final String defaultImplOwner; + @NotNull + private final String defaultImplParam; private final JvmMethodSignature signature; - private int invokeOpcode; + private final int invokeOpcode; private ClassDescriptor thisClass = null; private CallableDescriptor receiverFunction = null; private Type generateCalleeType = null; - public CallableMethod(String owner, JvmMethodSignature signature, int invokeOpcode) { + public CallableMethod(@NotNull String owner, @NotNull String defaultImplOwner, @NotNull String defaultImplParam, + JvmMethodSignature signature, int invokeOpcode) { this.owner = owner; + this.defaultImplOwner = defaultImplOwner; + this.defaultImplParam = defaultImplParam; this.signature = signature; this.invokeOpcode = invokeOpcode; } + @NotNull public String getOwner() { return owner; } + @NotNull + public String getDefaultImplParam() { + return defaultImplParam; + } + public JvmMethodSignature getSignature() { return signature; } @@ -75,16 +90,20 @@ public class CallableMethod implements Callable { } public void invokeWithDefault(InstructionAdapter v, int mask) { + if (defaultImplOwner.length() == 0 || defaultImplParam.length() == 0) { + throw new IllegalStateException(); + } + v.iconst(mask); String desc = getSignature().getAsmMethod().getDescriptor().replace(")", "I)"); if("".equals(getSignature().getAsmMethod().getName())) { - v.visitMethodInsn(Opcodes.INVOKESPECIAL, getOwner(), "", desc); + v.visitMethodInsn(Opcodes.INVOKESPECIAL, defaultImplOwner, "", desc); } else { if(getInvokeOpcode() != Opcodes.INVOKESTATIC) - desc = desc.replace("(", "(L" + getOwner() + ";"); - v.visitMethodInsn(Opcodes.INVOKESTATIC, getInvokeOpcode() == Opcodes.INVOKEINTERFACE ? getOwner() + JvmAbi.TRAIT_IMPL_SUFFIX - : getOwner(), getSignature().getAsmMethod().getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, desc); + desc = desc.replace("(", "(L" + defaultImplParam + ";"); + v.visitMethodInsn(Opcodes.INVOKESTATIC, defaultImplOwner, + getSignature().getAsmMethod().getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, desc); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index c5019a2c3e0..e58bfde6180 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -71,7 +71,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { public static CallableMethod asCallableMethod(FunctionDescriptor fd) { JvmMethodSignature descriptor = erasedInvokeSignature(fd); String owner = getInternalClassName(fd); - final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL); + final CallableMethod result = new CallableMethod(owner, "", "", descriptor, INVOKEVIRTUAL); if (fd.getReceiverParameter().exists()) { result.setNeedsReceiver(fd); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java index a7c1b270ff2..905dfc194ca 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -211,8 +211,9 @@ public abstract class CodegenContext { if(descriptor instanceof NamedFunctionDescriptor) { NamedFunctionDescriptorImpl myAccessor = new NamedFunctionDescriptorImpl(contextType, - Collections.emptyList(), - descriptor.getName() + "$bridge$" + accessors.size()); + Collections.emptyList(), + descriptor.getName() + "$bridge$" + accessors.size(), + CallableMemberDescriptor.Kind.DECLARATION); FunctionDescriptor fd = (NamedFunctionDescriptor) descriptor; myAccessor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null, fd.getExpectedThisObject(), @@ -231,7 +232,8 @@ public abstract class CodegenContext { pd.getVisibility(), pd.isVar(), pd.isObjectDeclaration(), - pd.getName() + "$bridge$" + accessors.size() + pd.getName() + "$bridge$" + accessors.size(), + CallableMemberDescriptor.Kind.DECLARATION ); JetType receiverType = pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null; myAccessor.setType(pd.getOutType(), Collections.emptyList(), pd.getExpectedThisObject(), receiverType); @@ -239,13 +241,13 @@ public abstract class CodegenContext { PropertyGetterDescriptor pgd = new PropertyGetterDescriptor( myAccessor, Collections.emptyList(), myAccessor.getModality(), myAccessor.getVisibility(), - false, false); + false, false, CallableMemberDescriptor.Kind.DECLARATION); pgd.initialize(myAccessor.getOutType()); PropertySetterDescriptor psd = new PropertySetterDescriptor( myAccessor, Collections.emptyList(), myAccessor.getModality(), myAccessor.getVisibility(), - false, false); + false, false, CallableMemberDescriptor.Kind.DECLARATION); myAccessor.initialize(pgd, psd); accessor = myAccessor; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index 4799a503c12..8cf37df457c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -97,7 +97,8 @@ public class CodegenUtil { NamedFunctionDescriptorImpl invokeDescriptor = new NamedFunctionDescriptorImpl( fd.getExpectedThisObject().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity), Collections.emptyList(), - "invoke"); + "invoke", + CallableMemberDescriptor.Kind.DECLARATION); invokeDescriptor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null, fd.getExpectedThisObject(), diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java b/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java index 2508e1332ce..3db398e8c62 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java @@ -36,7 +36,16 @@ public class CompilationException extends RuntimeException { col = -1; } - return "Internal error: (" + (line+1) + "," + col + ") " + (getCause().getMessage() != null ? getCause().getMessage() : getCause().toString()) + "\n@" + getCause().getStackTrace()[0].getFileName() + ":" + getCause().getStackTrace()[0].getLineNumber(); + String s2 = getCause().getMessage() != null ? getCause().getMessage() : getCause().toString(); + return "Internal error: (" + (line+1) + "," + col + ") " + s2 + "\n@" + where(); + } + + private String where() { + if (getCause().getStackTrace().length > 0) { + return getCause().getStackTrace()[0].getFileName() + ":" + getCause().getStackTrace()[0].getLineNumber(); + } else { + return "far away in cyberspace"; + } } @Override diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 457efc8c24c..8c4309eb6d5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -983,7 +983,10 @@ public class ExpressionCodegen extends JetVisitor { else if (descriptor instanceof PropertyDescriptor) { PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; - PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, 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); @@ -1013,7 +1016,7 @@ public class ExpressionCodegen extends JetVisitor { } 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.owner), v); + receiver.put(propertyDescriptor.getReceiverParameter().exists() || isStatic? receiver.type : Type.getObjectType(iValue.methodOwner), v); pushTypeArguments(resolvedCall); } else { @@ -1097,7 +1100,7 @@ public class ExpressionCodegen extends JetVisitor { } public void invokeFunctionNoParams(FunctionDescriptor functionDescriptor, Type type, InstructionAdapter v) { - DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); + DeclarationDescriptor containingDeclaration = functionDescriptor.getOriginal().getContainingDeclaration(); boolean isStatic = containingDeclaration instanceof NamespaceDescriptor; functionDescriptor = functionDescriptor.getOriginal(); String owner; @@ -1190,18 +1193,26 @@ public class ExpressionCodegen extends JetVisitor { } } + int invokeOpcode; + String owner; + String ownerParam; boolean isInterface; - if (isInsideClass || isStatic) { - owner = typeMapper.getOwner(propertyDescriptor, contextKind()); + if (isInsideClass || isStatic || propertyDescriptor.getGetter() == null) { + owner = ownerParam = typeMapper.getOwner(propertyDescriptor, contextKind()); isInterface = false; + invokeOpcode = isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL; } else { - owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.IMPLEMENTATION); isInterface = CodegenUtil.isInterface(containingDeclaration); + // TODO ugly + CallableMethod callableMethod = typeMapper.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper, contextKind()); + invokeOpcode = callableMethod.getInvokeOpcode(); + owner = callableMethod.getOwner(); + ownerParam = callableMethod.getDefaultImplParam(); } - return StackValue.property(propertyDescriptor.getName(), owner, asmType(propertyDescriptor.getOutType()), isStatic, isInterface, isSuper, getter, setter); + return StackValue.property(propertyDescriptor.getName(), owner, ownerParam, asmType(propertyDescriptor.getOutType()), isStatic, isInterface, isSuper, getter, setter, invokeOpcode); } @Override @@ -1442,13 +1453,18 @@ public class ExpressionCodegen extends JetVisitor { private int pushMethodArguments(@NotNull ResolvedCall resolvedCall, List valueParameterTypes) { @SuppressWarnings("unchecked") - Map valueArguments = resolvedCall.getValueArguments(); + List valueArguments = resolvedCall.getValueArgumentsByIndex(); CallableDescriptor fd = resolvedCall.getResultingDescriptor(); + if (fd.getValueParameters().size() != valueArguments.size()) { + throw new IllegalStateException(); + } + int index = 0; int mask = 0; + for (ValueParameterDescriptor valueParameterDescriptor : fd.getValueParameters()) { - ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameterDescriptor); + ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameterDescriptor.getIndex()); if(resolvedValueArgument instanceof ExpressionValueArgument) { ExpressionValueArgument valueArgument = (ExpressionValueArgument) resolvedValueArgument; gen(valueArgument.getExpression(), valueParameterTypes.get(index)); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 88c3f6b658b..c7f29560c3c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -1,6 +1,9 @@ package org.jetbrains.jet.codegen; +import com.google.common.collect.Lists; +import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; @@ -405,7 +408,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { signatureWriter.writeVoidReturn(); constructorMethod = signatureWriter.makeJvmMethodSignature(""); - callableMethod = new CallableMethod("", constructorMethod, INVOKESPECIAL); + callableMethod = new CallableMethod("", "", "", constructorMethod, INVOKESPECIAL); } else { callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind); @@ -651,62 +654,65 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { private void generateTraitMethods(ExpressionCodegen codegen) { if(!(myClass instanceof JetClass) || ((JetClass)myClass).isTrait() || ((JetClass)myClass).hasModifier(JetTokens.ABSTRACT_KEYWORD)) return; + + for (Pair needDelegates : getTraitImplementations(descriptor)) { + CallableMemberDescriptor callableDescriptor = needDelegates.first; + FunctionDescriptor fun = (FunctionDescriptor) needDelegates.second; + generateDelegationToTraitImpl(codegen, fun); + } + } - for (CallableDescriptor callableDescriptor : OverridingUtil.getEffectiveMembers(descriptor)) { - if(callableDescriptor instanceof FunctionDescriptor) { - FunctionDescriptor fun = (FunctionDescriptor) callableDescriptor; - DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration(); - if(containingDeclaration instanceof ClassDescriptor) { - ClassDescriptor declaration = (ClassDescriptor) containingDeclaration; - PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaration); - if(psiElement instanceof JetClass) { - JetClass jetClass = (JetClass) psiElement; - if(jetClass.isTrait()) { - int flags = ACC_PUBLIC; // TODO. + private void generateDelegationToTraitImpl(ExpressionCodegen codegen, FunctionDescriptor fun) { + DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration(); + if(containingDeclaration instanceof ClassDescriptor) { + ClassDescriptor declaration = (ClassDescriptor) containingDeclaration; + PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaration); + if(psiElement instanceof JetClass) { + JetClass jetClass = (JetClass) psiElement; + if(jetClass.isTrait()) { + int flags = ACC_PUBLIC; // TODO. - Method function = typeMapper.mapSignature(fun.getName(), fun).getAsmMethod(); - Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod(); + Method function = typeMapper.mapSignature(fun.getName(), fun).getAsmMethod(); + Method functionOriginal = typeMapper.mapSignature(fun.getName(), fun.getOriginal()).getAsmMethod(); - final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null); - if (v.generateCode()) { - mv.visitCode(); + final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null); + if (v.generateCode()) { + mv.visitCode(); - codegen.generateThisOrOuter(descriptor); + codegen.generateThisOrOuter(descriptor); - Type[] argTypes = function.getArgumentTypes(); - InstructionAdapter iv = new InstructionAdapter(mv); - iv.load(0, JetTypeMapper.TYPE_OBJECT); - for (int i = 0, reg = 1; i < argTypes.length; i++) { - Type argType = argTypes[i]; - iv.load(reg, argType); - //noinspection AssignmentToForLoopParameter - reg += argType.getSize(); - } - - JetType jetType = TraitImplBodyCodegen.getSuperClass(declaration, bindingContext); - Type type = typeMapper.mapType(jetType); - if(type.getInternalName().equals("java/lang/Object")) { - jetType = declaration.getDefaultType(); - type = typeMapper.mapType(jetType); - } - - String fdescriptor = functionOriginal.getDescriptor().replace("(","(" + type.getDescriptor()); - iv.invokestatic(typeMapper.mapType(((ClassDescriptor) fun.getContainingDeclaration()).getDefaultType(), OwnerKind.TRAIT_IMPL).getInternalName(), function.getName(), fdescriptor); - if(function.getReturnType().getSort() == Type.OBJECT) { - iv.checkcast(function.getReturnType()); - } - iv.areturn(function.getReturnType()); - FunctionCodegen.endVisit(iv, "trait method", bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, fun)); - } - - FunctionCodegen.generateBridgeIfNeeded(context, state, v, function, fun, kind); + Type[] argTypes = function.getArgumentTypes(); + InstructionAdapter iv = new InstructionAdapter(mv); + iv.load(0, JetTypeMapper.TYPE_OBJECT); + for (int i = 0, reg = 1; i < argTypes.length; i++) { + Type argType = argTypes[i]; + iv.load(reg, argType); + //noinspection AssignmentToForLoopParameter + reg += argType.getSize(); } + + JetType jetType = TraitImplBodyCodegen.getSuperClass(declaration, bindingContext); + Type type = typeMapper.mapType(jetType); + if(type.getInternalName().equals("java/lang/Object")) { + jetType = declaration.getDefaultType(); + type = typeMapper.mapType(jetType); + } + + String fdescriptor = functionOriginal.getDescriptor().replace("(","(" + type.getDescriptor()); + iv.invokestatic(typeMapper.mapType(((ClassDescriptor) fun.getContainingDeclaration()).getDefaultType(), OwnerKind.TRAIT_IMPL).getInternalName(), function.getName(), fdescriptor); + if(function.getReturnType().getSort() == Type.OBJECT) { + iv.checkcast(function.getReturnType()); + } + iv.areturn(function.getReturnType()); + FunctionCodegen.endVisit(iv, "trait method", bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, fun)); } + + FunctionCodegen.generateBridgeIfNeeded(context, state, v, function, fun, kind); } } } } - + @Nullable private ClassDescriptor getOuterClassDescriptor() { if (myClass.getParent() instanceof JetClassObject) { @@ -891,7 +897,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { codegen.gen(initializer, type); // @todo write directly to the field. Fix test excloset.jet::test6 String owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.IMPLEMENTATION); - StackValue.property(propertyDescriptor.getName(), owner, typeMapper.mapType(propertyDescriptor.getOutType()), false, false, false, null, null).store(iv); + StackValue.property(propertyDescriptor.getName(), owner, owner, typeMapper.mapType(propertyDescriptor.getOutType()), false, false, false, null, null, 0).store(iv); } } @@ -998,4 +1004,43 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } }); } + + + /** + * Return pairs of descriptors. First is member of this that should be implemented by delegating to trait, + * second is member of trait that contain implementation. + */ + public static List> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) { + List> r = Lists.newArrayList(); + + root: + for (DeclarationDescriptor decl : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) { + if (!(decl instanceof CallableMemberDescriptor)) { + continue; + } + + CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) decl; + if (callableMemberDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + continue; + } + + Collection overridenDeclarations = OverridingUtil.getOverridenDeclarations(callableMemberDescriptor); + for (CallableMemberDescriptor overridenDeclaration : overridenDeclarations) { + if (overridenDeclaration.getModality() != Modality.ABSTRACT) { + if (!CodegenUtil.isInterface(overridenDeclaration.getContainingDeclaration())) { + continue root; + } + } + } + + for (CallableMemberDescriptor overridenDeclaration : overridenDeclarations) { + if (overridenDeclaration.getModality() != Modality.ABSTRACT) { + r.add(Pair.create(callableMemberDescriptor, overridenDeclaration)); + } + } + } + + return r; + } + } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 167dbc2f0e8..63eb6359336 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -110,7 +110,11 @@ public class JetTypeMapper { kind = OwnerKind.IMPLEMENTATION; } } - owner = mapType(classDescriptor.getDefaultType(), kind).getInternalName(); + Type asmType = mapType(classDescriptor.getDefaultType(), kind); + if (asmType.getSort() != Type.OBJECT) { + throw new IllegalStateException(); + } + owner = asmType.getInternalName(); } else { throw new UnsupportedOperationException("don't know how to generate owner for parent " + containingDeclaration); @@ -118,11 +122,11 @@ public class JetTypeMapper { return owner; } - @NotNull public Type mapReturnType(final JetType jetType) { + @NotNull public Type mapReturnType(@NotNull final JetType jetType) { return mapReturnType(jetType, null); } - @NotNull private Type mapReturnType(final JetType jetType, @Nullable BothSignatureWriter signatureVisitor) { + @NotNull private Type mapReturnType(@NotNull final JetType jetType, @Nullable BothSignatureWriter signatureVisitor) { if (jetType.equals(JetStandardClasses.getUnitType())) { if (signatureVisitor != null) { signatureVisitor.writeAsmType(Type.VOID_TYPE, false); @@ -355,9 +359,11 @@ public class JetTypeMapper { if(functionDescriptor == null) return null; - final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration(); + final DeclarationDescriptor functionParent = functionDescriptor.getOriginal().getContainingDeclaration(); JvmMethodSignature descriptor = mapSignature(functionDescriptor.getOriginal(), true, kind); String owner; + String ownerForDefaultImpl; + String ownerForDefaultParam; int invokeOpcode; ClassDescriptor thisClass; if (functionParent instanceof NamespaceDescriptor) { @@ -367,6 +373,7 @@ public class JetTypeMapper { namespace = ((JavaNamespaceDescriptor) functionParent).isNamespace(); } owner = NamespaceCodegen.getJVMClassName(DescriptorUtils.getFQName(functionParent), namespace); + ownerForDefaultImpl = ownerForDefaultParam = owner; invokeOpcode = INVOKESTATIC; thisClass = null; } @@ -374,28 +381,50 @@ public class JetTypeMapper { assert !superCall; ClassDescriptor containingClass = (ClassDescriptor) functionParent; owner = mapType(containingClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(); + ownerForDefaultImpl = ownerForDefaultParam = owner; invokeOpcode = INVOKESPECIAL; thisClass = null; } else if (functionParent instanceof ClassDescriptor) { + + FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor); + + ClassDescriptor currentOwner = (ClassDescriptor) functionParent; + ClassDescriptor declarationOwner = (ClassDescriptor) declarationFunctionDescriptor.getContainingDeclaration(); + + boolean originalIsInterface = CodegenUtil.isInterface(declarationOwner); + boolean currentIsInterface = CodegenUtil.isInterface(currentOwner); + + ClassDescriptor receiver; + if (currentIsInterface && !originalIsInterface) { + receiver = declarationOwner; + } else { + receiver = currentOwner; + } + ClassDescriptor containingClass = (ClassDescriptor) functionParent; - boolean isInterface = CodegenUtil.isInterface(containingClass); + boolean isInterface = originalIsInterface && currentIsInterface; OwnerKind kind1 = isInterface && superCall ? OwnerKind.TRAIT_IMPL : OwnerKind.IMPLEMENTATION; - Type type = mapType(containingClass.getDefaultType(), kind1); + Type type = mapType(receiver.getDefaultType(), OwnerKind.IMPLEMENTATION); owner = type.getInternalName(); + ownerForDefaultParam = mapType(((ClassDescriptor) declarationOwner).getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(); + ownerForDefaultImpl = ownerForDefaultParam + + (originalIsInterface ? JvmAbi.TRAIT_IMPL_SUFFIX : ""); + invokeOpcode = isInterface ? (superCall ? Opcodes.INVOKESTATIC : Opcodes.INVOKEINTERFACE) : (superCall ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL); if(isInterface && superCall) { - descriptor = mapSignature(functionDescriptor.getOriginal(), false, OwnerKind.TRAIT_IMPL); + descriptor = mapSignature(functionDescriptor, false, OwnerKind.TRAIT_IMPL); + owner += JvmAbi.TRAIT_IMPL_SUFFIX; } - thisClass = (ClassDescriptor) functionParent; + thisClass = receiver; } else { throw new UnsupportedOperationException("unknown function parent"); } - final CallableMethod result = new CallableMethod(owner, descriptor, invokeOpcode); + final CallableMethod result = new CallableMethod(owner, ownerForDefaultImpl, ownerForDefaultParam, descriptor, invokeOpcode); result.setNeedsThis(thisClass); if(functionDescriptor.getReceiverParameter().exists()) { result.setNeedsReceiver(functionDescriptor); @@ -403,6 +432,17 @@ public class JetTypeMapper { return result; } + + @NotNull + private static FunctionDescriptor findAnyDeclaration(@NotNull FunctionDescriptor function) { + //if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) { + if (function.getOverriddenDescriptors().isEmpty()) { + return function; + } else { + // TODO: prefer class to interface + return findAnyDeclaration(function.getOverriddenDescriptors().iterator().next()); + } + } private JvmMethodSignature mapSignature(FunctionDescriptor f, boolean needGenericSignature, OwnerKind kind) { @@ -676,7 +716,7 @@ public class JetTypeMapper { public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) { final JvmMethodSignature method = mapConstructorSignature(descriptor); String owner = mapType(descriptor.getContainingDeclaration().getDefaultType(), kind).getInternalName(); - return new CallableMethod(owner, method, INVOKESPECIAL); + return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL); } public static int getAccessModifiers(DeclarationDescriptorWithVisibility p, int defaultFlags) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 30432e40861..ef72f084c3c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -1,15 +1,14 @@ package org.jetbrains.jet.codegen; import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; -import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; -import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lexer.JetTokens; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; @@ -106,8 +105,8 @@ public abstract class StackValue { return new Field(type, owner, name, isStatic); } - public static Property property(String name, String owner, Type type, boolean isStatic, boolean isInterface, boolean isSuper, Method getter, Method setter) { - return new Property(name, owner, getter, setter, isStatic, isInterface, isSuper, type); + public static Property property(String name, String methodOwner, String methodOwnerParam, Type type, boolean isStatic, boolean isInterface, boolean isSuper, Method getter, Method setter, int invokeOpcode) { + return new Property(name, methodOwner, methodOwnerParam, getter, setter, isStatic, isInterface, isSuper, type, invokeOpcode); } public static StackValue expression(Type type, JetExpression expression, ExpressionCodegen generator) { @@ -770,38 +769,50 @@ public abstract class StackValue { } static class Property extends StackValue { + @NotNull private final String name; @Nullable private final Method getter; @Nullable private final Method setter; - public final String owner; + @NotNull + public final String methodOwner; + @NotNull + private final String methodOwnerParam; private final boolean isStatic; private final boolean isInterface; - private boolean isSuper; + private final boolean isSuper; + private final int invokeOpcode; - public Property(String name, String owner, Method getter, Method setter, boolean aStatic, boolean isInterface, boolean isSuper, Type type) { + public Property(@NotNull String name, @NotNull String methodOwner, @NotNull String methodOwnerParam, Method getter, Method setter, boolean aStatic, boolean isInterface, boolean isSuper, Type type, int invokeOpcode) { super(type); this.name = name; - this.owner = owner; + this.methodOwner = methodOwner; + this.methodOwnerParam = methodOwnerParam; this.getter = getter; this.setter = setter; isStatic = aStatic; this.isInterface = isInterface; this.isSuper = isSuper; + this.invokeOpcode = invokeOpcode; + if (invokeOpcode == 0) { + if (setter != null || getter != null) { + throw new IllegalArgumentException(); + } + } } @Override public void put(Type type, InstructionAdapter v) { if(isSuper && isInterface) { - v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + JvmAbi.TRAIT_IMPL_SUFFIX, getter.getName(), getter.getDescriptor().replace("(","(L" + owner + ";")); + v.visitMethodInsn(Opcodes.INVOKESTATIC, methodOwner, getter.getName(), getter.getDescriptor().replace("(", "(L" + methodOwnerParam + ";")); } else { if (getter == null) { - v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor()); + v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, methodOwner, name, this.type.getDescriptor()); } else { - v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor()); + v.visitMethodInsn(invokeOpcode, methodOwner, getter.getName(), getter.getDescriptor()); } } coerce(type, v); @@ -810,14 +821,14 @@ public abstract class StackValue { @Override public void store(InstructionAdapter v) { if(isSuper && isInterface) { - v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + JvmAbi.TRAIT_IMPL_SUFFIX, setter.getName(), setter.getDescriptor().replace("(","(L" + owner + ";")); + v.visitMethodInsn(Opcodes.INVOKESTATIC, methodOwner, setter.getName(), setter.getDescriptor().replace("(", "(L" + methodOwnerParam + ";")); } else { if (setter == null) { - v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor()); + v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, methodOwner, name, this.type.getDescriptor()); } else { - v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor()); + v.visitMethodInsn(invokeOpcode, methodOwner, setter.getName(), setter.getDescriptor()); } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 7c27da6159f..7593508e80e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -36,7 +36,8 @@ public class IntrinsicMethods { private static final IntrinsicMethod INC = new Increment(1); private static final IntrinsicMethod DEC = new Increment(-1); - private static final List PRIMITIVE_NUMBER_TYPES = ImmutableList.of("Boolean", "Byte", "Char", "Short", "Int", "Float", "Long", "Double"); + private static final List PRIMITIVE_TYPES = ImmutableList.of("Boolean", "Byte", "Char", "Short", "Int", "Float", "Long", "Double"); + private static final List PRIMITIVE_NUMBER_TYPES = ImmutableList.of("Byte", "Char", "Short", "Int", "Float", "Long", "Double"); public static final IntrinsicMethod ARRAY_SIZE = new ArraySize(); public static final IntrinsicMethod ARRAY_INDICES = new ArrayIndices(); public static final Equals EQUALS = new Equals(); @@ -56,17 +57,20 @@ public class IntrinsicMethods { List primitiveCastMethods = ImmutableList.of("dbl", "flt", "lng", "int", "chr", "sht", "byt"); for (String method : primitiveCastMethods) { declareIntrinsicProperty("Number", method, NUMBER_CAST); + for (String type : PRIMITIVE_NUMBER_TYPES) { + declareIntrinsicProperty(type, method, NUMBER_CAST); + } } for (String type : PRIMITIVE_NUMBER_TYPES) { - declareIntrinsicFunction(type, "plus", 0, UNARY_PLUS); - declareIntrinsicFunction(type, "minus", 0, UNARY_MINUS); - declareIntrinsicFunction(type, "inv", 0, INV); - declareIntrinsicFunction(type, "rangeTo", 1, UP_TO); - declareIntrinsicFunction(type, "upto", 1, UP_TO); - declareIntrinsicFunction(type, "downto", 1, DOWN_TO); - declareIntrinsicFunction(type, "inc", 0, INC); - declareIntrinsicFunction(type, "dec", 0, DEC); + declareIntrinsicFunction(type, "plus", 0, UNARY_PLUS, false); + declareIntrinsicFunction(type, "minus", 0, UNARY_MINUS, false); + declareIntrinsicFunction(type, "inv", 0, INV, false); + declareIntrinsicFunction(type, "rangeTo", 1, UP_TO, false); + declareIntrinsicFunction(type, "upto", 1, UP_TO, false); + declareIntrinsicFunction(type, "downto", 1, DOWN_TO, false); + declareIntrinsicFunction(type, "inc", 0, INC, false); + declareIntrinsicFunction(type, "dec", 0, DEC, false); } final Set typeInfoFunctionGroup = stdlib.getTypeInfoFunctions(); @@ -85,10 +89,11 @@ public class IntrinsicMethods { declareBinaryOp("or", Opcodes.IOR); declareBinaryOp("xor", Opcodes.IXOR); - declareIntrinsicFunction("Boolean", "not", 0, new Not()); + declareIntrinsicFunction("Boolean", "not", 0, new Not(), true); - declareIntrinsicFunction("String", "plus", 1, new Concat()); - declareIntrinsicFunction("CharSequence", "get", 1, new StringGetChar()); + declareIntrinsicFunction("String", "plus", 1, new Concat(), true); + declareIntrinsicFunction("CharSequence", "get", 1, new StringGetChar(), true); + declareIntrinsicFunction("String", "get", 1, new StringGetChar(), true); declareOverload(myStdLib.getLibraryScope().getFunctions("toString"), 0, new ToString()); declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, EQUALS); @@ -99,22 +104,23 @@ public class IntrinsicMethods { declareOverload(myStdLib.getLibraryScope().getFunctions("synchronized"), 2, new StupidSync()); declareOverload(myStdLib.getLibraryScope().getFunctions("iterator"), 0, new IteratorIterator()); - declareIntrinsicFunction("ByteIterator", "next", 0, ITERATOR_NEXT); - declareIntrinsicFunction("ShortIterator", "next", 0, ITERATOR_NEXT); - declareIntrinsicFunction("IntIterator", "next", 0, ITERATOR_NEXT); - declareIntrinsicFunction("LongIterator", "next", 0, ITERATOR_NEXT); - declareIntrinsicFunction("CharIterator", "next", 0, ITERATOR_NEXT); - declareIntrinsicFunction("BooleanIterator", "next", 0, ITERATOR_NEXT); - declareIntrinsicFunction("FloatIterator", "next", 0, ITERATOR_NEXT); - declareIntrinsicFunction("DoubleIterator", "next", 0, ITERATOR_NEXT); + declareIntrinsicFunction("ByteIterator", "next", 0, ITERATOR_NEXT, false); + declareIntrinsicFunction("ShortIterator", "next", 0, ITERATOR_NEXT, false); + declareIntrinsicFunction("IntIterator", "next", 0, ITERATOR_NEXT, false); + declareIntrinsicFunction("LongIterator", "next", 0, ITERATOR_NEXT, false); + declareIntrinsicFunction("CharIterator", "next", 0, ITERATOR_NEXT, false); + declareIntrinsicFunction("BooleanIterator", "next", 0, ITERATOR_NEXT, false); + declareIntrinsicFunction("FloatIterator", "next", 0, ITERATOR_NEXT, false); + declareIntrinsicFunction("DoubleIterator", "next", 0, ITERATOR_NEXT, false); - for (String type : PRIMITIVE_NUMBER_TYPES) { - declareIntrinsicFunction(type, "compareTo", 1, new CompareTo()); + for (String type : PRIMITIVE_TYPES) { + declareIntrinsicFunction(type, "compareTo", 1, new CompareTo(), false); } // declareIntrinsicFunction("Any", "equals", 1, new Equals()); // declareIntrinsicStringMethods(); declareIntrinsicProperty("CharSequence", "length", new StringLength()); + declareIntrinsicProperty("String", "length", new StringLength()); declareArrayMethods(); } @@ -127,8 +133,8 @@ public class IntrinsicMethods { declareIntrinsicProperty("Array", "size", ARRAY_SIZE); declareIntrinsicProperty("Array", "indices", ARRAY_INDICES); - declareIntrinsicFunction("Array", "set", 2, ARRAY_SET); - declareIntrinsicFunction("Array", "get", 1, ARRAY_GET); + declareIntrinsicFunction("Array", "set", 2, ARRAY_SET, true); + declareIntrinsicFunction("Array", "get", 1, ARRAY_GET, true); declareIterator(myStdLib.getArray()); } @@ -136,8 +142,8 @@ public class IntrinsicMethods { PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType(); declareIntrinsicProperty(primitiveType.getArrayTypeName(), "size", ARRAY_SIZE); declareIntrinsicProperty(primitiveType.getArrayTypeName(), "indices", ARRAY_INDICES); - declareIntrinsicFunction(primitiveType.getArrayTypeName(), "set", 2, ARRAY_SET); - declareIntrinsicFunction(primitiveType.getArrayTypeName(), "get", 1, ARRAY_GET); + declareIntrinsicFunction(primitiveType.getArrayTypeName(), "set", 2, ARRAY_SET, true); + declareIntrinsicFunction(primitiveType.getArrayTypeName(), "get", 1, ARRAY_GET, true); declareIterator(myStdLib.getPrimitiveArrayClassDescriptor(primitiveType)); } @@ -173,8 +179,8 @@ public class IntrinsicMethods { private void declareBinaryOp(String methodName, int opcode) { BinaryOp op = new BinaryOp(opcode); - for (String type : PRIMITIVE_NUMBER_TYPES) { - declareIntrinsicFunction(type, methodName, 1, op); + for (String type : PRIMITIVE_TYPES) { + declareIntrinsicFunction(type, methodName, 1, op, false); } } @@ -186,12 +192,12 @@ public class IntrinsicMethods { myMethods.put(property.getOriginal(), implementation); } - private void declareIntrinsicFunction(String className, String functionName, int arity, IntrinsicMethod implementation) { + private void declareIntrinsicFunction(String className, String functionName, int arity, IntrinsicMethod implementation, boolean original) { JetScope memberScope = getClassMemberScope(className); final Set group = memberScope.getFunctions(functionName); for (FunctionDescriptor descriptor : group) { if (className.equals(descriptor.getContainingDeclaration().getName()) && descriptor.getValueParameters().size() == arity) { - myMethods.put(descriptor.getOriginal(), implementation); + myMethods.put(original ? descriptor.getOriginal() : descriptor, implementation); } } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index dd817e41513..14843c4d1e4 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -1045,15 +1045,16 @@ public class JavaDescriptorResolver { resolveVisibilityFromPsiModifiers(anyMember.getMember().psiMember), isVar, false, - propertyName); + propertyName, + CallableMemberDescriptor.Kind.DECLARATION); PropertyGetterDescriptor getterDescriptor = null; PropertySetterDescriptor setterDescriptor = null; if (members.getter != null) { - getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false); + getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false, CallableMemberDescriptor.Kind.DECLARATION); } if (members.setter != null) { - setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false); + setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false, CallableMemberDescriptor.Kind.DECLARATION); } propertyDescriptor.initialize(getterDescriptor, setterDescriptor); @@ -1111,7 +1112,7 @@ public class JavaDescriptorResolver { getterDescriptor.initialize(propertyType); } if (setterDescriptor != null) { - // TODO: initialize + setterDescriptor.initialize(new ValueParameterDescriptorImpl(setterDescriptor, 0, Collections.emptyList(), "p0"/*TODO*/, false, propertyDescriptor.getOutType(), false, null)); } semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember.getMember().psiMember, propertyDescriptor); @@ -1337,7 +1338,8 @@ public class JavaDescriptorResolver { NamedFunctionDescriptorImpl functionDescriptorImpl = new NamedFunctionDescriptorImpl( owner, Collections.emptyList(), // TODO - method.getName() + method.getName(), + CallableMemberDescriptor.Kind.DECLARATION ); methodDescriptorCache.put(method.getPsiMethod(), functionDescriptorImpl); 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 db805687a7b..d1b673f5833 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableMemberDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/CallableMemberDescriptor.java @@ -12,6 +12,22 @@ public interface CallableMemberDescriptor extends CallableDescriptor, MemberDesc @Override Set getOverriddenDescriptors(); + public enum Kind { + DECLARATION, + FAKE_OVERRIDE, + DELEGATION, + ; + + public boolean isReal() { + return this == DECLARATION || this == DELEGATION; + } + } + + /** + * Is this a real function or function projection. + */ + Kind getKind(); + @NotNull - CallableMemberDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract); + CallableMemberDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract, Kind kind, boolean copyOverrides); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java index 01a44fa52d5..a61c0a076dc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ConstructorDescriptorImpl.java @@ -19,12 +19,12 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements private final boolean isPrimary; public ConstructorDescriptorImpl(@NotNull ClassDescriptor containingDeclaration, @NotNull List annotations, boolean isPrimary) { - super(containingDeclaration, annotations, ""); + super(containingDeclaration, annotations, "", Kind.DECLARATION); this.isPrimary = isPrimary; } public ConstructorDescriptorImpl(@NotNull ClassDescriptor containingDeclaration, @NotNull ConstructorDescriptor original, @NotNull List annotations, boolean isPrimary) { - super(containingDeclaration, original, annotations, ""); + super(containingDeclaration, original, annotations, "", Kind.DECLARATION); this.isPrimary = isPrimary; } @@ -85,7 +85,10 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements } @Override - protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal) { + protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal, Kind kind) { + if (kind != Kind.DECLARATION) { + throw new IllegalStateException(); + } return new ConstructorDescriptorImpl( (ClassDescriptor) newOwner, this, @@ -95,7 +98,7 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements @NotNull @Override - public ConstructorDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) { + public ConstructorDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract, Kind kind, boolean copyOverrides) { throw new UnsupportedOperationException("Constructors should not be copied for overriding"); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java index e69f6d3cbe2..40e7a128b12 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptor.java @@ -26,5 +26,5 @@ public interface FunctionDescriptor extends CallableMemberDescriptor { @NotNull @Override - FunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract); + FunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract, Kind kind, boolean copyOverrides); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java index 810b9907b0c..82013e25688 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java @@ -31,24 +31,29 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorImpl i protected Modality modality; protected Visibility visibility; - private final Set overriddenFunctions = Sets.newLinkedHashSet(); + protected final Set overriddenFunctions = Sets.newLinkedHashSet(); private final FunctionDescriptor original; + private final Kind kind; protected FunctionDescriptorImpl( @NotNull DeclarationDescriptor containingDeclaration, @NotNull List annotations, - @NotNull String name) { + @NotNull String name, + Kind kind) { super(containingDeclaration, annotations, name); this.original = this; + this.kind = kind; } protected FunctionDescriptorImpl( - @NotNull DeclarationDescriptor containigDeclaration, + @NotNull DeclarationDescriptor containingDeclaration, @NotNull FunctionDescriptor original, @NotNull List annotations, - @NotNull String name) { - super(containigDeclaration, annotations, name); + @NotNull String name, + Kind kind) { + super(containingDeclaration, annotations, name); this.original = original; + this.kind = kind; } public FunctionDescriptorImpl initialize( @@ -146,17 +151,22 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorImpl i return original == this ? this : original.getOriginal(); } + @Override + public Kind getKind() { + return kind; + } + @Override public final FunctionDescriptor substitute(TypeSubstitutor originalSubstitutor) { if (originalSubstitutor.isEmpty()) { return this; } - return doSubstitute(originalSubstitutor, getContainingDeclaration(), modality, true); + return doSubstitute(originalSubstitutor, getContainingDeclaration(), modality, true, true, getKind()); } protected FunctionDescriptor doSubstitute(TypeSubstitutor originalSubstitutor, - DeclarationDescriptor newOwner, Modality newModality, boolean preserveOriginal) { - FunctionDescriptorImpl substitutedDescriptor = createSubstitutedCopy(newOwner, preserveOriginal); + DeclarationDescriptor newOwner, Modality newModality, boolean preserveOriginal, boolean copyOverrides, Kind kind) { + FunctionDescriptorImpl substitutedDescriptor = createSubstitutedCopy(newOwner, preserveOriginal, kind); List substitutedTypeParameters = Lists.newArrayList(); TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters); @@ -197,13 +207,15 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorImpl i newModality, visibility ); - for (FunctionDescriptor overriddenFunction : overriddenFunctions) { - substitutedDescriptor.addOverriddenFunction(overriddenFunction); + if (copyOverrides) { + for (FunctionDescriptor overriddenFunction : overriddenFunctions) { + substitutedDescriptor.addOverriddenFunction(overriddenFunction.substitute(substitutor)); + } } return substitutedDescriptor; } - protected abstract FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal); + protected abstract FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal, Kind kind); @Override public R accept(DeclarationDescriptorVisitor visitor, D data) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java index 631190d57cd..3b6ffd5dd49 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java @@ -46,7 +46,7 @@ public class FunctionDescriptorUtil { } @Nullable - public static List getSubstitutedValueParameters(FunctionDescriptor substitutedDescriptor, @NotNull FunctionDescriptor functionDescriptor, TypeSubstitutor substitutor) { + public static List getSubstitutedValueParameters(FunctionDescriptor substitutedDescriptor, @NotNull FunctionDescriptor functionDescriptor, @NotNull TypeSubstitutor substitutor) { List result = new ArrayList(); List unsubstitutedValueParameters = functionDescriptor.getValueParameters(); for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java index c7e45fd090e..bee872a2149 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptorLite.java @@ -104,17 +104,11 @@ public class MutableClassDescriptorLite extends MutableDeclarationDescriptor imp } } - private WritableScope getScopeForMemberLookupAsWritableScope() { + public WritableScope getScopeForMemberLookupAsWritableScope() { // hack return (WritableScope) scopeForMemberLookup; } - public void addSupertypesToScopeForMemberLookup() { - for (JetType supertype : supertypes) { - getScopeForMemberLookupAsWritableScope().importScope(supertype.getMemberScope()); - } - } - @NotNull @Override public JetScope getMemberScope(List typeArguments) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamedFunctionDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamedFunctionDescriptor.java index 52668469719..23767dd417a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamedFunctionDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamedFunctionDescriptor.java @@ -11,5 +11,9 @@ public interface NamedFunctionDescriptor extends FunctionDescriptor { @NotNull @Override - NamedFunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract); + NamedFunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract, Kind kind, boolean copyOverrides); + + @NotNull + @Override + NamedFunctionDescriptor getOriginal(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamedFunctionDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamedFunctionDescriptorImpl.java index 9e8b89c41bc..e36bc27db41 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamedFunctionDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamedFunctionDescriptorImpl.java @@ -1,6 +1,5 @@ package org.jetbrains.jet.lang.descriptors; -import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.DescriptorUtils; @@ -13,12 +12,21 @@ import java.util.List; */ public class NamedFunctionDescriptorImpl extends FunctionDescriptorImpl implements NamedFunctionDescriptor { - public NamedFunctionDescriptorImpl(@NotNull DeclarationDescriptor containingDeclaration, @NotNull List annotations, @NotNull String name) { - super(containingDeclaration, annotations, name); + public NamedFunctionDescriptorImpl( + @NotNull DeclarationDescriptor containingDeclaration, + @NotNull List annotations, + @NotNull String name, + Kind kind) { + super(containingDeclaration, annotations, name, kind); } - private NamedFunctionDescriptorImpl(@NotNull DeclarationDescriptor containingDeclaration, @NotNull NamedFunctionDescriptor original, @NotNull List annotations, @NotNull String name) { - super(containingDeclaration, original, annotations, name); + private NamedFunctionDescriptorImpl( + @NotNull DeclarationDescriptor containingDeclaration, + @NotNull NamedFunctionDescriptor original, + @NotNull List annotations, + @NotNull String name, + Kind kind) { + super(containingDeclaration, original, annotations, name, kind); } @NotNull @@ -28,26 +36,28 @@ public class NamedFunctionDescriptorImpl extends FunctionDescriptorImpl implemen } @Override - protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal) { + protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal, Kind kind) { if (preserveOriginal) { return new NamedFunctionDescriptorImpl( newOwner, getOriginal(), // TODO : safeSubstitute getAnnotations(), - getName()); + getName(), + kind); } else { return new NamedFunctionDescriptorImpl( newOwner, // TODO : safeSubstitute getAnnotations(), - getName()); + getName(), + kind); } } @NotNull @Override - public NamedFunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) { - return (NamedFunctionDescriptor) doSubstitute(TypeSubstitutor.EMPTY, newOwner, DescriptorUtils.convertModality(modality, makeNonAbstract), false); + public NamedFunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract, Kind kind, boolean copyOverrides) { + return (NamedFunctionDescriptor) doSubstitute(TypeSubstitutor.EMPTY, newOwner, DescriptorUtils.convertModality(modality, makeNonAbstract), false, copyOverrides, kind); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java index 93f2000146d..edbdd9f8f7f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyAccessorDescriptor.java @@ -20,6 +20,7 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm private final Modality modality; private final Visibility visibility; private final PropertyDescriptor correspondingProperty; + private final Kind kind; public PropertyAccessorDescriptor( @NotNull Modality modality, @@ -28,13 +29,15 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm @NotNull List annotations, @NotNull String name, boolean hasBody, - boolean isDefault) { + boolean isDefault, + Kind kind) { super(correspondingProperty.getContainingDeclaration(), annotations, name); this.modality = modality; this.visibility = visibility; this.correspondingProperty = correspondingProperty; this.hasBody = hasBody; this.isDefault = isDefault; + this.kind = kind; } public boolean hasBody() { @@ -45,6 +48,11 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm return isDefault; } + @Override + public Kind getKind() { + return kind; + } + @NotNull @Override public PropertyAccessorDescriptor getOriginal() { @@ -94,7 +102,7 @@ public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorIm @NotNull @Override - public PropertyAccessorDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) { + public PropertyAccessorDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract, Kind kind, boolean copyOverrides) { throw new UnsupportedOperationException("Accessors must be copied by the corresponding property"); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java index b535e241b16..7e469c7b89c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java @@ -32,6 +32,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab private final boolean isObject; private final Set overriddenProperties = Sets.newLinkedHashSet(); private final PropertyDescriptor original; + private final Kind kind; private ReceiverDescriptor expectedThisObject; private ReceiverDescriptor receiver; @@ -46,6 +47,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab this.isVar = false; this.isObject = false; this.original = null; + this.kind = Kind.DECLARATION; } private PropertyDescriptor( @@ -56,13 +58,15 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab @NotNull Visibility visibility, boolean isVar, boolean isObject, - @NotNull String name) { + @NotNull String name, + Kind kind) { super(containingDeclaration, annotations, name); this.isVar = isVar; this.isObject = isObject; this.modality = modality; this.visibility = visibility; this.original = original == null ? this : original.getOriginal(); + this.kind = kind; } public PropertyDescriptor( @@ -72,8 +76,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab @NotNull Visibility visibility, boolean isVar, boolean isObject, - @NotNull String name) { - this(null, containingDeclaration, annotations, modality, visibility, isVar, isObject, name); + @NotNull String name, + Kind kind) { + this(null, containingDeclaration, annotations, modality, visibility, isVar, isObject, name, kind); } public PropertyDescriptor( @@ -86,9 +91,10 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab @Nullable JetType receiverType, @NotNull ReceiverDescriptor expectedThisObject, @NotNull String name, - @NotNull JetType outType + @NotNull JetType outType, + Kind kind ) { - this(containingDeclaration, annotations, modality, visibility, isVar, isObject, name); + this(containingDeclaration, annotations, modality, visibility, isVar, isObject, name, kind); setType(outType, Collections.emptyList(), expectedThisObject, receiverType); } @@ -171,7 +177,13 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab if (originalSubstitutor.isEmpty()) { return this; } - PropertyDescriptor substitutedDescriptor = new PropertyDescriptor(this, getContainingDeclaration(), getAnnotations(), getModality(), getVisibility(), isVar(), isObjectDeclaration(), getName()); + return doSubstitute(originalSubstitutor, getContainingDeclaration(), modality, true, true, getKind()); + } + + private PropertyDescriptor doSubstitute(TypeSubstitutor originalSubstitutor, + DeclarationDescriptor newOwner, Modality newModality, boolean preserveOriginal, boolean copyOverrides, Kind kind) { + PropertyDescriptor substitutedDescriptor = new PropertyDescriptor(preserveOriginal ? getOriginal() : this, newOwner, + getAnnotations(), newModality, getVisibility(), isVar(), isObjectDeclaration(), getName(), kind); List substitutedTypeParameters = Lists.newArrayList(); TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters); @@ -202,6 +214,36 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab substitutedDescriptor.setType(outType, substitutedTypeParameters, substitutedExpectedThisObject, substitutedReceiverType); + PropertyGetterDescriptor newGetter = getter == null ? null : new PropertyGetterDescriptor( + substitutedDescriptor, Lists.newArrayList(getter.getAnnotations()), + DescriptorUtils.convertModality(getter.getModality(), false), getter.getVisibility(), + getter.hasBody(), getter.isDefault(), kind); + if (newGetter != null) { + JetType returnType = getter.getReturnType(); + newGetter.initialize(returnType != null ? substitutor.substitute(returnType, Variance.OUT_VARIANCE) : null); + } + PropertySetterDescriptor newSetter = setter == null ? null : new PropertySetterDescriptor( + substitutedDescriptor, Lists.newArrayList(setter.getAnnotations()), DescriptorUtils.convertModality(setter.getModality(), false), setter.getVisibility(), + setter.hasBody(), setter.isDefault(), kind); + if (newSetter != null) { + List substitutedValueParameters = FunctionDescriptorUtil.getSubstitutedValueParameters(newSetter, setter, substitutor); + if (substitutedValueParameters == null) { + return null; + } + if (substitutedValueParameters.size() != 1) { + throw new IllegalStateException(); + } + newSetter.initialize(substitutedValueParameters.get(0)); + } + + substitutedDescriptor.initialize(newGetter, newSetter); + + if (copyOverrides) { + for (PropertyDescriptor propertyDescriptor : overriddenProperties) { + substitutedDescriptor.addOverriddenDescriptor(propertyDescriptor.substitute(substitutor)); + } + } + return substitutedDescriptor; } @@ -216,6 +258,11 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab return original; } + @Override + public Kind getKind() { + return kind; + } + public void addOverriddenDescriptor(PropertyDescriptor overridden) { overriddenProperties.add(overridden); } @@ -228,30 +275,8 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab @NotNull @Override - public PropertyDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) { - PropertyDescriptor propertyDescriptor = new PropertyDescriptor( - newOwner, - Lists.newArrayList(getAnnotations()), - DescriptorUtils.convertModality(modality, makeNonAbstract), visibility, isVar, isObject, - getName()); - - propertyDescriptor.setType(getOutType(), DescriptorUtils.copyTypeParameters(propertyDescriptor, getTypeParameters()), expectedThisObject, receiver.exists() ? receiver.getType() : null); - - PropertyGetterDescriptor newGetter = getter == null ? null : new PropertyGetterDescriptor( - propertyDescriptor, Lists.newArrayList(getter.getAnnotations()), - DescriptorUtils.convertModality(getter.getModality(), makeNonAbstract), getter.getVisibility(), - getter.hasBody(), getter.isDefault()); - if (newGetter != null) { - newGetter.initialize(getter.getReturnType()); - } - PropertySetterDescriptor newSetter = setter == null ? null : new PropertySetterDescriptor( - propertyDescriptor, Lists.newArrayList(setter.getAnnotations()), DescriptorUtils.convertModality(setter.getModality(), makeNonAbstract), setter.getVisibility(), - setter.hasBody(), setter.isDefault()); - if (newSetter != null) { - newSetter.initialize(setter.getValueParameters().get(0).copy(newSetter)); - } - propertyDescriptor.initialize(newGetter, newSetter); - return propertyDescriptor; + public PropertyDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract, Kind kind, boolean copyOverrides) { + return doSubstitute(TypeSubstitutor.EMPTY, newOwner, DescriptorUtils.convertModality(modality, makeNonAbstract), false, copyOverrides, kind); } public static PropertyDescriptor createDummy() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java index 2574235361c..f4744baaa9f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyGetterDescriptor.java @@ -18,9 +18,9 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor { private JetType returnType; public PropertyGetterDescriptor(@NotNull PropertyDescriptor correspondingProperty, @NotNull List annotations, - @NotNull Modality modality, @NotNull Visibility visibility, boolean hasBody, boolean isDefault) + @NotNull Modality modality, @NotNull Visibility visibility, boolean hasBody, boolean isDefault, Kind kind) { - super(modality, visibility, correspondingProperty, annotations, "get-" + correspondingProperty.getName(), hasBody, isDefault); + super(modality, visibility, correspondingProperty, annotations, "get-" + correspondingProperty.getName(), hasBody, isDefault, kind); } public void initialize(JetType returnType) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java index 8a64c457b48..d4581676929 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java @@ -22,8 +22,9 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor { @NotNull Modality modality, @NotNull Visibility visibility, boolean hasBody, - boolean isDefault) { - super(modality, visibility, correspondingProperty, annotations, "set-" + correspondingProperty.getName(), hasBody, isDefault); + boolean isDefault, + Kind kind) { + super(modality, visibility, correspondingProperty, annotations, "set-" + correspondingProperty.getName(), hasBody, isDefault, kind); } public void initialize(@NotNull ValueParameterDescriptor parameter) { @@ -45,6 +46,9 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor { @NotNull @Override public List getValueParameters() { + if (parameter == null) { + throw new IllegalStateException(); + } return Collections.singletonList(parameter); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java index 939104ff740..7fff1e3decc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java @@ -238,7 +238,8 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement @NotNull public TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) { TypeParameterDescriptor copy = new TypeParameterDescriptor(newOwner, Lists.newArrayList(getAnnotations()), reified, variance, getName(), index); + copy.upperBounds.addAll(this.upperBounds); copy.initialized = this.initialized; - return copy; + return copy; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java index a17dae91e33..280b3455d47 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/VariableAsFunctionDescriptor.java @@ -21,7 +21,7 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl { private final VariableDescriptor variableDescriptor; private VariableAsFunctionDescriptor(VariableDescriptor variableDescriptor) { - super(variableDescriptor.getContainingDeclaration(), Collections.emptyList(), variableDescriptor.getName()); + super(variableDescriptor.getContainingDeclaration(), Collections.emptyList(), variableDescriptor.getName(), Kind.DECLARATION); this.variableDescriptor = variableDescriptor; } @@ -31,12 +31,12 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl { @NotNull @Override - public VariableAsFunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) { + public VariableAsFunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract, Kind kind, boolean copyOverrides) { throw new UnsupportedOperationException("Should not be copied for overriding"); } @Override - protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal) { + protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal, Kind kind) { throw new IllegalStateException(); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index a0fe615ff63..56c773d3150 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -16,6 +16,7 @@ import org.jetbrains.jet.util.Box; import org.jetbrains.jet.util.slicedmap.*; import java.util.Collection; +import java.util.Set; import static org.jetbrains.jet.util.slicedmap.RewritePolicy.DO_NOTHING; @@ -65,6 +66,9 @@ public interface BindingContext { WritableSlice BACKING_FIELD_REQUIRED = new Slices.SetSlice(DO_NOTHING) { @Override public Boolean computeValue(SlicedMap map, PropertyDescriptor propertyDescriptor, Boolean backingFieldRequired, boolean valueNotFound) { + if (propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) { + return false; + } backingFieldRequired = valueNotFound ? false : backingFieldRequired; assert backingFieldRequired != null; PsiElement declarationPsiElement = map.get(DESCRIPTOR_TO_DECLARATION, propertyDescriptor); @@ -105,6 +109,18 @@ public interface BindingContext { Slices.KeyNormalizer DECLARATION_DESCRIPTOR_NORMALIZER = new Slices.KeyNormalizer() { @Override public DeclarationDescriptor normalize(DeclarationDescriptor declarationDescriptor) { + if (declarationDescriptor instanceof CallableMemberDescriptor) { + CallableMemberDescriptor callable = (CallableMemberDescriptor) declarationDescriptor; + if (callable.getKind() != CallableMemberDescriptor.Kind.DECLARATION) { + Set overriddenDescriptors = callable.getOverriddenDescriptors(); + if (overriddenDescriptors.size() != 1) { + throw new IllegalStateException( + "cannot find declaration: fake descriptor" + + " has more then one overriden descriptor: " + declarationDescriptor); + } + return normalize(overriddenDescriptors.iterator().next()); + } + } if (declarationDescriptor instanceof VariableAsFunctionDescriptor) { VariableAsFunctionDescriptor descriptor = (VariableAsFunctionDescriptor) declarationDescriptor; return descriptor.getVariableDescriptor().getOriginal(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java index 1fae05541a9..42043b65fb5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java @@ -1,7 +1,7 @@ package org.jetbrains.jet.lang.resolve; +import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.MutableClassDescriptor; import org.jetbrains.jet.lang.descriptors.NamedFunctionDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; @@ -45,7 +45,7 @@ public class DelegationResolver { if (declarationDescriptor instanceof PropertyDescriptor) { PropertyDescriptor propertyDescriptor = (PropertyDescriptor) declarationDescriptor; if (propertyDescriptor.getModality().isOverridable()) { - PropertyDescriptor copy = propertyDescriptor.copy(classDescriptor, true); + PropertyDescriptor copy = propertyDescriptor.copy(classDescriptor, true, CallableMemberDescriptor.Kind.DELEGATION, true); classDescriptor.addPropertyDescriptor(copy); context.getTrace().record(DELEGATED, copy); } @@ -53,7 +53,7 @@ public class DelegationResolver { else if (declarationDescriptor instanceof NamedFunctionDescriptor) { NamedFunctionDescriptor functionDescriptor = (NamedFunctionDescriptor) declarationDescriptor; if (functionDescriptor.getModality().isOverridable()) { - NamedFunctionDescriptor copy = functionDescriptor.copy(classDescriptor, true); + NamedFunctionDescriptor copy = functionDescriptor.copy(classDescriptor, true, CallableMemberDescriptor.Kind.DELEGATION, true); classDescriptor.addFunctionDescriptor(copy); context.getTrace().record(DELEGATED, copy); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 17d28db95bf..8bd21f46b7d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -142,7 +142,8 @@ public class DescriptorResolver { final NamedFunctionDescriptorImpl functionDescriptor = new NamedFunctionDescriptorImpl( containingDescriptor, annotationResolver.resolveAnnotations(scope, function.getModifierList()), - JetPsiUtil.safeName(function.getName()) + JetPsiUtil.safeName(function.getName()), + CallableMemberDescriptor.Kind.DECLARATION ); WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function descriptor header scope"); innerScope.addLabeledDeclaration(functionDescriptor); @@ -470,7 +471,8 @@ public class DescriptorResolver { visibility, false, true, - JetPsiUtil.safeName(objectDeclaration.getName()) + JetPsiUtil.safeName(objectDeclaration.getName()), + CallableMemberDescriptor.Kind.DECLARATION ); propertyDescriptor.setType(classDescriptor.getDefaultType(), Collections.emptyList(), DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), ReceiverDescriptor.NO_RECEIVER); propertyDescriptor.initialize(createDefaultGetter(propertyDescriptor), null); @@ -527,7 +529,8 @@ public class DescriptorResolver { resolveVisibilityFromModifiers(property.getModifierList()), isVar, false, - JetPsiUtil.safeName(property.getName()) + JetPsiUtil.safeName(property.getName()), + CallableMemberDescriptor.Kind.DECLARATION ); List typeParameterDescriptors; @@ -677,7 +680,7 @@ public class DescriptorResolver { setterDescriptor = new PropertySetterDescriptor( propertyDescriptor, annotations, resolveModalityFromModifiers(setter.getModifierList(), propertyDescriptor.getModality()), resolveVisibilityFromModifiers(setter.getModifierList(), propertyDescriptor.getVisibility()), - setter.getBodyExpression() != null, false); + setter.getBodyExpression() != null, false, CallableMemberDescriptor.Kind.DECLARATION); if (parameter != null) { // This check is redundant: the parser does not allow a default value, but we'll keep it just in case @@ -731,7 +734,7 @@ public class DescriptorResolver { setterDescriptor = new PropertySetterDescriptor( propertyDescriptor, Collections.emptyList(), propertyDescriptor.getModality(), propertyDescriptor.getVisibility(), - false, true); + false, true, CallableMemberDescriptor.Kind.DECLARATION); setterDescriptor.initializeDefault(); return setterDescriptor; } @@ -757,7 +760,7 @@ public class DescriptorResolver { getterDescriptor = new PropertyGetterDescriptor( propertyDescriptor, annotations, resolveModalityFromModifiers(getter.getModifierList(), propertyDescriptor.getModality()), resolveVisibilityFromModifiers(getter.getModifierList(), propertyDescriptor.getVisibility()), - getter.getBodyExpression() != null, false); + getter.getBodyExpression() != null, false, CallableMemberDescriptor.Kind.DECLARATION); getterDescriptor.initialize(returnType); trace.record(BindingContext.PROPERTY_ACCESSOR, getter, getterDescriptor); } @@ -773,7 +776,7 @@ public class DescriptorResolver { getterDescriptor = new PropertyGetterDescriptor( propertyDescriptor, Collections.emptyList(), propertyDescriptor.getModality(), propertyDescriptor.getVisibility(), - false, true); + false, true, CallableMemberDescriptor.Kind.DECLARATION); return getterDescriptor; } @@ -845,7 +848,8 @@ public class DescriptorResolver { resolveVisibilityFromModifiers(parameter.getModifierList()), isMutable, false, - name == null ? "" : name + name == null ? "" : name, + CallableMemberDescriptor.Kind.DECLARATION ); propertyDescriptor.setType(type, Collections.emptyList(), DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor), ReceiverDescriptor.NO_RECEIVER); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index 0cf691552af..b51f51a91af 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -1,20 +1,23 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; +import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.util.CommonSuppliers; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -34,46 +37,205 @@ public class OverrideResolver { } public void process() { - bindOverrides(); + generateOverrides(); checkOverrides(); } - private void bindOverrides() { - for (Map.Entry entry : context.getClasses().entrySet()) { - bindOverridesInAClass(entry.getValue()); - } - for (Map.Entry entry : context.getObjects().entrySet()) { - bindOverridesInAClass(entry.getValue()); + /** + * Generate fake overrides and add overriden descriptors to existing descriptors. + */ + private void generateOverrides() { + Set ourClasses = new HashSet(); + ourClasses.addAll(context.getClasses().values()); + ourClasses.addAll(context.getObjects().values()); + + Set processed = new HashSet(); + + for (MutableClassDescriptor clazz : ourClasses) { + generateOverridesInAClass(clazz, processed, ourClasses); } } - private void bindOverridesInAClass(MutableClassDescriptor classDescriptor) { - for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { - for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { - Collection overridden = findFunctionsOverridableBy(declaredFunction, supertype); - for (FunctionDescriptor functionDescriptor : overridden) { - ((FunctionDescriptorImpl) declaredFunction).addOverriddenFunction(functionDescriptor); - } + private void generateOverridesInAClass(final MutableClassDescriptor classDescriptor, Set processed, Set ourClasses) { + if (!processed.add(classDescriptor)) { + return; + } + + // avoid processing stdlib classes twice + if (!ourClasses.contains(classDescriptor)) { + return; + } + + for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { + ClassDescriptor superclass = (ClassDescriptor) supertype.getConstructor().getDeclarationDescriptor(); + if (superclass instanceof MutableClassDescriptor) { + generateOverridesInAClass((MutableClassDescriptor) superclass, processed, ourClasses); } } - for (PropertyDescriptor propertyDescriptor : classDescriptor.getProperties()) { - for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { - Collection overridden = findPropertiesOverridableBy(propertyDescriptor, supertype); - for (PropertyDescriptor descriptor : overridden) { - propertyDescriptor.addOverriddenDescriptor(descriptor); + List functionsFromSupertypes = getDescriptorsFromSupertypes(classDescriptor, NamedFunctionDescriptor.class); + List propertiesFromSupertypes = getDescriptorsFromSupertypes(classDescriptor, PropertyDescriptor.class); + + MultiMap functionsFromSupertypesByName = groupDescriptorsByName(functionsFromSupertypes); + MultiMap propertiesFromSupertypesByName = groupDescriptorsByName(propertiesFromSupertypes); + + MultiMap functionsFromCurrentByName = groupDescriptorsByName(classDescriptor.getFunctions()); + MultiMap propertiesFromCurrentByName = groupDescriptorsByName(classDescriptor.getProperties()); + + Set functionNames = new HashSet(); + functionNames.addAll(functionsFromSupertypesByName.keySet()); + functionNames.addAll(functionsFromCurrentByName.keySet()); + + Set propertyNames = new HashSet(); + propertyNames.addAll(propertiesFromSupertypesByName.keySet()); + propertyNames.addAll(propertiesFromCurrentByName.keySet()); + + + for (String functionName : functionNames) { + generateOverridesInFunctionGroup(functionName, + functionsFromSupertypesByName.get(functionName), + functionsFromCurrentByName.get(functionName), + classDescriptor, + new DescriptorSink() { + @Override + public void addToScope(NamedFunctionDescriptor fakeOverride) { + classDescriptor.getScopeForMemberLookupAsWritableScope().addFunctionDescriptor(fakeOverride); + } + }); + } + + for (String propertyName : propertyNames) { + generateOverridesInPropertyGroup(propertyName, + propertiesFromSupertypesByName.get(propertyName), + propertiesFromCurrentByName.get(propertyName), + classDescriptor, + new DescriptorSink() { + @Override + public void addToScope(PropertyDescriptor fakeOverride) { + classDescriptor.getScopeForMemberLookupAsWritableScope().addPropertyDescriptor(fakeOverride); + } + }); + } + } + + public interface DescriptorSink { + void addToScope(D fakeOverride); + } + + public static void generateOverridesInFunctionGroup( + @NotNull String name, + @NotNull Collection functionsFromSupertypes, + @NotNull Collection functionsFromCurrent, + @NotNull ClassDescriptor current, + @NotNull DescriptorSink sink) { + + List fakeOverrides = Lists.newArrayList(); + + for (NamedFunctionDescriptor functionFromSupertype : functionsFromSupertypes) { + + boolean overrides = false; + + for (NamedFunctionDescriptor functionFromCurrent : functionsFromCurrent) { + if (OverridingUtil.isOverridableBy(functionFromSupertype, functionFromCurrent).isSuccess()) { + ((FunctionDescriptorImpl) functionFromCurrent).addOverriddenFunction(functionFromSupertype); + overrides = true; } } + + for (NamedFunctionDescriptor fakeOverride : fakeOverrides) { + if (OverridingUtil.isOverridableBy(functionFromSupertype, fakeOverride).isSuccess()) { + ((FunctionDescriptorImpl) fakeOverride).addOverriddenFunction(functionFromSupertype); + overrides = true; + } + } + + if (!overrides) { + NamedFunctionDescriptor fakeOverride = functionFromSupertype.copy(current, false, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); + ((FunctionDescriptorImpl) fakeOverride).addOverriddenFunction(functionFromSupertype); + + fakeOverrides.add(fakeOverride); + + sink.addToScope(fakeOverride); + } } } + + public static void generateOverridesInPropertyGroup( + @NotNull String name, + @NotNull Collection propertiesFromSupertypes, + @NotNull Collection propertiesFromCurrent, + @NotNull ClassDescriptor current, + @NotNull DescriptorSink sink) { + + List fakeOverrides = Lists.newArrayList(); + + for (PropertyDescriptor propertyFromSupertype : propertiesFromSupertypes) { + boolean overrides = false; + for (PropertyDescriptor propertyFromCurrent : propertiesFromCurrent) { + if (OverridingUtil.isOverridableBy(propertyFromSupertype, propertyFromCurrent).isSuccess()) { + propertyFromCurrent.addOverriddenDescriptor(propertyFromSupertype); + overrides = true; + } + } + + for (PropertyDescriptor fakeOverride : fakeOverrides) { + if (OverridingUtil.isOverridableBy(propertyFromSupertype, fakeOverride).isSuccess()) { + ((PropertyDescriptor) fakeOverride).addOverriddenDescriptor(propertyFromSupertype); + overrides = true; + } + } + + if (!overrides) { + PropertyDescriptor fakeOverride = propertyFromSupertype.copy(current, false, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); + fakeOverride.addOverriddenDescriptor(propertyFromSupertype); + + fakeOverrides.add(fakeOverride); + + sink.addToScope(fakeOverride); + } + } + } + + + private static MultiMap groupDescriptorsByName(Collection properties) { + MultiMap r = new MultiMap(); + for (T property : properties) { + r.putValue(property.getName(), property); + } + return r; + } + + + private static List getDescriptorsFromSupertypes( + ClassDescriptor classDescriptor, Class descriptorClass) { + Set r = Sets.newHashSet(); + for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { + r.addAll(getDescriptorsOfType(supertype.getMemberScope(), descriptorClass)); + } + return new ArrayList(r); + } + + private static List getDescriptorsOfType( + JetScope scope, Class descriptorClass) { + List r = Lists.newArrayList(); + for (DeclarationDescriptor decl : scope.getAllDescriptors()) { + if (descriptorClass.isInstance(decl)) { + r.add((T) decl); + } + } + return r; + } @NotNull private Collection findFunctionsOverridableBy(@NotNull FunctionDescriptor declaredFunction, @NotNull JetType supertype) { List result = Lists.newArrayList(); + List result2 = Lists.newArrayList(); Set functionGroup = supertype.getMemberScope().getFunctions(declaredFunction.getName()); for (FunctionDescriptor functionDescriptor : functionGroup) { if (OverridingUtil.isOverridableBy(functionDescriptor, declaredFunction).isSuccess()) { result.add(functionDescriptor); + } else { + result2.add(functionDescriptor); } } return result; @@ -172,37 +334,32 @@ public class OverrideResolver { } public static void collectMissingImplementations(MutableClassDescriptor classDescriptor, Set abstractNoImpl, Set manyImpl) { - // Everything from supertypes - Map implementedWithDelegationBy = Maps.newHashMap(); - Multimap factoredMembers = collectSuperMethods(classDescriptor); + + for (DeclarationDescriptor descriptor : classDescriptor.getScopeForMemberLookup().getAllDescriptors()) { + if (descriptor instanceof CallableMemberDescriptor) { + collectMissingImplementations((CallableMemberDescriptor) descriptor, abstractNoImpl, manyImpl); + } + } + } - for (CallableMemberDescriptor key : factoredMembers.keySet()) { - Collection mutuallyOverridable = factoredMembers.get(key); - - int implementationCount = 0; - for (CallableMemberDescriptor member : mutuallyOverridable) { - if (member.getModality() != Modality.ABSTRACT) { - implementationCount++; + private static void collectMissingImplementations(CallableMemberDescriptor descriptor, Set abstractNoImpl, Set manyImpl) { + if (descriptor.getKind().isReal()) { + if (descriptor.getModality() == Modality.ABSTRACT) { + //abstractNoImpl.add(descriptor); + } + } else { + Collection overridenDeclarations = OverridingUtil.getOverridenDeclarations(descriptor); + if (overridenDeclarations.size() == 0) { + throw new IllegalStateException(); + } else if (overridenDeclarations.size() == 1) { + CallableMemberDescriptor single = overridenDeclarations.iterator().next(); + if (single.getModality() == Modality.ABSTRACT) { + abstractNoImpl.add(single); } - } - - if (implementationCount == 0) { - abstractNoImpl.addAll(mutuallyOverridable); - } - else if (implementationCount > 1) { - manyImpl.addAll(mutuallyOverridable); + } else { + manyImpl.addAll(overridenDeclarations); } } - - // Members actually present (declared) in the class - Set actuallyOverridden = Sets.newHashSet(implementedWithDelegationBy.keySet()); - for (CallableMemberDescriptor member : classDescriptor.getCallableMembers()) { - actuallyOverridden.addAll(member.getOverriddenDescriptors()); - } - - // Those to be overridden that are actually not - abstractNoImpl.removeAll(actuallyOverridden); - manyImpl.removeAll(actuallyOverridden); } public static Multimap collectSuperMethods(MutableClassDescriptor classDescriptor) { @@ -242,6 +399,10 @@ public class OverrideResolver { return; } + if (declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION) { + return; + } + JetModifierList modifierList = member.getModifierList(); ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null; boolean hasOverrideModifier = overrideNode != null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java index ef3f839a5e5..38ecf4b4964 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -4,6 +4,7 @@ import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import com.intellij.openapi.util.Pair; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; @@ -21,21 +22,6 @@ public class OverridingUtil { private OverridingUtil() { } - public static Set getEffectiveMembers(@NotNull ClassDescriptor classDescriptor) { - Collection allDescriptors = classDescriptor.getDefaultType().getMemberScope().getAllDescriptors(); - Set allMembers = Sets.newLinkedHashSet(); - for (DeclarationDescriptor descriptor : allDescriptors) { - assert !(descriptor instanceof ConstructorDescriptor); - if (descriptor instanceof CallableDescriptor && descriptor instanceof MemberDescriptor) { - CallableDescriptor callableDescriptor = (CallableDescriptor) descriptor; - if (((MemberDescriptor) descriptor).getModality() != Modality.ABSTRACT) { - allMembers.add(callableDescriptor); - } - } - } - return filterOverrides(allMembers); - } - public static Set filterOverrides(Set candidateSet) { return filterOverrides(candidateSet, Function.ID); } @@ -198,6 +184,30 @@ public class OverridingUtil { return true; } + /** + * Get overriden descriptors that are declarations or delegations. + * + * @see CallableMemberDescriptor.Kind#isReal() + */ + public static Collection getOverridenDeclarations(CallableMemberDescriptor descriptor) { + Map result = Maps.newHashMap(); + getOverridenDeclarations(descriptor, result); + return result.values(); + } + + private static void getOverridenDeclarations(CallableMemberDescriptor descriptor, Map r) { + if (descriptor.getKind().isReal()) { + r.put((ClassDescriptor) descriptor.getContainingDeclaration(), descriptor); + } else { + if (descriptor.getOverriddenDescriptors().isEmpty()) { + throw new IllegalStateException(); + } + for (CallableMemberDescriptor overriden : descriptor.getOverriddenDescriptors()) { + getOverridenDeclarations(overriden, r); + } + } + } + public static class OverrideCompatibilityInfo { private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(true, "SUCCESS"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 30e3f7e9a35..86ec027c2e2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -8,7 +8,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.Configuration; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; -import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.MutableClassDescriptor; +import org.jetbrains.jet.lang.descriptors.NamedFunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.NamespaceLike; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetObjectDeclaration; @@ -66,8 +72,8 @@ public class TopDownAnalyzer { new TypeHierarchyResolver(context).process(outerScope, owner, declarations); new DeclarationResolver(context).process(); new DelegationResolver(context).process(); - lockScopes(context); new OverrideResolver(context).process(); + lockScopes(context); new OverloadResolver(context).process(); if (!context.analyzingBootstrapLibrary()) { new BodyResolver(context).resolveBehaviorDeclarationBodies(); @@ -79,6 +85,7 @@ public class TopDownAnalyzer { context.printDebugOutput(System.out); } + private static void lockScopes(TopDownAnalysisContext context) { for (MutableClassDescriptor mutableClassDescriptor : context.getClasses().values()) { mutableClassDescriptor.lockScopes(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index d28a08311ad..da0d17519cc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -57,9 +57,6 @@ public class TypeHierarchyResolver { checkSupertypesForConsistency(); // computeSuperclasses(); - // Add supertypes to resolution scopes of classes - addSupertypesToScopes(); - checkTypesInClassHeaders(); // Check bounds in the types used in generic bounds and supertype lists } @@ -440,15 +437,6 @@ public class TypeHierarchyResolver { public abstract boolean removeNeeded(JetType subject, JetType other); } - private void addSupertypesToScopes() { - for (MutableClassDescriptor mutableClassDescriptor : context.getClasses().values()) { - mutableClassDescriptor.addSupertypesToScopeForMemberLookup(); - } - for (MutableClassDescriptor mutableClassDescriptor : context.getObjects().values()) { - mutableClassDescriptor.addSupertypesToScopeForMemberLookup(); - } - } - private void checkTypesInClassHeaders() { for (Map.Entry entry : context.getClasses().entrySet()) { JetClass jetClass = entry.getKey(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ExpressionAsFunctionDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ExpressionAsFunctionDescriptor.java index c9fb9a3062d..9099a7983dd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ExpressionAsFunctionDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ExpressionAsFunctionDescriptor.java @@ -1,32 +1,27 @@ package org.jetbrains.jet.lang.resolve.calls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; -import org.jetbrains.jet.lang.types.JetStandardClasses; -import org.jetbrains.jet.lang.types.JetType; import java.util.Collections; -import java.util.List; /** * @author alex.tkachman */ public class ExpressionAsFunctionDescriptor extends FunctionDescriptorImpl { public ExpressionAsFunctionDescriptor(DeclarationDescriptor containingDeclaration, String name) { - super(containingDeclaration, Collections.emptyList(), name); + super(containingDeclaration, Collections.emptyList(), name, Kind.DECLARATION); } @Override - protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal) { + protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal, Kind kind) { throw new IllegalStateException(); } @NotNull @Override - public FunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) { + public FunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract, Kind kind, boolean copyOverrides) { throw new IllegalStateException(); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCall.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCall.java index f5545f22ddb..cb1b2dfd7fa 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCall.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCall.java @@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; +import java.util.List; import java.util.Map; /** @@ -33,6 +34,10 @@ public interface ResolvedCall { @NotNull Map getValueArguments(); + /** Values (arguments) for value parameters indexed by parameter index */ + @NotNull + List getValueArgumentsByIndex(); + /** What's substituted for type parameters */ @NotNull Map getTypeArguments(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java index 01813c4d3bd..6eec7902983 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCallImpl.java @@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -143,6 +144,29 @@ public class ResolvedCallImpl implements ResolvedC return valueArguments; } + @NotNull + @Override + public List getValueArgumentsByIndex() { + List arguments = new ArrayList(candidateDescriptor.getValueParameters().size()); + for (int i = 0; i < candidateDescriptor.getValueParameters().size(); ++i) { + arguments.add(null); + } + + for (Map.Entry entry : valueArguments.entrySet()) { + if (arguments.set(entry.getKey().getIndex(), entry.getValue()) != null) { + throw new IllegalStateException(); + } + } + + for (Object o : arguments) { + if (o == null) { + throw new IllegalStateException(); + } + } + + return arguments; + } + public void argumentHasNoType() { this.someArgumentHasNoType = true; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java index b3b722941fc..5460660dead 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ValueArgumentsToParametersMapper.java @@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -31,7 +32,10 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; Set usedParameters = Sets.newHashSet(); D candidate = candidateCall.getCandidateDescriptor(); - List valueParameters = candidate.getValueParameters(); + + D base = getDescriptorForValueArgumentsResolving(candidate); + + List valueParameters = base.getValueParameters(); Map parameterByName = Maps.newHashMap(); for (ValueParameterDescriptor valueParameter : valueParameters) { @@ -187,4 +191,30 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; candidateCall.recordValueArgument(valueParameterDescriptor, argument); } } + + /** + * Descriptor used to resolve parameter names and default parameter values. + */ + @NotNull + private static D getDescriptorForValueArgumentsResolving(D descriptor) { + Set allBases = new HashSet(); + getAllDescriptorsForValueArgumentsResolving(descriptor, allBases); + + if (allBases.size() == 1) { + return allBases.iterator().next(); + } else { + // TODO remove parameter names and parameter default values + return descriptor; + } + } + + private static void getAllDescriptorsForValueArgumentsResolving(D descriptor, Set dest) { + if (descriptor.getOverriddenDescriptors().isEmpty()) { + dest.add(descriptor); + } else { + for (CallableDescriptor overriden : descriptor.getOverriddenDescriptors()) { + getAllDescriptorsForValueArgumentsResolving((D) overriden, dest); + } + } + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScope.java index 53e1c23176b..a3287f56f72 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScope.java @@ -79,4 +79,4 @@ public interface JetScope { * @param result */ void getImplicitReceiversHierarchy(@NotNull List result); -} \ No newline at end of file +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java index 213bed1238e..f9b7894b1b2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -142,7 +142,8 @@ public class ErrorUtils { null, ReceiverDescriptor.NO_RECEIVER, "", - ERROR_PROPERTY_TYPE); + ERROR_PROPERTY_TYPE, + CallableMemberDescriptor.Kind.DECLARATION); private static final Set ERROR_PROPERTY_GROUP = Collections.singleton(ERROR_PROPERTY); private static NamedFunctionDescriptor createErrorFunction(ErrorScope ownerScope) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardClasses.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardClasses.java index 14d537fcd7f..31a3645e9b6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardClasses.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardClasses.java @@ -120,9 +120,9 @@ public class JetStandardClasses { Collections.emptyList(), true, Variance.OUT_VARIANCE, "T" + (j + 1), j); parameters.add(typeParameterDescriptor); - PropertyDescriptor propertyDescriptor = new PropertyDescriptor(classDescriptor, Collections.emptyList(), Modality.FINAL, Visibility.PUBLIC, false, false, "_" + (j + 1)); + PropertyDescriptor propertyDescriptor = new PropertyDescriptor(classDescriptor, Collections.emptyList(), Modality.FINAL, Visibility.PUBLIC, false, false, "_" + (j + 1), CallableMemberDescriptor.Kind.DECLARATION); propertyDescriptor.setType(typeParameterDescriptor.getDefaultType(), Collections.emptyList(), classDescriptor.getImplicitReceiver(), ReceiverDescriptor.NO_RECEIVER); - PropertyGetterDescriptor getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.FINAL, Visibility.PUBLIC, false, true); + PropertyGetterDescriptor getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.FINAL, Visibility.PUBLIC, false, true, CallableMemberDescriptor.Kind.DECLARATION); getterDescriptor.initialize(typeParameterDescriptor.getDefaultType()); propertyDescriptor.initialize(getterDescriptor, null); writableScope.addPropertyDescriptor(propertyDescriptor); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/error/NamedFunctionDescriptorErrorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/error/NamedFunctionDescriptorErrorImpl.java index a831b6cf766..df3aabde834 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/error/NamedFunctionDescriptorErrorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/error/NamedFunctionDescriptorErrorImpl.java @@ -9,7 +9,6 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.types.ErrorUtils; import java.util.Collections; -import java.util.List; /** * @author Stepan Koltsov @@ -20,18 +19,18 @@ public class NamedFunctionDescriptorErrorImpl extends NamedFunctionDescriptorImp private final ErrorUtils.ErrorScope ownerScope; public NamedFunctionDescriptorErrorImpl(ErrorUtils.ErrorScope ownerScope) { - super(ErrorUtils.getErrorClass(), Collections.emptyList(), ""); + super(ErrorUtils.getErrorClass(), Collections.emptyList(), "", Kind.DECLARATION); this.ownerScope = ownerScope; } @Override - protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal) { + protected FunctionDescriptorImpl createSubstitutedCopy(DeclarationDescriptor newOwner, boolean preserveOriginal, Kind kind) { return this; } @NotNull @Override - public NamedFunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) { + public NamedFunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract, Kind kind, boolean copyOverrides) { return this; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java index 0df6d9c4af1..a61a63f4423 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java @@ -112,7 +112,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); JetTypeReference receiverTypeRef = functionLiteral.getReceiverTypeRef(); NamedFunctionDescriptorImpl functionDescriptor = new NamedFunctionDescriptorImpl( - context.scope.getContainingDeclaration(), Collections.emptyList(), ""); + context.scope.getContainingDeclaration(), Collections.emptyList(), "", CallableMemberDescriptor.Kind.DECLARATION); List valueParameterDescriptors = createValueParameterDescriptors(context, functionLiteral, functionDescriptor, functionTypeExpected); diff --git a/compiler/testData/diagnostics/tests/LValueAssignment.jet b/compiler/testData/diagnostics/tests/LValueAssignment.jet index b4402994c0e..5411031f893 100644 --- a/compiler/testData/diagnostics/tests/LValueAssignment.jet +++ b/compiler/testData/diagnostics/tests/LValueAssignment.jet @@ -12,7 +12,7 @@ class C() : B() { this.b = 123 super.b = 23 this.c = 34 - super.c = 3535 //repeat for 'c' + super.c = 3535 //repeat for 'c' getInt() = 12 } @@ -140,4 +140,4 @@ fun Array.checkThis() { abstract class Ab { abstract fun getArray() : Array -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/override/ComplexValRedeclaration.jet b/compiler/testData/diagnostics/tests/override/ComplexValRedeclaration.jet new file mode 100644 index 00000000000..a84a556ba5d --- /dev/null +++ b/compiler/testData/diagnostics/tests/override/ComplexValRedeclaration.jet @@ -0,0 +1,9 @@ +package override.generics + +abstract class MyAbstractClass { + abstract val pr : T +} + +abstract class MyLegalAbstractClass2(t : T) : MyAbstractClass() { + val pr : T = t +} diff --git a/compiler/testData/diagnostics/tests/override/Generics.jet b/compiler/testData/diagnostics/tests/override/Generics.jet index 2e46a163bd0..a5faaa386de 100644 --- a/compiler/testData/diagnostics/tests/override/Generics.jet +++ b/compiler/testData/diagnostics/tests/override/Generics.jet @@ -6,7 +6,7 @@ trait MyTrait { abstract class MyAbstractClass { abstract fun bar(t: T) : T - abstract val pr : T + abstract val pr : T } trait MyProps { @@ -43,7 +43,7 @@ abstract class MyAbstractClass1 : MyTrait, MyAbstractClass() { class MyIllegalGenericClass1 : MyTrait, MyAbstractClass() {} class MyIllegalGenericClass2(r : R) : MyTrait, MyAbstractClass() { override fun foo(r: R) = r - override val pr : R = r + override val pr : R = r } class MyIllegalClass1 : MyTrait, MyAbstractClass() {} abstract class MyLegalAbstractClass1 : MyTrait, MyAbstractClass() {} @@ -51,10 +51,10 @@ abstract class MyLegalAbstractClass1 : MyTrait, MyAbstractClass() { class MyIllegalClass2(t : T) : MyTrait, MyAbstractClass() { fun foo(t: T) = t fun bar(t: T) = t - val pr : T = t + val pr : T = t } abstract class MyLegalAbstractClass2(t : T) : MyTrait, MyAbstractClass() { fun foo(t: T) = t fun bar(t: T) = t - val pr : T = t + val pr : T = t } diff --git a/compiler/testData/diagnostics/tests/override/SuspiciousCase1.jet b/compiler/testData/diagnostics/tests/override/SuspiciousCase1.jet new file mode 100644 index 00000000000..ff44b3984c3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/override/SuspiciousCase1.jet @@ -0,0 +1,12 @@ +// NamedFunctionDescriptor.substitute substitutes "overrides" +// this test checks it does it properly + +trait Foo

{ + fun quux(p: P, q: Int = 17) = 18 +} + +trait Bar : Foo + +abstract class Baz() : Bar + +fun zz(b: Baz) = b.quux("a") diff --git a/idea/testData/checker/infos/Autocasts.jet b/idea/testData/checker/infos/Autocasts.jet index cfacc4c3336..4f8ace84cbf 100644 --- a/idea/testData/checker/infos/Autocasts.jet +++ b/idea/testData/checker/infos/Autocasts.jet @@ -11,7 +11,7 @@ fun f9(a : A?) { a?.bar() if (a is B) { a.bar() - a.foo() + a.foo() } a?.foo() a?.bar() @@ -26,7 +26,7 @@ fun f9(a : A?) { return; } a.bar() - a.foo() + a.foo() } fun f10(a : A?) { @@ -77,7 +77,7 @@ fun f12(a : A?) { b?.foo() } if (a is val b is B) { - b.foo() + b.foo() a.bar() b.bar() } @@ -85,7 +85,7 @@ fun f12(a : A?) { fun f13(a : A?) { if (a is val c is B) { - c.foo() + c.foo() c.bar() } else { @@ -99,13 +99,13 @@ fun f13(a : A?) { c.bar() } else { - a.foo() + a.foo() c.bar() } a?.foo() - if (a is val c is B && a.foo() == #() && c.bar() == #()) { - c.foo() + if (a is val c is B && a.foo() == #() && c.bar() == #()) { + c.foo() c.bar() } else { @@ -250,4 +250,4 @@ fun foo(var a: Any): Int { return a } return 1 -} \ No newline at end of file +}