From cd06bdedfe73002feb6cdd7244ed4b929df77c83 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Fri, 15 Feb 2013 19:14:19 +0400 Subject: [PATCH] Added propagation error message when array of subtype is used in return type of sub method. EA-43482 - ISE: JavaFunctionResolver.checkFunctionsOverrideCorrectly --- .../SignaturesPropagationData.java | 53 +++++++++++++++++-- .../arraysInSubtypes/ArraysInSubtypes.java | 19 +++++++ .../arraysInSubtypes/ArraysInSubtypes.txt | 14 +++++ .../jet/jvm/compiler/LoadJavaCustomTest.java | 6 +++ 4 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/loadJavaCustom/arraysInSubtypes/ArraysInSubtypes.java create mode 100644 compiler/testData/loadJavaCustom/arraysInSubtypes/ArraysInSubtypes.txt diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java index c7c52199afe..a2dc168a1e1 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagationData.java @@ -22,6 +22,7 @@ import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.SystemInfo; import com.intellij.psi.HierarchicalMethodSignature; import com.intellij.psi.PsiClass; @@ -41,7 +42,9 @@ import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.renderer.DescriptorRenderer; import java.util.*; @@ -329,11 +332,51 @@ public class SignaturesPropagationData { resultScope = autoType.getMemberScope(); } - return new JetTypeImpl(autoType.getAnnotations(), - resultClassifier.getTypeConstructor(), - resultNullable, - resultArguments, - resultScope); + JetTypeImpl type = new JetTypeImpl(autoType.getAnnotations(), + resultClassifier.getTypeConstructor(), + resultNullable, + resultArguments, + resultScope); + + checkArrayInReturnTypeType(type, typesFromSuper); + + return type; + } + + // Checks for case when method returning Super[] is overridden with method returning Sub[] + private void checkArrayInReturnTypeType(JetType type, List typesFromSuper) { + List arrayTypesFromSuper = ContainerUtil.filter(typesFromSuper, new Condition() { + @Override + public boolean value(TypeAndVariance typeAndVariance) { + return typeAndVariance.type.getConstructor().getDeclarationDescriptor() == KotlinBuiltIns.getInstance().getArray(); + } + }); + if (KotlinBuiltIns.getInstance().getArray() == type.getConstructor().getDeclarationDescriptor() && !arrayTypesFromSuper.isEmpty()) { + assert type.getArguments().size() == 1; + if (type.getArguments().get(0).getProjectionKind() == Variance.INVARIANT) { + for (TypeAndVariance typeAndVariance : arrayTypesFromSuper) { + JetType arrayTypeFromSuper = typeAndVariance.type; + assert arrayTypeFromSuper.getArguments().size() == 1; + JetType elementTypeInSuper = arrayTypeFromSuper.getArguments().get(0).getType(); + JetType elementType = type.getArguments().get(0).getType(); + + if (JetTypeChecker.INSTANCE.isSubtypeOf(elementType, elementTypeInSuper) + && !JetTypeChecker.INSTANCE.equalTypes(elementType, elementTypeInSuper)) { + JetTypeImpl betterTypeInSuper = new JetTypeImpl( + arrayTypeFromSuper.getAnnotations(), + arrayTypeFromSuper.getConstructor(), + arrayTypeFromSuper.isNullable(), + Arrays.asList(new TypeProjection(Variance.OUT_VARIANCE, elementTypeInSuper)), + JetScope.EMPTY); + + reportError("Return type is not a subtype of overridden method. " + + "To fix it, add annotation with Kotlin signature to super method with type " + + DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(arrayTypeFromSuper) + " replaced with " + + DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(betterTypeInSuper) + " in return type"); + } + } + } + } } @NotNull diff --git a/compiler/testData/loadJavaCustom/arraysInSubtypes/ArraysInSubtypes.java b/compiler/testData/loadJavaCustom/arraysInSubtypes/ArraysInSubtypes.java new file mode 100644 index 00000000000..17ac585c40c --- /dev/null +++ b/compiler/testData/loadJavaCustom/arraysInSubtypes/ArraysInSubtypes.java @@ -0,0 +1,19 @@ +package test; + +import java.util.List; +import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError; + +public interface ArraysInSubtypes { + interface Super { + CharSequence[] array(); + List listOfArray(); + } + + interface Sub extends Super { + @ExpectLoadError("Return type is not a subtype of overridden method. To fix it, add annotation with Kotlin signature to super method with type Array? replaced with Array? in return type") + String[] array(); + + @ExpectLoadError("Return type is not a subtype of overridden method. To fix it, add annotation with Kotlin signature to super method with type Array? replaced with Array? in return type") + List listOfArray(); + } +} \ No newline at end of file diff --git a/compiler/testData/loadJavaCustom/arraysInSubtypes/ArraysInSubtypes.txt b/compiler/testData/loadJavaCustom/arraysInSubtypes/ArraysInSubtypes.txt new file mode 100644 index 00000000000..a1155fc1603 --- /dev/null +++ b/compiler/testData/loadJavaCustom/arraysInSubtypes/ArraysInSubtypes.txt @@ -0,0 +1,14 @@ +package test + +public trait ArraysInSubtypes : java.lang.Object { + + public trait Sub : test.ArraysInSubtypes.Super { + public abstract override /*1*/ fun array() : jet.Array? + public abstract override /*1*/ fun listOfArray() : jet.MutableList?>? + } + + public trait Super : java.lang.Object { + public abstract fun array() : jet.Array? + public abstract fun listOfArray() : jet.MutableList?>? + } +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java index edd4036efe5..38f1eedbad7 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java @@ -161,6 +161,12 @@ public final class LoadJavaCustomTest extends KotlinTestWithEnvironment { dir + "SubclassWithRawType.java"); } + public void testArraysInSubtypes() throws Exception { + String dir = PATH + "/arraysInSubtypes/"; + doTest(dir + "ArraysInSubtypes.txt", + dir + "ArraysInSubtypes.java"); + } + public void testMethodTypeParameterErased() throws Exception { String dir = PATH + "/methodTypeParameterErased/"; doTest(dir + "MethodTypeParameterErased.txt",