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 b303150e166..40c15c61e9a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.descriptors; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; @@ -11,6 +12,7 @@ import org.jetbrains.jet.lang.types.TypeSubstitutor; import org.jetbrains.jet.lang.types.Variance; import java.util.List; +import java.util.Set; /** * @author abreslav @@ -20,6 +22,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member private final Modality modality; private final boolean isVar; private final ReceiverDescriptor receiver; + private final Set overriddenProperties = Sets.newLinkedHashSet(); private final List typeParemeters = Lists.newArrayListWithCapacity(0); private final PropertyDescriptor original; private PropertyGetterDescriptor getter; @@ -145,4 +148,14 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member public PropertyDescriptor getOriginal() { return original; } + + public void addOverriddenDescriptor(PropertyDescriptor overridden) { + overriddenProperties.add(overridden); + } + + @NotNull + @Override + public Set getOverriddenDescriptors() { + return overriddenProperties; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 5b1b72809c7..b265cc1f68f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -94,7 +94,6 @@ public class BodyResolver { } private void bindOverridesInAClass(MutableClassDescriptor classDescriptor) { - for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { FunctionDescriptor overridden = findFunctionOverridableBy(declaredFunction, supertype); @@ -103,6 +102,15 @@ public class BodyResolver { } } } + + for (PropertyDescriptor propertyDescriptor : classDescriptor.getProperties()) { + for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { + PropertyDescriptor overridden = findPropertyOverridableBy(propertyDescriptor, supertype); + if (overridden != null) { + propertyDescriptor.addOverriddenDescriptor(overridden); + } + } + } } @Nullable @@ -116,6 +124,32 @@ public class BodyResolver { return null; } + @Nullable + private PropertyDescriptor findPropertyOverridableBy(@NotNull PropertyDescriptor declaredProperty, @NotNull JetType supertype) { + PropertyDescriptor property = (PropertyDescriptor) supertype.getMemberScope().getVariable(declaredProperty.getName()); + if (property == null) { + return null; + } + if (isOverridableBy(property, declaredProperty)) { + 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()); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java new file mode 100644 index 00000000000..c91031b7624 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -0,0 +1,53 @@ +package org.jetbrains.jet.lang.resolve; + +import com.google.common.collect.Sets; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.*; + +import java.util.Collection; +import java.util.Set; + +/** + * @author abreslav + */ +public class 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) { + CallableDescriptor callableDescriptor = (CallableDescriptor) descriptor; + allMembers.add(callableDescriptor); + } + } + return filterOverrides(allMembers); + } + + public static Set filterOverrides(Set candidateSet) { + Set candidates = Sets.newLinkedHashSet(candidateSet); + for (D descriptor : candidateSet) { + candidates.removeAll(descriptor.getOverriddenDescriptors()); + } + return candidates; + } + + public static boolean overrides(@NotNull Descriptor f, @NotNull Descriptor g) { + Set overriddenDescriptors = Sets.newHashSet(); + getAllOverriddenDescriptors(f.getOriginal(), overriddenDescriptors); + CallableDescriptor originalG = g.getOriginal(); + for (CallableDescriptor overriddenFunction : overriddenDescriptors) { + if (originalG.equals(overriddenFunction.getOriginal())) return true; + } + return false; + } + + private static void getAllOverriddenDescriptors(@NotNull CallableDescriptor current, @NotNull Set overriddenDescriptors) { + if (overriddenDescriptors.contains(current)) return; + for (CallableDescriptor descriptor : current.getOriginal().getOverriddenDescriptors()) { + getAllOverriddenDescriptors(descriptor, overriddenDescriptors); + overriddenDescriptors.add(descriptor); + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 3746bf6bba7..d2649b587c6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -524,7 +524,7 @@ public class CallResolver { return OverloadResolutionResult.success(maximallySpecificGenericsDiscriminated); } - Set noOverrides = filterOverrides(successfulCandidates.keySet()); + Set noOverrides = OverridingUtil.filterOverrides(successfulCandidates.keySet()); if (dirtyCandidates.isEmpty()) { // tracing.reportOverallResolutionError(trace, "Overload resolution ambiguity: " // + makeErrorMessageForMultipleDescriptors(noOverrides)); @@ -547,7 +547,7 @@ public class CallResolver { } else if (!failedCandidates.isEmpty()) { if (failedCandidates.size() != 1) { - Set noOverrides = filterOverrides(failedCandidates); + Set noOverrides = OverridingUtil.filterOverrides(failedCandidates); if (noOverrides.size() != 1) { // tracing.reportOverallResolutionError(trace, "None of the following functions can be called with the arguments supplied: " // + makeErrorMessageForMultipleDescriptors(noOverrides)); @@ -568,20 +568,6 @@ public class CallResolver { } } - private Set filterOverrides(Set candidateSet) { - Set candidates = Sets.newLinkedHashSet(); - outerLoop: - for (D me : candidateSet) { - for (D other : candidateSet) { - if (OverloadingConflictResolver.overrides(other, me)) { - continue outerLoop; - } - } - candidates.add(me); - } - return candidates; - } - private boolean checkValueArgumentTypes(JetScope scope, JetTypeInferrer.Services temporaryServices, Map argumentsToParameters, Flag dirty, Function parameterMap) { boolean result = true; for (Map.Entry entry : argumentsToParameters.entrySet()) { 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 ca78d53b398..b029df2ee3d 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 @@ -1,13 +1,13 @@ package org.jetbrains.jet.lang.resolve.calls; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.OverridingUtil; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetStandardLibrary; @@ -15,7 +15,6 @@ import org.jetbrains.jet.lang.types.JetType; import java.util.List; import java.util.Map; -import java.util.Set; /** * @author abreslav @@ -57,8 +56,8 @@ import java.util.Set; * Int < Short < Byte */ private boolean moreSpecific(Descriptor f, Descriptor g, boolean discriminateGenericDescriptors) { - if (overrides(f, g)) return true; - if (overrides(g, f)) return false; + if (OverridingUtil.overrides(f, g)) return true; + if (OverridingUtil.overrides(g, f)) return false; ReceiverDescriptor receiverOfF = f.getReceiver(); ReceiverDescriptor receiverOfG = g.getReceiver(); @@ -121,22 +120,4 @@ import java.util.Set; return false; } - public static boolean overrides(@NotNull Descriptor f, @NotNull Descriptor g) { - Set overriddenDescriptors = Sets.newHashSet(); - getAllOverriddenDescriptors(f.getOriginal(), overriddenDescriptors); - CallableDescriptor originalG = g.getOriginal(); - for (CallableDescriptor overriddenFunction : overriddenDescriptors) { - if (originalG.equals(overriddenFunction.getOriginal())) return true; - } - return false; - } - - private static void getAllOverriddenDescriptors(@NotNull CallableDescriptor current, @NotNull Set overriddenDescriptors) { - if (overriddenDescriptors.contains(current)) return; - for (CallableDescriptor descriptor : current.getOriginal().getOverriddenDescriptors()) { - getAllOverriddenDescriptors(descriptor, overriddenDescriptors); - overriddenDescriptors.add(descriptor); - } - } - }