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;
}
@@ -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 {
@@ -79,16 +79,10 @@ public class IdeErrorMessages {
"<tr><td>Parameter:</td><td>{1}</td></tr></table></html>", HTML_RENDER_TYPE, HTML_RENDER_TYPE);
MAP.put(RETURN_TYPE_MISMATCH_ON_OVERRIDE, "<html>Return type is ''{0}'', which is not a subtype of overridden<br/>" +
"{1}</html>",
new Renderer<CallableMemberDescriptor>() {
@NotNull
@Override
public String render(@NotNull CallableMemberDescriptor object) {
JetType returnType = object.getReturnType();
assert returnType != null;
return DescriptorRenderer.HTML.renderType(returnType);
}
}, DescriptorRenderer.HTML);
"{1}</html>", HTML_RENDER_RETURN_TYPE, DescriptorRenderer.HTML);
MAP.put(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE, "<html>Var-property type is ''{0}'', which is not a type of overridden<br/>" +
"{1}</html>", HTML_RENDER_RETURN_TYPE, DescriptorRenderer.HTML);
MAP.put(VAR_OVERRIDDEN_BY_VAL, "<html>Val-property cannot override var-property<br />" +
"{1}</html>", DescriptorRenderer.HTML, DescriptorRenderer.HTML);
@@ -20,10 +20,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1;
import org.jetbrains.jet.lang.diagnostics.Errors;
@@ -213,4 +210,13 @@ public class IdeRenderers {
}
};
public static final Renderer<CallableMemberDescriptor> HTML_RENDER_RETURN_TYPE = new Renderer<CallableMemberDescriptor>() {
@NotNull
@Override
public String render(@NotNull CallableMemberDescriptor object) {
JetType returnType = object.getReturnType();
assert returnType != null;
return DescriptorRenderer.HTML.renderType(returnType);
}
};
}