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 fd49ba81f0a..69197269fd3 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 @@ -35,6 +35,7 @@ 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.TypeCheckingProcedure; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import java.util.*; @@ -75,7 +76,10 @@ public class SignaturesPropagation { } }); - JetType altType = modifyTypeAccordingToSuperMethods(originalParam.getType(), typesFromSuperMethods, false, reportError); + VarargCheckResult varargCheckResult = + checkVarargInSuperFunctions(originalParam, superFunctions, reportError); + + JetType altType = modifyTypeAccordingToSuperMethods(varargCheckResult.parameterType, typesFromSuperMethods, false, reportError); resultParameters.add(new ValueParameterDescriptorImpl( originalParam.getContainingDeclaration(), @@ -85,7 +89,7 @@ public class SignaturesPropagation { originalParam.isVar(), altType, originalParam.declaresDefaultValue(), - originalParam.getVarargElementType() + varargCheckResult.isVararg ? KotlinBuiltIns.getInstance().getArrayElementType(altType) : null )); } @@ -127,6 +131,49 @@ public class SignaturesPropagation { return superFunctions; } + @NotNull + private static VarargCheckResult checkVarargInSuperFunctions( + @NotNull ValueParameterDescriptor originalParam, + @NotNull List superFunctions, + @NotNull Function1 reportError + ) { + boolean someSupersVararg = false; + boolean someSupersNotVararg = false; + for (FunctionDescriptor superFunction : superFunctions) { + if (superFunction.getValueParameters().get(originalParam.getIndex()).getVarargElementType() != null) { + someSupersVararg = true; + } + else { + someSupersNotVararg = true; + } + } + + JetType originalVarargElementType = originalParam.getVarargElementType(); + JetType originalType = originalParam.getType(); + + if (someSupersVararg && someSupersNotVararg) { + reportError.invoke("Incompatible super methods: some have vararg parameter, some have not"); + return new VarargCheckResult(originalType, originalVarargElementType != null); + } + + if (someSupersVararg && originalVarargElementType == null) { + assert KotlinBuiltIns.getInstance().isArray(originalType); + + // convert to vararg; replace Array? with Array + JetType varargElementType = KotlinBuiltIns.getInstance().getArrayElementType(originalType); + return new VarargCheckResult(KotlinBuiltIns.getInstance().getArrayType(varargElementType), true); + } + else if (someSupersNotVararg && originalVarargElementType != null) { + assert KotlinBuiltIns.getInstance().isArray(originalType); + + // convert to non-vararg; replace Array with Array? + return new VarargCheckResult( + TypeUtils.makeNullable(KotlinBuiltIns.getInstance().getArrayType(Variance.OUT_VARIANCE, originalVarargElementType)), + false); + } + + return new VarargCheckResult(originalType, originalVarargElementType != null); + } @NotNull private static JetType modifyTypeAccordingToSuperMethods( @@ -394,4 +441,14 @@ public class SignaturesPropagation { private SignaturesPropagation() { } + + private static class VarargCheckResult { + public final JetType parameterType; + public final boolean isVararg; + + private VarargCheckResult(JetType parameterType, boolean isVararg) { + this.parameterType = parameterType; + this.isVararg = isVararg; + } + } } diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVararg.java b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVararg.java new file mode 100644 index 00000000000..4385f4175ea --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVararg.java @@ -0,0 +1,12 @@ +package test; + +public interface InheritNotVararg { + + public interface Super { + void foo(String[] p); + } + + public interface Sub extends Super { + void foo(String... p); + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVararg.kt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVararg.kt new file mode 100644 index 00000000000..3947c5029c4 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVararg.kt @@ -0,0 +1,12 @@ +package test + +public trait InheritNotVararg: Object { + + public trait Super: Object { + public fun foo(p0: Array?) + } + + public trait Sub: Super { + override fun foo(p0: Array?) + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVararg.txt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVararg.txt new file mode 100644 index 00000000000..61e72c2a67d --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVararg.txt @@ -0,0 +1,10 @@ +namespace test + +public abstract trait test.InheritNotVararg : java.lang.Object { + public abstract trait test.InheritNotVararg.Sub : test.InheritNotVararg.Super { + public abstract override /*1*/ fun foo(/*0*/ p0: jet.Array?): jet.Tuple0 + } + public abstract trait test.InheritNotVararg.Super : java.lang.Object { + public abstract fun foo(/*0*/ p0: jet.Array?): jet.Tuple0 + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVarargNotNull.java b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVarargNotNull.java new file mode 100644 index 00000000000..c2d95af9a08 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVarargNotNull.java @@ -0,0 +1,15 @@ +package test; + +import jet.runtime.typeinfo.KotlinSignature; + +public interface InheritNotVarargNotNull { + + public interface Super { + @KotlinSignature("fun foo(p: Array)") + void foo(String[] p); + } + + public interface Sub extends Super { + void foo(String... p); + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVarargNotNull.kt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVarargNotNull.kt new file mode 100644 index 00000000000..bd1d42e1406 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVarargNotNull.kt @@ -0,0 +1,12 @@ +package test + +public trait InheritNotVarargNotNull: Object { + + public trait Super: Object { + public fun foo(p0: Array) + } + + public trait Sub: Super { + override fun foo(p0: Array) + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVarargNotNull.txt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVarargNotNull.txt new file mode 100644 index 00000000000..1db60a73dc9 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVarargNotNull.txt @@ -0,0 +1,10 @@ +namespace test + +public abstract trait test.InheritNotVarargNotNull : java.lang.Object { + public abstract trait test.InheritNotVarargNotNull.Sub : test.InheritNotVarargNotNull.Super { + public abstract override /*1*/ fun foo(/*0*/ p0: jet.Array): jet.Tuple0 + } + public abstract trait test.InheritNotVarargNotNull.Super : java.lang.Object { + public abstract fun foo(/*0*/ p0: jet.Array): jet.Tuple0 + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVararg.java b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVararg.java new file mode 100644 index 00000000000..f8a6d4388a7 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVararg.java @@ -0,0 +1,12 @@ +package test; + +public interface InheritVararg { + + public interface Super { + void foo(String... p); + } + + public interface Sub extends Super { + void foo(String[] p); + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVararg.kt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVararg.kt new file mode 100644 index 00000000000..c5dff9e67de --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVararg.kt @@ -0,0 +1,12 @@ +package test + +public trait InheritVararg: Object { + + public trait Super: Object { + public fun foo(vararg p0: String?) + } + + public trait Sub: Super { + override fun foo(vararg p0: String?) + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVararg.txt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVararg.txt new file mode 100644 index 00000000000..7bad1fdbfbb --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVararg.txt @@ -0,0 +1,10 @@ +namespace test + +public abstract trait test.InheritVararg : java.lang.Object { + public abstract trait test.InheritVararg.Sub : test.InheritVararg.Super { + public abstract override /*1*/ fun foo(/*0*/ vararg p0: jet.String? /*jet.Array*/): jet.Tuple0 + } + public abstract trait test.InheritVararg.Super : java.lang.Object { + public abstract fun foo(/*0*/ vararg p0: jet.String? /*jet.Array*/): jet.Tuple0 + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVarargNotNull.java b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVarargNotNull.java new file mode 100644 index 00000000000..eef9c8fbc76 --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVarargNotNull.java @@ -0,0 +1,15 @@ +package test; + +import jet.runtime.typeinfo.KotlinSignature; + +public interface InheritVarargNotNull { + + public interface Super { + @KotlinSignature("fun foo(vararg p: String)") + void foo(String... p); + } + + public interface Sub extends Super { + void foo(String[] p); + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVarargNotNull.kt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVarargNotNull.kt new file mode 100644 index 00000000000..6556b02705f --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVarargNotNull.kt @@ -0,0 +1,12 @@ +package test + +public trait InheritVarargNotNull: Object { + + public trait Super: Object { + public fun foo(vararg p0: String) + } + + public trait Sub: Super { + override fun foo(vararg p0: String) + } +} diff --git a/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVarargNotNull.txt b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVarargNotNull.txt new file mode 100644 index 00000000000..b5f9e5e85fa --- /dev/null +++ b/compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVarargNotNull.txt @@ -0,0 +1,10 @@ +namespace test + +public abstract trait test.InheritVarargNotNull : java.lang.Object { + public abstract trait test.InheritVarargNotNull.Sub : test.InheritVarargNotNull.Super { + public abstract override /*1*/ fun foo(/*0*/ vararg p0: jet.String /*jet.Array*/): jet.Tuple0 + } + public abstract trait test.InheritVarargNotNull.Super : java.lang.Object { + public abstract fun foo(/*0*/ vararg p0: jet.String /*jet.Array*/): jet.Tuple0 + } +} diff --git a/compiler/testData/loadJavaCustom/kotlinSignature/TwoSuperclassesVarargAndNot.java b/compiler/testData/loadJavaCustom/kotlinSignature/TwoSuperclassesVarargAndNot.java new file mode 100644 index 00000000000..33668f708e2 --- /dev/null +++ b/compiler/testData/loadJavaCustom/kotlinSignature/TwoSuperclassesVarargAndNot.java @@ -0,0 +1,26 @@ +package test; + +import org.jetbrains.annotations.NotNull; + +import java.lang.String; +import java.util.List; + +import jet.runtime.typeinfo.KotlinSignature; +import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError; + +public interface TwoSuperclassesVarargAndNot { + public interface Super1 { + void foo(String... s); + } + + public interface Super2 { + void foo(String[] s); + } + + public interface Sub extends Super1, Super2 { + @ExpectLoadError("Incompatible projection kinds in type arguments of super methods' return types: [String?, out String?]|" + + "Incompatible super methods: some have vararg parameter, some have not|" + + "Incompatible types in superclasses: [Array, Array?]") + void foo(String[] s); + } +} \ No newline at end of file diff --git a/compiler/testData/loadJavaCustom/kotlinSignature/TwoSuperclassesVarargAndNot.txt b/compiler/testData/loadJavaCustom/kotlinSignature/TwoSuperclassesVarargAndNot.txt new file mode 100644 index 00000000000..a31e0f772ea --- /dev/null +++ b/compiler/testData/loadJavaCustom/kotlinSignature/TwoSuperclassesVarargAndNot.txt @@ -0,0 +1,14 @@ +namespace test + +public abstract trait test.TwoSuperclassesVarargAndNot : java.lang.Object { + public abstract trait test.TwoSuperclassesVarargAndNot.Sub : test.TwoSuperclassesVarargAndNot.Super1, test.TwoSuperclassesVarargAndNot.Super2 { + public abstract override /*1*/ fun foo(/*0*/ p0: jet.Array?): jet.Tuple0 + public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ vararg p0: jet.String? /*jet.Array*/): jet.Tuple0 + } + public abstract trait test.TwoSuperclassesVarargAndNot.Super1 : java.lang.Object { + public abstract fun foo(/*0*/ vararg p0: jet.String? /*jet.Array*/): jet.Tuple0 + } + public abstract trait test.TwoSuperclassesVarargAndNot.Super2 : java.lang.Object { + public abstract fun foo(/*0*/ p0: jet.Array?): jet.Tuple0 + } +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java index c443efbbaa1..a14c71dc7e7 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaCustomTest.java @@ -98,6 +98,12 @@ public final class LoadJavaCustomTest extends KotlinTestWithEnvironment { dir + "TwoSuperclassesInconsistentGenericTypes.java"); } + public void testKotlinSignatureTwoSuperclassesVarargAndNot() throws Exception { + String dir = PATH + "/kotlinSignature/"; + doTest(dir + "TwoSuperclassesVarargAndNot.txt", + dir + "TwoSuperclassesVarargAndNot.java"); + } + //TODO: move to LoadJavaTestGenerated when possible public void testEnum() throws Exception { String dir = PATH + "/enum"; diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 772d35a2081..7297da9ffea 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -456,6 +456,16 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.java"); } + @TestMetadata("InheritNotVararg.java") + public void testInheritNotVararg() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVararg.java"); + } + + @TestMetadata("InheritNotVarargNotNull.java") + public void testInheritNotVarargNotNull() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVarargNotNull.java"); + } + @TestMetadata("InheritNullability.java") public void testInheritNullability() throws Exception { doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNullability.java"); @@ -471,6 +481,16 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.java"); } + @TestMetadata("InheritVararg.java") + public void testInheritVararg() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVararg.java"); + } + + @TestMetadata("InheritVarargNotNull.java") + public void testInheritVarargNotNull() throws Exception { + doTest("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVarargNotNull.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 a1f526b0344..9882094623a 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveNamespaceComparingTestGenerated.java @@ -1346,6 +1346,16 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritMutability.kt"); } + @TestMetadata("InheritNotVararg.kt") + public void testInheritNotVararg() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVararg.kt"); + } + + @TestMetadata("InheritNotVarargNotNull.kt") + public void testInheritNotVarargNotNull() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNotVarargNotNull.kt"); + } + @TestMetadata("InheritNullability.kt") public void testInheritNullability() throws Exception { doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritNullability.kt"); @@ -1361,6 +1371,16 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritReadOnliness.kt"); } + @TestMetadata("InheritVararg.kt") + public void testInheritVararg() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVararg.kt"); + } + + @TestMetadata("InheritVarargNotNull.kt") + public void testInheritVarargNotNull() throws Exception { + doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/InheritVarargNotNull.kt"); + } + @TestMetadata("NotNullToNullable.kt") public void testNotNullToNullable() throws Exception { doTestSinglePackage("compiler/testData/loadJava/kotlinSignature/propagation/parameter/NotNullToNullable.kt");