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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user