diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index f784e02d460..e6c80836b46 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -151,6 +151,8 @@ public class JetTypeMapper { register(JetStandardLibraryNames.ENUM, JL_ENUM_TYPE, JL_ENUM_TYPE); register(JetStandardLibraryNames.ITERABLE, JL_ITERABLE_TYPE, JL_ITERABLE_TYPE); register(JetStandardLibraryNames.ITERATOR, JL_ITERATOR_TYPE, JL_ITERATOR_TYPE); + register(JetStandardLibraryNames.MUTABLE_ITERABLE, JL_ITERABLE_TYPE, JL_ITERABLE_TYPE); + register(JetStandardLibraryNames.MUTABLE_ITERATOR, JL_ITERATOR_TYPE, JL_ITERATOR_TYPE); for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType(); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index b7e07542a26..9a6326a5cc9 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -1686,7 +1686,8 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes transformedType = semanticServices.getTypeTransformer().transformToType(returnTypeFromAnnotation, typeVariableResolver); } else { - transformedType = semanticServices.getTypeTransformer().transformToType(returnType, typeVariableResolver); + transformedType = semanticServices.getTypeTransformer().transformToType( + returnType, JavaTypeTransformer.TypeUsage.MEMBER_SIGNATURE_COVARIANT, typeVariableResolver); } if (method.getJetMethod().returnTypeNullable()) { return TypeUtils.makeNullableAsSpecified(transformedType, true); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java index 98bba84a679..ca684690294 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.lang.resolve.java; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; @@ -59,6 +60,7 @@ public class JavaTypeTransformer { private Map primitiveTypesMap; private Map classDescriptorMap; + private Map classDescriptorMapForCovariantPositions; @NotNull @@ -157,7 +159,7 @@ public class JavaTypeTransformer { // 'L extends List' in Java is a List in Kotlin, not a List boolean nullable = !EnumSet.of(SUPERTYPE_ARGUMENT, SUPERTYPE).contains(howThisTypeIsUsed); - ClassDescriptor classData = getKotlinAnalog(new FqName(psiClass.getQualifiedName())); + ClassDescriptor classData = getKotlinAnalog(new FqName(psiClass.getQualifiedName()), howThisTypeIsUsed); if (classData == null) { classData = resolver.resolveClass(new FqName(psiClass.getQualifiedName()), DescriptorSearchRule.INCLUDE_KOTLIN); @@ -255,7 +257,7 @@ public class JavaTypeTransformer { public Map getClassDescriptorMap() { if (classDescriptorMap == null) { - classDescriptorMap = new HashMap(); + classDescriptorMap = Maps.newHashMap(); for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType(); classDescriptorMap.put(jvmPrimitiveType.getWrapper().getFqName(), JetStandardLibrary.getInstance().getPrimitiveClassDescriptor(primitiveType)); @@ -273,8 +275,23 @@ public class JavaTypeTransformer { return classDescriptorMap; } + public Map getClassDescriptorMapForCovariantPositions() { + if (classDescriptorMapForCovariantPositions == null) { + classDescriptorMapForCovariantPositions = Maps.newHashMap(); + classDescriptorMapForCovariantPositions.put(new FqName("java.lang.Iterable"), JetStandardLibrary.getInstance().getMutableIterable()); + classDescriptorMapForCovariantPositions.put(new FqName("java.util.Iterator"), JetStandardLibrary.getInstance().getMutableIterator()); + } + return classDescriptorMapForCovariantPositions; + } + @Nullable - public ClassDescriptor getKotlinAnalog(@NotNull FqName fqName) { + public ClassDescriptor getKotlinAnalog(@NotNull FqName fqName, @NotNull TypeUsage typeUsage) { + if (typeUsage == MEMBER_SIGNATURE_COVARIANT) { + ClassDescriptor descriptor = getClassDescriptorMapForCovariantPositions().get(fqName); + if (descriptor != null) { + return descriptor; + } + } return getClassDescriptorMap().get(fqName); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java index 245a751d018..3d993f32329 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java @@ -95,7 +95,7 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd this.classDescriptor = null; if (!forceReal) { - classDescriptor = javaSemanticServices.getTypeTransformer().getKotlinAnalog(ourName); + classDescriptor = javaSemanticServices.getTypeTransformer().getKotlinAnalog(ourName, JavaTypeTransformer.TypeUsage.MEMBER_SIGNATURE_INVARIANT); } if (classDescriptor == null) { diff --git a/compiler/frontend/src/jet/Iterables.jet b/compiler/frontend/src/jet/Iterables.jet index 901636139f4..8f3f685a4bb 100644 --- a/compiler/frontend/src/jet/Iterables.jet +++ b/compiler/frontend/src/jet/Iterables.jet @@ -4,6 +4,10 @@ public trait Iterable { public fun iterator() : Iterator } +public trait MutableIterable : Iterable { + override fun iterator() : MutableIterator +} + public trait ByteIterable : Iterable { public override fun iterator() : ByteIterator } diff --git a/compiler/frontend/src/jet/Iterators.jet b/compiler/frontend/src/jet/Iterators.jet index 365b842c3ac..717504c7132 100644 --- a/compiler/frontend/src/jet/Iterators.jet +++ b/compiler/frontend/src/jet/Iterators.jet @@ -5,6 +5,10 @@ public trait Iterator { public fun hasNext() : Boolean } +public trait MutableIterator : Iterator { + public fun remove() +} + public abstract class ByteIterator() : Iterator { public abstract open fun nextByte() : Byte diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardLibrary.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardLibrary.java index 065f1b9aa02..b35e816202b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardLibrary.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardLibrary.java @@ -94,6 +94,8 @@ public class JetStandardLibrary { private ClassDescriptor arrayClass; private ClassDescriptor iterableClass; private ClassDescriptor iteratorClass; + private ClassDescriptor mutableIterableClass; + private ClassDescriptor mutableIteratorClass; private ClassDescriptor comparableClass; private ClassDescriptor throwableClass; private ClassDescriptor enumClass; @@ -170,6 +172,8 @@ public class JetStandardLibrary { this.iterableClass = (ClassDescriptor) libraryScope.getClassifier(Name.identifier("Iterable")); this.iteratorClass = (ClassDescriptor) libraryScope.getClassifier(Name.identifier("Iterator")); + this.mutableIterableClass = (ClassDescriptor) libraryScope.getClassifier(Name.identifier("MutableIterable")); + this.mutableIteratorClass = (ClassDescriptor) libraryScope.getClassifier(Name.identifier("MutableIterator")); this.comparableClass = (ClassDescriptor) libraryScope.getClassifier(Name.identifier("Comparable")); this.stringType = new JetTypeImpl(getString()); @@ -213,6 +217,8 @@ public class JetStandardLibrary { classDescriptors.add(throwableClass); classDescriptors.add(iterableClass); classDescriptors.add(iteratorClass); + classDescriptors.add(mutableIterableClass); + classDescriptors.add(mutableIteratorClass); classDescriptors.add(comparableClass); classDescriptors.add(enumClass); @@ -301,6 +307,18 @@ public class JetStandardLibrary { return iteratorClass; } + @NotNull + public ClassDescriptor getMutableIterable() { + initStdClasses(); + return mutableIterableClass; + } + + @NotNull + public ClassDescriptor getMutableIterator() { + initStdClasses(); + return mutableIteratorClass; + } + @NotNull public ClassDescriptor getComparable() { initStdClasses(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardLibraryNames.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardLibraryNames.java index 3034b3ac416..50ddc903adc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardLibraryNames.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/JetStandardLibraryNames.java @@ -41,6 +41,8 @@ public class JetStandardLibraryNames { public static final ClassName COMPARABLE = classIn("Comparable", 1); public static final ClassName ITERABLE = classIn("Iterable", 1); public static final ClassName ITERATOR = classIn("Iterator", 1); + public static final ClassName MUTABLE_ITERABLE = classIn("MutableIterable", 1); + public static final ClassName MUTABLE_ITERATOR = classIn("MutableIterator", 1); public static final ClassName NOTHING = classIn("Nothing", 0); public static final ClassName STRING = classIn("String", 0); public static final ClassName CHAR_SEQUENCE = classIn("CharSequence", 0); diff --git a/compiler/testData/builtin-classes.txt b/compiler/testData/builtin-classes.txt index 4dc04ec2196..c55c686c89f 100644 --- a/compiler/testData/builtin-classes.txt +++ b/compiler/testData/builtin-classes.txt @@ -832,6 +832,14 @@ public final class jet.LongRange : jet.Range, jet.LongIterable { public final val EMPTY: jet.LongRange } } +public abstract trait jet.MutableIterable : jet.Iterable { + public abstract override /*1*/ fun iterator(): jet.MutableIterator +} +public abstract trait jet.MutableIterator : jet.Iterator { + public abstract override /*1*/ fun hasNext(): jet.Boolean + public abstract override /*1*/ fun next(): T + public abstract fun remove(): jet.Tuple0 +} public final class jet.Nothing { private final /*constructor*/ fun (): jet.Nothing } diff --git a/compiler/testData/diagnostics/tests/j+k/mutableIterator.kt b/compiler/testData/diagnostics/tests/j+k/mutableIterator.kt new file mode 100644 index 00000000000..6cba8d1b63a --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/mutableIterator.kt @@ -0,0 +1,29 @@ +//FILE:a/JC.java +package a; + +import java.util.Iterator; + +public interface JC { + public Iterator getIterator(); + + public void setIterator(Iterator iterator); + + public Iterable getIterable(); + + public void setIterable(Iterable iterable); +} + +//FILE:n.kt +package n + +import a.JC + +fun foo(c: JC, iterator: Iterator, iterable: Iterable) { + val mutableIterator: MutableIterator? = c.getIterator() + c.setIterator(mutableIterator) + c.setIterator(iterator) + + val mutableIterable: MutableIterable? = c.getIterable() + c.setIterable(mutableIterable) + c.setIterable(iterable) +} \ No newline at end of file diff --git a/compiler/testData/loadJava/InnerClassesInGeneric.kt b/compiler/testData/loadJava/InnerClassesInGeneric.kt index 659635577d5..3cf9685624a 100644 --- a/compiler/testData/loadJava/InnerClassesInGeneric.kt +++ b/compiler/testData/loadJava/InnerClassesInGeneric.kt @@ -5,7 +5,7 @@ public open class InnerClassesInGeneric() : java.lang.Object() { } public open class Inner2() : Inner() { - public open fun iterator() : jet.Iterator

? { + public open fun iterator() : jet.MutableIterator

? { throw UnsupportedOperationException() } } diff --git a/compiler/testData/loadJava/InnerClassesInGeneric.txt b/compiler/testData/loadJava/InnerClassesInGeneric.txt index 677c76fc7d2..e67437fc583 100644 --- a/compiler/testData/loadJava/InnerClassesInGeneric.txt +++ b/compiler/testData/loadJava/InnerClassesInGeneric.txt @@ -7,6 +7,6 @@ public open class test.InnerClassesInGeneric(): test.InnerClassesInGeneric.Inner2 - public open fun iterator(): jet.Iterator

? + public open fun iterator(): jet.MutableIterator

? } } diff --git a/compiler/testData/loadJava/library/LoadIterable.java b/compiler/testData/loadJava/library/LoadIterable.java new file mode 100644 index 00000000000..ad0c98b69e1 --- /dev/null +++ b/compiler/testData/loadJava/library/LoadIterable.java @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test; + +public interface LoadIterable { + public Iterable getIterable(); + public void setIterable(Iterable Iterable); +} diff --git a/compiler/testData/loadJava/library/LoadIterable.kt b/compiler/testData/loadJava/library/LoadIterable.kt new file mode 100644 index 00000000000..22e4b3ea2f8 --- /dev/null +++ b/compiler/testData/loadJava/library/LoadIterable.kt @@ -0,0 +1,6 @@ +package test + +public trait LoadIterable : java.lang.Object { + public fun getIterable(): MutableIterable? + public fun setIterable(p0: Iterable?) +} diff --git a/compiler/testData/loadJava/library/LoadIterable.txt b/compiler/testData/loadJava/library/LoadIterable.txt new file mode 100644 index 00000000000..8dd05db16d8 --- /dev/null +++ b/compiler/testData/loadJava/library/LoadIterable.txt @@ -0,0 +1,6 @@ +namespace test + +public abstract trait test.LoadIterable : java.lang.Object { + public abstract fun getIterable(): jet.MutableIterable? + public abstract fun setIterable(/*0*/ p0: jet.Iterable?): jet.Tuple0 +} diff --git a/compiler/testData/loadJava/library/LoadIterator.java b/compiler/testData/loadJava/library/LoadIterator.java new file mode 100644 index 00000000000..2c262fa0f49 --- /dev/null +++ b/compiler/testData/loadJava/library/LoadIterator.java @@ -0,0 +1,8 @@ +package test; + +import java.util.Iterator; + +public interface LoadIterator { + public Iterator getIterator(); + public void setIterator(Iterator iterator); +} diff --git a/compiler/testData/loadJava/library/LoadIterator.kt b/compiler/testData/loadJava/library/LoadIterator.kt new file mode 100644 index 00000000000..d43c39e15b9 --- /dev/null +++ b/compiler/testData/loadJava/library/LoadIterator.kt @@ -0,0 +1,6 @@ +package test + +public trait LoadIterator : java.lang.Object { + public fun getIterator(): MutableIterator? + public fun setIterator(p0: Iterator?) +} diff --git a/compiler/testData/loadJava/library/LoadIterator.txt b/compiler/testData/loadJava/library/LoadIterator.txt new file mode 100644 index 00000000000..c75bdc8da61 --- /dev/null +++ b/compiler/testData/loadJava/library/LoadIterator.txt @@ -0,0 +1,6 @@ +namespace test + +public abstract trait test.LoadIterator : java.lang.Object { + public abstract fun getIterator(): jet.MutableIterator? + public abstract fun setIterator(/*0*/ p0: jet.Iterator?): jet.Tuple0 +} diff --git a/compiler/testData/loadJava/modality/ModalityOfFakeOverrides.txt b/compiler/testData/loadJava/modality/ModalityOfFakeOverrides.txt index efec7ae1889..224a5da6be8 100644 --- a/compiler/testData/loadJava/modality/ModalityOfFakeOverrides.txt +++ b/compiler/testData/loadJava/modality/ModalityOfFakeOverrides.txt @@ -12,7 +12,7 @@ public open class test.ModalityOfFakeOverrides : java.util.AbstractList? + public open override /*1*/ fun iterator(): jet.MutableIterator? public open override /*1*/ fun lastIndexOf(/*0*/ p0: jet.Any?): jet.Int public open override /*1*/ fun listIterator(): java.util.ListIterator? public open override /*1*/ fun listIterator(/*0*/ p0: jet.Int): java.util.ListIterator? diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 81a90ea22cb..baefd98e7f1 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -1706,6 +1706,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/j+k/kt2394.kt"); } + @TestMetadata("mutableIterator.kt") + public void testMutableIterator() throws Exception { + doTest("compiler/testData/diagnostics/tests/j+k/mutableIterator.kt"); + } + @TestMetadata("OverrideVararg.kt") public void testOverrideVararg() throws Exception { doTest("compiler/testData/diagnostics/tests/j+k/OverrideVararg.kt"); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index f01eb4fddad..a06b836b460 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -15,12 +15,15 @@ */ package org.jetbrains.jet.jvm.compiler; +import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestSuite; + +import java.io.File; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.test.TestMetadata; -import java.io.File; +import org.jetbrains.jet.jvm.compiler.AbstractLoadJavaTest; /** This class is generated by {@link org.jetbrains.jet.jvm.compiler.AbstractLoadJavaTest}. DO NOT MODIFY MANUALLY */ @TestMetadata("compiler/testData/loadJava") @@ -370,6 +373,24 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { } } + @TestMetadata("compiler/testData/loadJava/library") + public static class Library extends AbstractLoadJavaTest { + public void testAllFilesPresentInLibrary() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.jvm.compiler.AbstractLoadJavaTest", new File("compiler/testData/loadJava/library"), "java", false); + } + + @TestMetadata("LoadIterable.java") + public void testLoadIterable() throws Exception { + doTest("compiler/testData/loadJava/library/LoadIterable.java"); + } + + @TestMetadata("LoadIterator.java") + public void testLoadIterator() throws Exception { + doTest("compiler/testData/loadJava/library/LoadIterator.java"); + } + + } + @TestMetadata("compiler/testData/loadJava/modality") public static class Modality extends AbstractLoadJavaTest { public void testAllFilesPresentInModality() throws Exception { @@ -431,6 +452,7 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { suite.addTestSuite(Constructor.class); suite.addTestSuite(JavaBean.class); suite.addTest(KotlinSignature.innerSuite()); + suite.addTestSuite(Library.class); suite.addTestSuite(Modality.class); suite.addTestSuite(NotNull.class); suite.addTestSuite(Vararg.class);