diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java index 9fcf3830627..c7d1aeef4ad 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java @@ -328,7 +328,7 @@ public final class JavaFunctionResolver { return autoArguments; } - List> typeArgumentsFromSuper = calculateTypeArgumentsFromSuper(autoType, typesFromSuper); + List> typeArgumentsFromSuper = calculateTypeArgumentsFromSuper(autoType, typesFromSuper); // Modify type arguments using info from typesFromSuper List resultArguments = Lists.newArrayList(); @@ -339,17 +339,55 @@ public final class JavaFunctionResolver { TypeCheckingProcedure.getEffectiveProjectionKind(typeConstructor.getParameters().get(i), argument); JetType argumentType = argument.getType(); - Collection argumentTypesFromSuper = typeArgumentsFromSuper.get(i); + List projectionsFromSuper = typeArgumentsFromSuper.get(i); + Collection argTypesFromSuper = getTypes(projectionsFromSuper); boolean covariantPosition = effectiveProjectionKind == TypeCheckingProcedure.EnrichedProjectionKind.OUT; - JetType type = modifyReturnTypeAccordingToSuperMethods(argumentType, argumentTypesFromSuper, covariantPosition); - resultArguments.add(new TypeProjection(argument.getProjectionKind(), type)); + JetType type = modifyReturnTypeAccordingToSuperMethods(argumentType, argTypesFromSuper, covariantPosition); + Variance variance = calculateArgumentVarianceFromSuper(argument, projectionsFromSuper); + + resultArguments.add(new TypeProjection(variance, type)); } return resultArguments; } + private static Variance calculateArgumentVarianceFromSuper(TypeProjection argument, List projectionsFromSuper) { + Set variancesInSuper = Sets.newHashSet(); + for (TypeProjection projection : projectionsFromSuper) { + variancesInSuper.add(projection.getProjectionKind()); + } + + Variance defaultVariance = argument.getProjectionKind(); + if (variancesInSuper.size() == 0) { + return defaultVariance; + } + else if (variancesInSuper.size() == 1) { + Variance varianceInSuper = variancesInSuper.iterator().next(); + if (defaultVariance == Variance.INVARIANT || defaultVariance == varianceInSuper) { + return varianceInSuper; + } + else { + // TODO report error + return defaultVariance; + } + } + else { + // TODO report error + return defaultVariance; + } + } + + @NotNull + private static List getTypes(@NotNull List projections) { + List types = Lists.newArrayList(); + for (TypeProjection projection : projections) { + types.add(projection.getType()); + } + return types; + } + // Returns list with type arguments info from supertypes - private static List> calculateTypeArgumentsFromSuper( + private static List> calculateTypeArgumentsFromSuper( @NotNull JetType autoType, @NotNull Collection typesFromSuper ) { @@ -360,9 +398,9 @@ public final class JavaFunctionResolver { TypeUtils.makeUnsubstitutedType(klass, null)); // for each parameter of autoType, hold arguments in corresponding supertypes - List> parameterToArgTypesFromSuper = Lists.newArrayList(); + List> parameterToArgTypesFromSuper = Lists.newArrayList(); for (TypeProjection ignored : autoType.getArguments()) { - parameterToArgTypesFromSuper.add(new ArrayList()); + parameterToArgTypesFromSuper.add(new ArrayList()); } // Enumerate all types from super and all its parameters @@ -370,7 +408,7 @@ public final class JavaFunctionResolver { List typeFromSuperParameters = typeFromSuper.getConstructor().getParameters(); for (int i = 0; i < typeFromSuperParameters.size(); i++) { TypeParameterDescriptor typeFromSuperParam = typeFromSuperParameters.get(i); - JetType typeFromSuperArgType = typeFromSuper.getArguments().get(i).getType(); + TypeProjection typeFromSuperArgType = typeFromSuper.getArguments().get(i); // if it is mapped to autoType's parameter, then store it into map for (TypeProjection projection : substitution.get(typeFromSuperParam.getTypeConstructor())) { diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritVariance.java b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritVariance.java new file mode 100644 index 00000000000..b8e13663a35 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritVariance.java @@ -0,0 +1,20 @@ +package test; + +import org.jetbrains.annotations.NotNull; +import java.util.List; +import java.util.Collection; + +import jet.runtime.typeinfo.KotlinSignature; + +public class InheritVariance { + @KotlinSignature("fun foo(): MutableCollection") + public Collection foo() { + throw new UnsupportedOperationException(); + } + + public class Sub extends InheritVariance { + public List foo() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritVariance.kt b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritVariance.kt new file mode 100644 index 00000000000..9aa80270851 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritVariance.kt @@ -0,0 +1,11 @@ +package test + +import org.jetbrains.annotations.NotNull + +public open class InheritVariance : java.lang.Object() { + public open fun foo(): MutableCollection = throw UnsupportedOperationException() + + public open class Sub: InheritVariance() { + override fun foo(): MutableList = throw UnsupportedOperationException() + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritVariance.txt b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritVariance.txt new file mode 100644 index 00000000000..d9c1ecc2fa0 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/return/InheritVariance.txt @@ -0,0 +1,10 @@ +namespace test + +public open class test.InheritVariance : java.lang.Object { + public final /*constructor*/ fun (): test.InheritVariance + public open fun foo(): jet.MutableCollection + public open class test.InheritVariance.Sub : test.InheritVariance { + public final /*constructor*/ fun (): test.InheritVariance.Sub + public open override /*1*/ fun foo(): jet.MutableList + } +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index af5cd7756c0..b28946d7ecf 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -516,6 +516,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.java"); } + @TestMetadata("InheritVariance.java") + public void testInheritVariance() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritVariance.java"); + } + } public static Test innerSuite() { 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 fc8e842384d..e09ebd224b6 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -1411,6 +1411,11 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritReadOnlinessSubclass.kt"); } + @TestMetadata("InheritVariance.kt") + public void testInheritVariance() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/return/InheritVariance.kt"); + } + } public static Test innerSuite() {