KT-3159 Disallow overriding var with different type #KT-3159 fixed
This commit is contained in:
committed by
Andrey Breslav
parent
e9613b95ac
commit
e89a8c684f
@@ -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);
|
||||
|
||||
+3
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
trait Super {
|
||||
var v: CharSequence
|
||||
val v2: CharSequence
|
||||
}
|
||||
|
||||
class Sub: Super {
|
||||
override var v: <!PROPERTY_TYPE_MISMATCH_ON_OVERRIDE!>String<!> = "fail"
|
||||
override val v2: String = "ok"
|
||||
}
|
||||
@@ -4105,6 +4105,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
public void testKt2744() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/subtyping/kt2744.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt3159.kt")
|
||||
public void testKt3159() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/subtyping/kt3159.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kt304.kt")
|
||||
public void testKt304() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user