KT-3159 Disallow overriding var with different type #KT-3159 fixed

This commit is contained in:
Kirill Berezin
2012-12-19 23:44:22 +04:00
committed by Andrey Breslav
parent e9613b95ac
commit e89a8c684f
8 changed files with 73 additions and 18 deletions
@@ -221,6 +221,8 @@ public interface Errors {
DiagnosticFactory3.create(ERROR, VISIBILITY_MODIFIER);
DiagnosticFactory2<JetNamedDeclaration, CallableMemberDescriptor, CallableMemberDescriptor> RETURN_TYPE_MISMATCH_ON_OVERRIDE =
DiagnosticFactory2.create(ERROR, DECLARATION_RETURN_TYPE);
DiagnosticFactory2<JetNamedDeclaration, CallableMemberDescriptor, CallableMemberDescriptor> PROPERTY_TYPE_MISMATCH_ON_OVERRIDE =
DiagnosticFactory2.create(ERROR, DECLARATION_RETURN_TYPE);
DiagnosticFactory2<PsiElement, JetClassOrObject, CallableMemberDescriptor> ABSTRACT_MEMBER_NOT_IMPLEMENTED =
DiagnosticFactory2.create(ERROR);
@@ -358,6 +358,9 @@ public class DefaultErrorMessages {
MAP.put(RETURN_TYPE_MISMATCH_ON_OVERRIDE, "Return type of ''{0}'' is not a subtype of the return type of overridden member {1}",
NAME, DescriptorRenderer.TEXT);
MAP.put(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE, "Type of ''{0}'' doesn't match to the type of overridden var-property {1}",
NAME, DescriptorRenderer.TEXT);
MAP.put(VAR_OVERRIDDEN_BY_VAL, "Var-property {0} cannot be overridden by val-property {1}", DescriptorRenderer.TEXT,
DescriptorRenderer.TEXT);
@@ -585,6 +585,8 @@ public class OverrideResolver {
void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden);
void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden);
void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden);
void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden);
@@ -636,6 +638,14 @@ public class OverrideResolver {
}
}
@Override
public void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
if (!typeMismatchError) {
typeMismatchError = true;
trace.report(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
}
}
@Override
public void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden) {
if (!kindMismatchError) {
@@ -674,7 +684,11 @@ public class OverrideResolver {
reportError.overridingFinalMember(overridden);
}
if (!OverridingUtil.isReturnTypeOkForOverride(JetTypeChecker.INSTANCE, overridden, declared)) {
if (declared instanceof PropertyDescriptor && !OverridingUtil.isPropertyTypeOkForOverride(
JetTypeChecker.INSTANCE, (PropertyDescriptor) overridden, (PropertyDescriptor) declared)) {
reportError.propertyTypeMismatchOnOverride(overridden);
}
else if (!OverridingUtil.isReturnTypeOkForOverride(JetTypeChecker.INSTANCE, overridden, declared)) {
reportError.returnTypeMismatchOnOverride(overridden);
}
@@ -721,6 +735,11 @@ public class OverrideResolver {
}
}
@Override
public void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
throw new IllegalStateException("Component functions are not properties");
}
@Override
public void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden) {
throw new IllegalStateException("Component functions are not properties");
@@ -221,6 +221,21 @@ public class OverridingUtil {
}
public static boolean isReturnTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
JetType superReturnType = superDescriptor.getReturnType();
assert superReturnType != null;
JetType subReturnType = subDescriptor.getReturnType();
assert subReturnType != null;
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE);
assert substitutedSuperReturnType != null;
return typeChecker.isSubtypeOf(subReturnType, substitutedSuperReturnType);
}
private static TypeSubstitutor prepareTypeSubstitutor(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
@@ -231,12 +246,14 @@ public class OverridingUtil {
superTypeParameter.getTypeConstructor(),
new TypeProjection(subTypeParameter.getDefaultType()));
}
return TypeSubstitutor.create(substitutionContext);
}
// This code compares return types, but they are not a part of the signature, so this code does not belong here
TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitutionContext);
public static boolean isPropertyTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull PropertyDescriptor superDescriptor, @NotNull PropertyDescriptor subDescriptor) {
TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getReturnType(), Variance.OUT_VARIANCE);
assert substitutedSuperReturnType != null;
if (!typeChecker.isSubtypeOf(subDescriptor.getReturnType(), substitutedSuperReturnType)) {
if (superDescriptor.isVar() && !typeChecker.equalTypes(subDescriptor.getReturnType(), substitutedSuperReturnType)) {
return false;
}