diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/CollectionClassMapping.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/CollectionClassMapping.java index cf33a29eac9..ea524166e43 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/CollectionClassMapping.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/CollectionClassMapping.java @@ -65,10 +65,19 @@ public class CollectionClassMapping extends JavaToKotlinClassMapBuilder { @NotNull public ClassDescriptor convertMutableToReadOnly(@NotNull ClassDescriptor mutable) { - ClassDescriptor immutable = mutableToReadOnlyMap.get(mutable); - if (immutable == null) { + ClassDescriptor readOnly = mutableToReadOnlyMap.get(mutable); + if (readOnly == null) { throw new IllegalArgumentException("Given class " + mutable + " is not a mutable collection"); } - return immutable; + return readOnly; + } + + @NotNull + public ClassDescriptor convertReadOnlyToMutable(@NotNull ClassDescriptor readOnly) { + ClassDescriptor mutable = mutableToReadOnlyMap.inverse().get(readOnly); + if (mutable == null) { + throw new IllegalArgumentException("Given class " + readOnly + " is not a read-only collection"); + } + return mutable; } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagation.java index bcdb6e084ea..fd49ba81f0a 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagation.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesPropagation.java @@ -140,7 +140,7 @@ public class SignaturesPropagation { } boolean resultNullable = typeMustBeNullable(autoType, typesFromSuper, covariantPosition, reportError); - ClassifierDescriptor resultClassifier = modifyTypeClassifier(autoType, typesFromSuper); + ClassifierDescriptor resultClassifier = modifyTypeClassifier(autoType, typesFromSuper, covariantPosition, reportError); List resultArguments = getTypeArgsOfType(autoType, resultClassifier, typesFromSuper, reportError); JetScope resultScope; if (resultClassifier instanceof ClassDescriptor) { @@ -334,7 +334,12 @@ public class SignaturesPropagation { } @NotNull - private static ClassifierDescriptor modifyTypeClassifier(@NotNull JetType autoType, @NotNull List typesFromSuper) { + private static ClassifierDescriptor modifyTypeClassifier( + @NotNull JetType autoType, + @NotNull List typesFromSuper, + boolean covariantPosition, + @NotNull Function1 reportError + ) { ClassifierDescriptor classifier = autoType.getConstructor().getDeclarationDescriptor(); if (!(classifier instanceof ClassDescriptor)) { assert classifier != null : "no declaration descriptor for type " + autoType; @@ -344,25 +349,43 @@ public class SignaturesPropagation { CollectionClassMapping collectionMapping = CollectionClassMapping.getInstance(); - if (collectionMapping.isMutableCollection(clazz)) { + boolean someSupersMutable = false; + boolean someSupersReadOnly = false; + for (JetType typeFromSuper : typesFromSuper) { + ClassifierDescriptor classifierFromSuper = typeFromSuper.getConstructor().getDeclarationDescriptor(); + if (classifierFromSuper instanceof ClassDescriptor) { + ClassDescriptor classFromSuper = (ClassDescriptor) classifierFromSuper; - boolean someSupersMutable = false; - boolean someSupersReadOnly = false; - for (JetType typeFromSuper : typesFromSuper) { - ClassifierDescriptor classifierFromSuper = typeFromSuper.getConstructor().getDeclarationDescriptor(); - if (classifierFromSuper instanceof ClassDescriptor) { - ClassDescriptor classFromSuper = (ClassDescriptor) classifierFromSuper; - - if (collectionMapping.isMutableCollection(classFromSuper)) { - someSupersMutable = true; - } - else if (collectionMapping.isReadOnlyCollection(classFromSuper)) { - someSupersReadOnly = true; - } + if (collectionMapping.isMutableCollection(classFromSuper)) { + someSupersMutable = true; + } + else if (collectionMapping.isReadOnlyCollection(classFromSuper)) { + someSupersReadOnly = true; } } + } - if (someSupersReadOnly && !someSupersMutable) { + if (covariantPosition) { + if (collectionMapping.isMutableCollection(clazz)) { + if (someSupersReadOnly && !someSupersMutable) { + return collectionMapping.convertMutableToReadOnly(clazz); + } + } + } + else { + if (someSupersMutable == someSupersReadOnly) { + //noinspection ConstantConditions + if (someSupersMutable && someSupersReadOnly) { + reportError.invoke("Incompatible types in superclasses: " + typesFromSuper); + } + return classifier; + } + + if (someSupersMutable && collectionMapping.isReadOnlyCollection(clazz)) { + return collectionMapping.convertReadOnlyToMutable(clazz); + } + + if (someSupersReadOnly && collectionMapping.isMutableCollection(clazz)) { return collectionMapping.convertMutableToReadOnly(clazz); } } diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.java b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.java new file mode 100644 index 00000000000..6d2304d504c --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.java @@ -0,0 +1,18 @@ +package test; + +import org.jetbrains.annotations.NotNull; +import jet.runtime.typeinfo.KotlinSignature; +import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError; +import java.util.*; + +public interface InheritMutability { + + public interface Super { + @KotlinSignature("fun foo(p: MutableList)") + void foo(List p); + } + + public interface Sub extends Super { + void foo(List p); + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.kt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.kt new file mode 100644 index 00000000000..bf5a0be738b --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.kt @@ -0,0 +1,12 @@ +package test + +public trait InheritMutability: Object { + + public trait Super: Object { + public fun foo(p0: MutableList) + } + + public trait Sub: Super { + override fun foo(p0: MutableList) + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.txt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.txt new file mode 100644 index 00000000000..18779e6e8a3 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.txt @@ -0,0 +1,10 @@ +namespace test + +public abstract trait test.InheritMutability : java.lang.Object { + public abstract trait test.InheritMutability.Sub : test.InheritMutability.Super { + public abstract override /*1*/ fun foo(/*0*/ p0: jet.MutableList): jet.Tuple0 + } + public abstract trait test.InheritMutability.Super : java.lang.Object { + public abstract fun foo(/*0*/ p0: jet.MutableList): jet.Tuple0 + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.java b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.java new file mode 100644 index 00000000000..d077d30a550 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.java @@ -0,0 +1,18 @@ +package test; + +import org.jetbrains.annotations.NotNull; +import jet.runtime.typeinfo.KotlinSignature; +import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError; +import java.util.*; + +public interface InheritReadOnliness { + + public interface Super { + @KotlinSignature("fun foo(p: List)") + void foo(List p); + } + + public interface Sub extends Super { + void foo(List p); + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.kt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.kt new file mode 100644 index 00000000000..1e6f1a0b361 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.kt @@ -0,0 +1,12 @@ +package test + +public trait InheritReadOnliness: Object { + + public trait Super: Object { + public fun foo(p0: List) + } + + public trait Sub: Super { + override fun foo(p0: List) + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.txt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.txt new file mode 100644 index 00000000000..c1719d861cc --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.txt @@ -0,0 +1,10 @@ +namespace test + +public abstract trait test.InheritReadOnliness : java.lang.Object { + public abstract trait test.InheritReadOnliness.Sub : test.InheritReadOnliness.Super { + public abstract override /*1*/ fun foo(/*0*/ p0: jet.List): jet.Tuple0 + } + public abstract trait test.InheritReadOnliness.Super : java.lang.Object { + public abstract fun foo(/*0*/ p0: jet.List): jet.Tuple0 + } +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 54375cf9f95..25a813772d7 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -451,11 +451,21 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/kotlinSignature/propagation/parameter"), "java", true); } + @TestMetadata("InheritMutability.java") + public void testInheritMutability() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.java"); + } + @TestMetadata("InheritNullability.java") public void testInheritNullability() throws Exception { doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNullability.java"); } + @TestMetadata("InheritReadOnliness.java") + public void testInheritReadOnliness() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.java"); + } + @TestMetadata("NotNullToNullable.java") public void testNotNullToNullable() throws Exception { doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/NotNullToNullable.java"); diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java index 815d1af71fb..5e0a7cf16e0 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -1341,11 +1341,21 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/kotlinSignature/propagation/parameter"), "kt", true); } + @TestMetadata("InheritMutability.kt") + public void testInheritMutability() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.kt"); + } + @TestMetadata("InheritNullability.kt") public void testInheritNullability() throws Exception { doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNullability.kt"); } + @TestMetadata("InheritReadOnliness.kt") + public void testInheritReadOnliness() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.kt"); + } + @TestMetadata("NotNullToNullable.kt") public void testNotNullToNullable() throws Exception { doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/NotNullToNullable.kt");