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 ff2fc69b585..74fa8b21abe 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java @@ -165,4 +165,24 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements return visitor.visitFunctionDescriptor(this, data); } +// @Override +// public boolean equals(Object obj) { +// if (obj == null) return false; +// if (obj.getClass() != FunctionDescriptorImpl.class) return false; +// FunctionDescriptorImpl other = (FunctionDescriptorImpl) obj; +// if (!eq(this.getName(), other.getName())) return false; +// if (!eq(this.getContainingDeclaration(), other.getContainingDeclaration())) return false; +// +// } +// +// private static boolean eq(Object a, Object b) { +// if (a == null) return b == null; +// if (b == null) return false; +// return a.equals(b); +// } +// +// @Override +// public int hashCode() { +// return super.hashCode(); // TODO +// } } 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 04bd0dcd6ca..07a14eece99 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java @@ -1,8 +1,5 @@ package org.jetbrains.jet.lang.descriptors; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.google.common.collect.Maps; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.BindingTrace; @@ -112,125 +109,4 @@ public class FunctionDescriptorUtil { return parameterScope; } - public static class OverrideCompatibilityInfo { - - private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(false, "SUCCESS"); - - @NotNull - public static OverrideCompatibilityInfo nameMismatch() { - return new OverrideCompatibilityInfo(true, "nameMismatch"); // TODO - } - - @NotNull - public static OverrideCompatibilityInfo typeParameterNumberMismatch() { - return new OverrideCompatibilityInfo(true, "typeParameterNumberMismatch"); // TODO - } - - @NotNull - public static OverrideCompatibilityInfo valueParameterNumberMismatch() { - return new OverrideCompatibilityInfo(true, "valueParameterNumberMismatch"); // TODO - } - - @NotNull - public static OverrideCompatibilityInfo boundsMismatch(TypeParameterDescriptor superTypeParameter, TypeParameterDescriptor subTypeParameter) { - return new OverrideCompatibilityInfo(true, "boundsMismatch"); // TODO - } - - @NotNull - public static OverrideCompatibilityInfo valueParameterTypeMismatch(ValueParameterDescriptor superValueParameter, ValueParameterDescriptor subValueParameter) { - return new OverrideCompatibilityInfo(true, "valueParameterTypeMismatch"); // TODO - } - - @NotNull - public static OverrideCompatibilityInfo returnTypeMismatch(JetType substitutedSuperReturnType, JetType unsubstitutedSubReturnType) { - return new OverrideCompatibilityInfo(true, "returnTypeMismatch: " + unsubstitutedSubReturnType + " >< " + substitutedSuperReturnType); // TODO - } - - @NotNull - public static OverrideCompatibilityInfo success() { - return SUCCESS; - } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - private final boolean isError; - private final String message; - - public OverrideCompatibilityInfo(boolean error, String message) { - isError = error; - this.message = message; - } - - public boolean isSuccess() { - return !isError; - } - - public String getMessage() { - return message; - } - } - - @NotNull - public static OverrideCompatibilityInfo isOverridableBy(@NotNull JetTypeChecker typeChecker, @NotNull FunctionDescriptor superFunction, @NotNull FunctionDescriptor subFunction) { - if (!superFunction.getName().equals(subFunction.getName())) { - return OverrideCompatibilityInfo.nameMismatch(); - } - - // TODO : Visibility - - if (superFunction.getTypeParameters().size() != subFunction.getTypeParameters().size()) { - return OverrideCompatibilityInfo.typeParameterNumberMismatch(); - } - - if (superFunction.getValueParameters().size() != subFunction.getValueParameters().size()) { - return OverrideCompatibilityInfo.valueParameterNumberMismatch(); - } - - List superTypeParameters = superFunction.getTypeParameters(); - List subTypeParameters = subFunction.getTypeParameters(); - - Map substitutionContext = Maps.newHashMap(); - BiMap axioms = HashBiMap.create(); - for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) { - TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i); - TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i); - substitutionContext.put( - superTypeParameter.getTypeConstructor(), - new TypeProjection(subTypeParameter.getDefaultType())); - axioms.put(superTypeParameter.getTypeConstructor(), subTypeParameter.getTypeConstructor()); - } - - for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) { - TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i); - TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i); - - - if (!JetTypeImpl.equalTypes(superTypeParameter.getBoundsAsType(), subTypeParameter.getBoundsAsType(), axioms)) { - return OverrideCompatibilityInfo.boundsMismatch(superTypeParameter, subTypeParameter); - } - } - - List superValueParameters = superFunction.getValueParameters(); - List subValueParameters = subFunction.getValueParameters(); - for (int i = 0, unsubstitutedValueParametersSize = superValueParameters.size(); i < unsubstitutedValueParametersSize; i++) { - ValueParameterDescriptor superValueParameter = superValueParameters.get(i); - ValueParameterDescriptor subValueParameter = subValueParameters.get(i); - - if (!JetTypeImpl.equalTypes(superValueParameter.getOutType(), subValueParameter.getOutType(), axioms)) { - return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameter, subValueParameter); - } - } - - // TODO : Default values, varargs etc - - TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitutionContext); - JetType substitutedSuperReturnType = typeSubstitutor.substitute(superFunction.getReturnType(), Variance.OUT_VARIANCE); - assert substitutedSuperReturnType != null; - if (!typeChecker.isSubtypeOf(subFunction.getReturnType(), substitutedSuperReturnType)) { - return OverrideCompatibilityInfo.returnTypeMismatch(substitutedSuperReturnType, subFunction.getReturnType()); - } - - return OverrideCompatibilityInfo.success(); - } - } 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 03639f1f1a3..d0371925643 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -8,7 +8,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.JetTypeChecker; import org.jetbrains.jet.lexer.JetTokens; import java.util.Collection; @@ -66,7 +65,7 @@ public class OverrideResolver { private FunctionDescriptor findFunctionOverridableBy(@NotNull FunctionDescriptor declaredFunction, @NotNull JetType supertype) { FunctionGroup functionGroup = supertype.getMemberScope().getFunctionGroup(declaredFunction.getName()); for (FunctionDescriptor functionDescriptor : functionGroup.getFunctionDescriptors()) { - if (FunctionDescriptorUtil.isOverridableBy(context.getSemanticServices().getTypeChecker(), functionDescriptor, declaredFunction).isSuccess()) { + if (OverridingUtil.isOverridableBy(context.getSemanticServices().getTypeChecker(), functionDescriptor, declaredFunction).isSuccess()) { return functionDescriptor; } } @@ -79,26 +78,12 @@ public class OverrideResolver { if (property == null) { return null; } - if (isOverridableBy(property, declaredProperty)) { + if (OverridingUtil.isOverridableBy(context.getSemanticServices().getTypeChecker(), property, declaredProperty).isSuccess()) { return property; } return null; } - private boolean isOverridableBy(@NotNull PropertyDescriptor property, @NotNull PropertyDescriptor overrideCandidate) { - boolean var = property.isVar(); - if (var && !overrideCandidate.isVar()) return false; - JetType propertyType = property.getReturnType(); - JetType overrideType = overrideCandidate.getReturnType(); - JetTypeChecker typeChecker = context.getSemanticServices().getTypeChecker(); - if (var) { - return typeChecker.equalTypes(propertyType, overrideType); - } - else { - return typeChecker.isSubtypeOf(overrideType, propertyType); - } - } - private void checkOverrides() { for (Map.Entry entry : context.getClasses().entrySet()) { checkOverridesInAClass(entry.getValue(), entry.getKey()); @@ -109,6 +94,30 @@ public class OverrideResolver { } protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) { + + Set inheritedFunctions = Sets.newLinkedHashSet(); + Set inheritedProperties = Sets.newLinkedHashSet(); + for (JetType supertype : classDescriptor.getSupertypes()) { + for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) { + if (descriptor instanceof FunctionDescriptor) { + FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; + inheritedFunctions.add(functionDescriptor); + } + else if (descriptor instanceof PropertyDescriptor) { + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; + inheritedProperties.add(propertyDescriptor); + } + } + } + + OverridingUtil.filterOverrides(inheritedFunctions); + OverridingUtil.filterOverrides(inheritedProperties); + +// System.out.println(classDescriptor); +// println(inheritedFunctions); +// println(inheritedProperties); + + for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { checkOverrideForFunction(declaredFunction); } @@ -151,6 +160,12 @@ public class OverrideResolver { } } + private void println(Set inheritedProperties) { + for (CallableDescriptor inheritedProperty : inheritedProperties) { + System.out.println(" " + inheritedProperty); + } + } + private void checkOverrideForFunction(FunctionDescriptor declaredFunction) { JetFunction function = (JetFunction) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredFunction); 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 5aea65d7aad..8e402bf1c52 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -1,10 +1,16 @@ package org.jetbrains.jet.lang.resolve; +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 org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.types.*; import java.util.Collection; +import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -17,21 +23,40 @@ public class OverridingUtil { Set allMembers = Sets.newLinkedHashSet(); for (DeclarationDescriptor descriptor : allDescriptors) { assert !(descriptor instanceof ConstructorDescriptor); - if (descriptor instanceof CallableDescriptor) { + if (descriptor instanceof CallableDescriptor && descriptor instanceof MemberDescriptor) { CallableDescriptor callableDescriptor = (CallableDescriptor) descriptor; - allMembers.add(callableDescriptor); + if (((MemberDescriptor) descriptor).getModality() != Modality.ABSTRACT) { + allMembers.add(callableDescriptor); + } } } return filterOverrides(allMembers); } public static Set filterOverrides(Set candidateSet) { - Set candidates = Sets.newLinkedHashSet(candidateSet); - for (D descriptor : candidateSet) { - Set overriddenDescriptors = Sets.newHashSet(); - getAllOverriddenDescriptors(descriptor.getOriginal(), overriddenDescriptors); - candidates.removeAll(overriddenDescriptors); + Set candidates = Sets.newLinkedHashSet(); + outerLoop: + for (D me : candidateSet) { + for (D other : candidateSet) { + if (me == other) continue; + if (overrides(other, me)) { + continue outerLoop; + } + if (me.getOriginal() == other.getOriginal() + && isOverridableBy(JetTypeChecker.INSTANCE, other, me).isSuccess() + && isOverridableBy(JetTypeChecker.INSTANCE, me, other).isSuccess()) { + continue outerLoop; + } + } +// System.out.println(me); + candidates.add(me); } +// Set candidates = Sets.newLinkedHashSet(candidateSet); +// for (D descriptor : candidateSet) { +// Set overriddenDescriptors = Sets.newHashSet(); +// getAllOverriddenDescriptors(descriptor.getOriginal(), overriddenDescriptors); +// candidates.removeAll(overriddenDescriptors); +// } return candidates; } @@ -52,4 +77,130 @@ public class OverridingUtil { overriddenDescriptors.add(descriptor); } } + + @NotNull + public static OverrideCompatibilityInfo isOverridableBy(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) { + if (!superDescriptor.getName().equals(subDescriptor.getName())) { + return OverrideCompatibilityInfo.nameMismatch(); + } + + // TODO : Visibility + + if (superDescriptor.getTypeParameters().size() != subDescriptor.getTypeParameters().size()) { + return OverrideCompatibilityInfo.typeParameterNumberMismatch(); + } + + if (superDescriptor.getValueParameters().size() != subDescriptor.getValueParameters().size()) { + return OverrideCompatibilityInfo.valueParameterNumberMismatch(); + } + + List superTypeParameters = superDescriptor.getTypeParameters(); + List subTypeParameters = subDescriptor.getTypeParameters(); + + Map substitutionContext = Maps.newHashMap(); + BiMap axioms = HashBiMap.create(); + for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) { + TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i); + TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i); + substitutionContext.put( + superTypeParameter.getTypeConstructor(), + new TypeProjection(subTypeParameter.getDefaultType())); + axioms.put(superTypeParameter.getTypeConstructor(), subTypeParameter.getTypeConstructor()); + } + + for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) { + TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i); + TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i); + + + if (!JetTypeImpl.equalTypes(superTypeParameter.getBoundsAsType(), subTypeParameter.getBoundsAsType(), axioms)) { + return OverrideCompatibilityInfo.boundsMismatch(superTypeParameter, subTypeParameter); + } + } + + List superValueParameters = superDescriptor.getValueParameters(); + List subValueParameters = subDescriptor.getValueParameters(); + for (int i = 0, unsubstitutedValueParametersSize = superValueParameters.size(); i < unsubstitutedValueParametersSize; i++) { + ValueParameterDescriptor superValueParameter = superValueParameters.get(i); + ValueParameterDescriptor subValueParameter = subValueParameters.get(i); + + if (!JetTypeImpl.equalTypes(superValueParameter.getOutType(), subValueParameter.getOutType(), axioms)) { + return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameter, subValueParameter); + } + } + + // TODO : Default values, varargs etc + + TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitutionContext); + JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getReturnType(), Variance.OUT_VARIANCE); + assert substitutedSuperReturnType != null; + if (!typeChecker.isSubtypeOf(subDescriptor.getReturnType(), substitutedSuperReturnType)) { + return OverrideCompatibilityInfo.returnTypeMismatch(substitutedSuperReturnType, subDescriptor.getReturnType()); + } + + return OverrideCompatibilityInfo.success(); + } + + public static class OverrideCompatibilityInfo { + + private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(true, "SUCCESS"); + + @NotNull + public static OverrideCompatibilityInfo success() { + return SUCCESS; + } + + @NotNull + public static OverrideCompatibilityInfo nameMismatch() { + return new OverrideCompatibilityInfo(false, "nameMismatch"); // TODO + } + + @NotNull + public static OverrideCompatibilityInfo typeParameterNumberMismatch() { + return new OverrideCompatibilityInfo(false, "typeParameterNumberMismatch"); // TODO + } + + @NotNull + public static OverrideCompatibilityInfo valueParameterNumberMismatch() { + return new OverrideCompatibilityInfo(false, "valueParameterNumberMismatch"); // TODO + } + + @NotNull + public static OverrideCompatibilityInfo boundsMismatch(TypeParameterDescriptor superTypeParameter, TypeParameterDescriptor subTypeParameter) { + return new OverrideCompatibilityInfo(false, "boundsMismatch"); // TODO + } + + @NotNull + public static OverrideCompatibilityInfo valueParameterTypeMismatch(ValueParameterDescriptor superValueParameter, ValueParameterDescriptor subValueParameter) { + return new OverrideCompatibilityInfo(false, "valueParameterTypeMismatch"); // TODO + } + + @NotNull + public static OverrideCompatibilityInfo returnTypeMismatch(JetType substitutedSuperReturnType, JetType unsubstitutedSubReturnType) { + return new OverrideCompatibilityInfo(false, "returnTypeMismatch: " + unsubstitutedSubReturnType + " >< " + substitutedSuperReturnType); // TODO + } + + @NotNull + public static OverrideCompatibilityInfo varOverriddenByVal() { + return new OverrideCompatibilityInfo(false, "varOverriddenByVal"); // TODO + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + private final boolean isSuccess; + private final String message; + + public OverrideCompatibilityInfo(boolean success, String message) { + isSuccess = success; + this.message = message; + } + + public boolean isSuccess() { + return isSuccess; + } + + public String getMessage() { + return message; + } + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java index b029df2ee3d..127cf37efec 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/OverloadingConflictResolver.java @@ -19,7 +19,7 @@ import java.util.Map; /** * @author abreslav */ -/*package*/ class OverloadingConflictResolver { +public class OverloadingConflictResolver { private final JetSemanticServices semanticServices; diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 847ba7b715e..b5abe519db1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -200,6 +200,7 @@ public class DescriptorRenderer { @Override public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) { + renderModality(descriptor.getModality(), builder); builder.append(renderKeyword("fun")).append(" "); renderTypeParameters(descriptor.getTypeParameters(), builder); @@ -275,6 +276,7 @@ public class DescriptorRenderer { } public void renderClassDescriptor(ClassDescriptor descriptor, StringBuilder builder, String keyword) { + renderModality(descriptor.getModality(), builder); builder.append(renderKeyword(keyword)).append(" "); renderName(descriptor, builder); renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder); diff --git a/idea/tests/org/jetbrains/jet/types/JetOverridingTest.java b/idea/tests/org/jetbrains/jet/types/JetOverridingTest.java index 13d0c1a8827..d34a474936a 100644 --- a/idea/tests/org/jetbrains/jet/types/JetOverridingTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetOverridingTest.java @@ -5,11 +5,11 @@ import com.intellij.openapi.application.PathManager; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptorUtil; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver; +import org.jetbrains.jet.lang.resolve.OverridingUtil; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.parsing.JetParsingTest; @@ -139,7 +139,7 @@ public class JetOverridingTest extends LightDaemonAnalyzerTestCase { private void assertOverridabilityRelation(String superFun, String subFun, boolean expectedIsError) { FunctionDescriptor a = makeFunction(superFun); FunctionDescriptor b = makeFunction(subFun); - FunctionDescriptorUtil.OverrideCompatibilityInfo overridableWith = FunctionDescriptorUtil.isOverridableBy(semanticServices.getTypeChecker(), a, b); + OverridingUtil.OverrideCompatibilityInfo overridableWith = OverridingUtil.isOverridableBy(semanticServices.getTypeChecker(), a, b); assertEquals(overridableWith.getMessage(), expectedIsError, !overridableWith.isSuccess()); }