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 e1692445134..c087c90fdd5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorImpl.java @@ -175,4 +175,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/descriptors/PropertyDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java index 50f73f05a23..d56ba48d855 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 @@ -21,6 +23,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Member private final Visibility visibility; 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; @@ -156,4 +159,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..2beff92cbe7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -68,7 +68,7 @@ public class BodyResolver { public void resolveBehaviorDeclarationBodies() { - bindOverrides(); +// bindOverrides(); resolveDelegationSpecifierLists(); resolveClassAnnotations(); @@ -81,125 +81,9 @@ public class BodyResolver { checkIfPrimaryConstructorIsNecessary(); - checkOverrides(); +// checkOverrides(); } - private void bindOverrides() { - for (Map.Entry entry : context.getClasses().entrySet()) { - bindOverridesInAClass(entry.getValue()); - } - for (Map.Entry entry : context.getObjects().entrySet()) { - bindOverridesInAClass(entry.getValue()); - } - } - - private void bindOverridesInAClass(MutableClassDescriptor classDescriptor) { - - for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { - for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { - FunctionDescriptor overridden = findFunctionOverridableBy(declaredFunction, supertype); - if (overridden != null) { - ((FunctionDescriptorImpl) declaredFunction).addOverriddenFunction(overridden); - } - } - } - } - - @Nullable - 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()) { - return functionDescriptor; - } - } - return null; - } - - private void checkOverrides() { - for (Map.Entry entry : context.getClasses().entrySet()) { - checkOverridesInAClass(entry.getValue(), entry.getKey()); - } - for (Map.Entry entry : context.getObjects().entrySet()) { - checkOverridesInAClass(entry.getValue(), entry.getKey()); - } - } - - protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) { - for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { - checkOverrideForFunction(declaredFunction); - } - if (classDescriptor.getModality() == Modality.ABSTRACT) { - return; - } - Set allOverriddenFunctions = Sets.newHashSet(); - Collection allDescriptors = classDescriptor.getDefaultType().getMemberScope().getAllDescriptors(); - for (DeclarationDescriptor descriptor : allDescriptors) { - if (descriptor instanceof FunctionDescriptor) { - FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; - if (functionDescriptor.getModality() != Modality.ABSTRACT) { - for (FunctionDescriptor overriddenDescriptor : functionDescriptor.getOverriddenDescriptors()) { - allOverriddenFunctions.add(overriddenDescriptor.getOriginal()); - } - } - } - } - boolean foundError = false; - PsiElement nameIdentifier = null; - if (klass instanceof JetClass) { - nameIdentifier = ((JetClass) klass).getNameIdentifier(); - } - else if (klass instanceof JetObjectDeclaration) { - nameIdentifier = ((JetObjectDeclaration) klass).getNameIdentifier(); - } - for (DeclarationDescriptor descriptor : allDescriptors) { - if (descriptor instanceof FunctionDescriptor) { - FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; - if (functionDescriptor.getModality() == Modality.ABSTRACT && !allOverriddenFunctions.contains(functionDescriptor.getOriginal()) && !foundError && nameIdentifier != null) { - DeclarationDescriptor declarationDescriptor = functionDescriptor.getContainingDeclaration(); - if (declarationDescriptor != classDescriptor) { -// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Class '" + klass.getName() + "' must be declared abstract or implement abstract method '" + -// functionDescriptor.getName() + "' declared in " + declarationDescriptor.getName()); - context.getTrace().report(ABSTRACT_METHOD_NOT_IMPLEMENTED.on(nameIdentifier, klass, functionDescriptor, declarationDescriptor)); - foundError = true; - } - } - } - } - } - - private void checkOverrideForFunction(FunctionDescriptor declaredFunction) { - JetFunction function = (JetFunction) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredFunction); - assert function != null; - JetModifierList modifierList = function.getModifierList(); - ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null; - boolean hasOverrideModifier = overrideNode != null; - boolean foundError = false; - - for (FunctionDescriptor overridden : declaredFunction.getOverriddenDescriptors()) { - if (overridden != null) { - if (hasOverrideModifier && !overridden.getModality().isOpen() && !foundError) { -// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and cannot be overridden"); - context.getTrace().report(OVERRIDING_FINAL_FUNCTION.on(overrideNode, overridden, overridden.getContainingDeclaration())); - foundError = true; - } - } - } - if (hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() == 0) { -// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declaredFunction.getName() + " overrides nothing"); - context.getTrace().report(NOTHING_TO_OVERRIDE.on(function, overrideNode, declaredFunction)); - } - PsiElement nameIdentifier = function.getNameIdentifier(); - if (!hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) { - FunctionDescriptor overriddenFunction = declaredFunction.getOverriddenDescriptors().iterator().next(); -// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), -// "Method '" + declaredFunction.getName() + "' overrides method '" + overriddenFunction.getName() + "' in class " + -// overriddenFunction.getContainingDeclaration().getName() + " and needs 'override' modifier"); - context.getTrace().report(VIRTUAL_METHOD_HIDDEN.on(function, nameIdentifier, declaredFunction, overriddenFunction, overriddenFunction.getContainingDeclaration())); - } - } - - private void checkIfPrimaryConstructorIsNecessary() { for (Map.Entry entry : context.getClasses().entrySet()) { MutableClassDescriptor classDescriptor = entry.getValue(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index d6e8b151adc..1a974344ae2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -191,16 +191,10 @@ public class ClassDescriptorResolver { returnType = ErrorUtils.createErrorType("No type, no body"); } } - Modality defaultModality; - if (containingDescriptor instanceof ClassDescriptor) { - boolean isDefinitelyAbstract = ((ClassDescriptor) containingDescriptor).getKind() == ClassKind.TRAIT && function.getBodyExpression() == null; - defaultModality = isDefinitelyAbstract ? Modality.ABSTRACT : Modality.FINAL; - } else { - defaultModality = Modality.FINAL; - } + boolean hasBody = function.getBodyExpression() != null; + Modality defaultModality = getDefaultModality(containingDescriptor, hasBody); Modality modality = resolveModalityFromModifiers(trace, function.getModifierList(), defaultModality); Visibility visibility = resolveVisibilityFromModifiers(trace, function.getModifierList()); - functionDescriptor.initialize( receiverType, typeParameterDescriptors, @@ -213,6 +207,20 @@ public class ClassDescriptorResolver { return functionDescriptor; } + private Modality getDefaultModality(DeclarationDescriptor containingDescriptor, boolean isBodyPresent) { + Modality defaultModality; + if (containingDescriptor instanceof ClassDescriptor) { + boolean isTrait = ((ClassDescriptor) containingDescriptor).getKind() == ClassKind.TRAIT; + boolean isDefinitelyAbstract = isTrait && !isBodyPresent; + Modality basicModality = isTrait ? Modality.OPEN : Modality.FINAL; + defaultModality = isDefinitelyAbstract ? Modality.ABSTRACT : basicModality; + } + else { + defaultModality = Modality.FINAL; + } + return defaultModality; + } + @NotNull private List resolveValueParameters(FunctionDescriptor functionDescriptor, WritableScope parameterScope, List valueParameters) { List result = new ArrayList(); @@ -451,7 +459,6 @@ public class ClassDescriptorResolver { @NotNull public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property) { - JetScope scopeWithTypeParameters; List typeParameterDescriptors; List typeParameters = property.getTypeParameters(); @@ -477,10 +484,22 @@ public class ClassDescriptorResolver { JetType type = getVariableType(scopeWithTypeParameters, property, true); + boolean hasBody = property.getInitializer() != null; + if (!hasBody) { + JetPropertyAccessor getter = property.getGetter(); + if (getter != null && getter.getBodyExpression() != null) { + hasBody = true; + } + JetPropertyAccessor setter = property.getSetter(); + if (!hasBody && setter != null && setter.getBodyExpression() != null) { + hasBody = true; + } + } + Modality defaultModality = getDefaultModality(containingDeclaration, hasBody); PropertyDescriptor propertyDescriptor = new PropertyDescriptor( containingDeclaration, annotationResolver.resolveAnnotations(scope, modifierList), - resolveModalityFromModifiers(trace, property.getModifierList()), // TODO : default modifiers differ in different contexts + resolveModalityFromModifiers(trace, property.getModifierList(), defaultModality), resolveVisibilityFromModifiers(trace, property.getModifierList()), isVar, receiverType, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java new file mode 100644 index 00000000000..d0371925643 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -0,0 +1,200 @@ +package org.jetbrains.jet.lang.resolve; + +import com.google.common.collect.Sets; +import com.intellij.lang.ASTNode; +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.*; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lexer.JetTokens; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import static org.jetbrains.jet.lang.diagnostics.Errors.*; + +/** + * @author abreslav + */ +public class OverrideResolver { + + private final TopDownAnalysisContext context; + + public OverrideResolver(@NotNull TopDownAnalysisContext context) { + this.context = context; + } + + public void process() { + bindOverrides(); + checkOverrides(); + } + + private void bindOverrides() { + for (Map.Entry entry : context.getClasses().entrySet()) { + bindOverridesInAClass(entry.getValue()); + } + for (Map.Entry entry : context.getObjects().entrySet()) { + bindOverridesInAClass(entry.getValue()); + } + } + + private void bindOverridesInAClass(MutableClassDescriptor classDescriptor) { + for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { + for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { + FunctionDescriptor overridden = findFunctionOverridableBy(declaredFunction, supertype); + if (overridden != null) { + ((FunctionDescriptorImpl) declaredFunction).addOverriddenFunction(overridden); + } + } + } + + for (PropertyDescriptor propertyDescriptor : classDescriptor.getProperties()) { + for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { + PropertyDescriptor overridden = findPropertyOverridableBy(propertyDescriptor, supertype); + if (overridden != null) { + propertyDescriptor.addOverriddenDescriptor(overridden); + } + } + } + } + + @Nullable + private FunctionDescriptor findFunctionOverridableBy(@NotNull FunctionDescriptor declaredFunction, @NotNull JetType supertype) { + FunctionGroup functionGroup = supertype.getMemberScope().getFunctionGroup(declaredFunction.getName()); + for (FunctionDescriptor functionDescriptor : functionGroup.getFunctionDescriptors()) { + if (OverridingUtil.isOverridableBy(context.getSemanticServices().getTypeChecker(), functionDescriptor, declaredFunction).isSuccess()) { + return functionDescriptor; + } + } + 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 (OverridingUtil.isOverridableBy(context.getSemanticServices().getTypeChecker(), property, declaredProperty).isSuccess()) { + return property; + } + return null; + } + + private void checkOverrides() { + for (Map.Entry entry : context.getClasses().entrySet()) { + checkOverridesInAClass(entry.getValue(), entry.getKey()); + } + for (Map.Entry entry : context.getObjects().entrySet()) { + checkOverridesInAClass(entry.getValue(), entry.getKey()); + } + } + + 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); + } + if (classDescriptor.getModality() == Modality.ABSTRACT) { + return; + } + Set allOverriddenFunctions = Sets.newHashSet(); + Collection allDescriptors = classDescriptor.getDefaultType().getMemberScope().getAllDescriptors(); + for (DeclarationDescriptor descriptor : allDescriptors) { + if (descriptor instanceof FunctionDescriptor) { + FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; + if (functionDescriptor.getModality() != Modality.ABSTRACT) { + for (FunctionDescriptor overriddenDescriptor : functionDescriptor.getOverriddenDescriptors()) { + allOverriddenFunctions.add(overriddenDescriptor.getOriginal()); + } + } + } + } + boolean foundError = false; + PsiElement nameIdentifier = null; + if (klass instanceof JetClass) { + nameIdentifier = ((JetClass) klass).getNameIdentifier(); + } + else if (klass instanceof JetObjectDeclaration) { + nameIdentifier = ((JetObjectDeclaration) klass).getNameIdentifier(); + } + for (DeclarationDescriptor descriptor : allDescriptors) { + if (descriptor instanceof FunctionDescriptor) { + FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; + if (functionDescriptor.getModality() == Modality.ABSTRACT && !allOverriddenFunctions.contains(functionDescriptor.getOriginal()) && !foundError && nameIdentifier != null) { + DeclarationDescriptor declarationDescriptor = functionDescriptor.getContainingDeclaration(); + if (declarationDescriptor != classDescriptor) { +// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Class '" + klass.getName() + "' must be declared abstract or implement abstract method '" + +// functionDescriptor.getName() + "' declared in " + declarationDescriptor.getName()); + context.getTrace().report(ABSTRACT_METHOD_NOT_IMPLEMENTED.on(nameIdentifier, klass, functionDescriptor, declarationDescriptor)); + foundError = true; + } + } + } + } + } + + 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); + assert function != null; + JetModifierList modifierList = function.getModifierList(); + ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null; + boolean hasOverrideModifier = overrideNode != null; + boolean foundError = false; + + for (FunctionDescriptor overridden : declaredFunction.getOverriddenDescriptors()) { + if (overridden != null) { + if (hasOverrideModifier && !overridden.getModality().isOpen() && !foundError) { +// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and cannot be overridden"); + context.getTrace().report(OVERRIDING_FINAL_FUNCTION.on(overrideNode, overridden, overridden.getContainingDeclaration())); + foundError = true; + } + } + } + if (hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() == 0) { +// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declaredFunction.getName() + " overrides nothing"); + context.getTrace().report(NOTHING_TO_OVERRIDE.on(function, overrideNode, declaredFunction)); + } + PsiElement nameIdentifier = function.getNameIdentifier(); + if (!hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) { + FunctionDescriptor overriddenFunction = declaredFunction.getOverriddenDescriptors().iterator().next(); +// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), +// "Method '" + declaredFunction.getName() + "' overrides method '" + overriddenFunction.getName() + "' in class " + +// overriddenFunction.getContainingDeclaration().getName() + " and needs 'override' modifier"); + context.getTrace().report(VIRTUAL_METHOD_HIDDEN.on(function, nameIdentifier, declaredFunction, overriddenFunction, overriddenFunction.getContainingDeclaration())); + } + } +} 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..2ca2700119e --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverridingUtil.java @@ -0,0 +1,208 @@ +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; + +/** + * @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 && 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) { + Set candidates = Sets.newLinkedHashSet(); + outerLoop: + for (D me : candidateSet) { + for (D other : candidateSet) { + if (me == other) continue; + if (overrides(other, me)) { + continue outerLoop; + } + } + for (D other : candidates) { + 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; + } + + 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); + } + } + + @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/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index ac6a81e01ce..457807e60f0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -65,6 +65,7 @@ public class TopDownAnalyzer { TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace); new TypeHierarchyResolver(context).process(outerScope, owner, declarations); new DeclarationResolver(context).process(); + new OverrideResolver(context).process(); new BodyResolver(context).resolveBehaviorDeclarationBodies(); } @@ -77,6 +78,12 @@ public class TopDownAnalyzer { context.getNamespaceDescriptors().put(namespace, standardLibraryNamespace); new TypeHierarchyResolver(context).process(outerScope, standardLibraryNamespace, namespace.getDeclarations()); new DeclarationResolver(context).process(); + OverrideResolver overrideResolver = new OverrideResolver(context) { + @Override + protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) { + } + }; + overrideResolver.process(); BodyResolver bodyResolver = new BodyResolver(context) { @Override protected void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor, @Nullable ClassDescriptor classDescriptor) { @@ -85,10 +92,6 @@ public class TopDownAnalyzer { @Override protected void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) { } - - @Override - protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) { - } }; bodyResolver.resolveBehaviorDeclarationBodies(); } 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..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 @@ -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,12 +15,11 @@ import org.jetbrains.jet.lang.types.JetType; import java.util.List; import java.util.Map; -import java.util.Set; /** * @author abreslav */ -/*package*/ class OverloadingConflictResolver { +public class OverloadingConflictResolver { private final JetSemanticServices semanticServices; @@ -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); - } - } - } diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 32dcfce68ab..b5abe519db1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -172,6 +172,7 @@ public class DescriptorRenderer { @Override public Void visitPropertyDescriptor(PropertyDescriptor descriptor, StringBuilder builder) { + renderModality(descriptor.getModality(), builder); String typeString = renderPropertyPrefixAndComputeTypeString( builder, descriptor.getTypeParameters(), descriptor.getReceiver(), @@ -182,8 +183,24 @@ public class DescriptorRenderer { return null; } + private void renderModality(Modality modality, StringBuilder builder) { + switch (modality) { + case FINAL: + builder.append("final"); + break; + case OPEN: + builder.append("open"); + break; + case ABSTRACT: + builder.append("abstract"); + break; + } + builder.append(" "); + } + @Override public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) { + renderModality(descriptor.getModality(), builder); builder.append(renderKeyword("fun")).append(" "); renderTypeParameters(descriptor.getTypeParameters(), builder); @@ -259,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/docs/StrangeLoop_Kotlin.key b/docs/StrangeLoop_Kotlin.key index a819dd5c097..cf94f3c845d 100644 Binary files a/docs/StrangeLoop_Kotlin.key and b/docs/StrangeLoop_Kotlin.key differ diff --git a/idea/testData/checkerWithErrorTypes/quick/regressions/kt316.jet b/idea/testData/checkerWithErrorTypes/quick/regressions/kt316.jet new file mode 100644 index 00000000000..a794d90d035 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/quick/regressions/kt316.jet @@ -0,0 +1,10 @@ +// KT-316 Members of traits must be open by default + +trait B { + fun bar() {} + fun foo() {} +} + +open class A() : B{ + override fun foo() {} +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/JetLiteFixture.java b/idea/tests/org/jetbrains/jet/JetLiteFixture.java index e0c0051493f..a2142bee57c 100644 --- a/idea/tests/org/jetbrains/jet/JetLiteFixture.java +++ b/idea/tests/org/jetbrains/jet/JetLiteFixture.java @@ -81,7 +81,7 @@ public abstract class JetLiteFixture extends PlatformLiteFixture { public void verify(PicoContainer container) throws PicoIntrospectionException { } }); - myProject = disposeOnTearDown(new MockProjectEx()); + myProject = disposeOnTearDown(new MockProjectEx(getTestRootDisposable())); myPsiManager = new MockPsiManager(myProject); myFileFactory = new PsiFileFactoryImpl(myPsiManager); final MutablePicoContainer appContainer = getApplication().getPicoContainer(); 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()); }