Checking redundant/conflicting projection kind in alt signatures.

This commit is contained in:
Evgeny Gerashchenko
2013-02-01 13:55:01 +04:00
parent a47ff5cdb5
commit 4be1e7d8d8
15 changed files with 111 additions and 20 deletions
@@ -25,7 +25,10 @@ import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.JavaToKotlinClassMap;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.KotlinToJavaTypesMap;
import org.jetbrains.jet.lang.resolve.java.TypeUsage;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
@@ -33,7 +36,8 @@ import org.jetbrains.jet.renderer.DescriptorRenderer;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.java.TypeUsage.*;
import static org.jetbrains.jet.lang.resolve.java.TypeUsage.TYPE_ARGUMENT;
import static org.jetbrains.jet.lang.types.Variance.INVARIANT;
class TypeTransformingVisitor extends JetVisitor<JetType, Void> {
private final JetType originalType;
@@ -113,6 +117,18 @@ class TypeTransformingVisitor extends JetVisitor<JetType, Void> {
throw new AlternativeSignatureMismatchException("Alternative signature type mismatch, expected: %s, actual: %s", qualifiedName, fqName);
}
TypeConstructor typeConstructor;
if (classFromLibrary != null) {
typeConstructor = classFromLibrary.getTypeConstructor();
}
else {
typeConstructor = originalTypeConstructor;
}
ClassifierDescriptor typeConstructorClassifier = typeConstructor.getDeclarationDescriptor();
if (typeConstructorClassifier instanceof TypeParameterDescriptor && originalToAltTypeParameters.containsKey(typeConstructorClassifier)) {
typeConstructor = originalToAltTypeParameters.get(typeConstructorClassifier).getTypeConstructor();
}
List<TypeProjection> arguments = originalType.getArguments();
if (arguments.size() != type.getTypeArgumentsAsTypes().size()) {
@@ -138,6 +154,7 @@ class TypeTransformingVisitor extends JetVisitor<JetType, Void> {
JetTypeElement argumentAlternativeTypeElement = typeReference.getTypeElement();
assert argumentAlternativeTypeElement != null;
TypeParameterDescriptor parameter = typeConstructor.getParameters().get(i);
TypeProjection argument = arguments.get(i);
JetType alternativeArgumentType = computeType(argumentAlternativeTypeElement, argument.getType(), originalToAltTypeParameters, TYPE_ARGUMENT);
Variance projectionKind = argument.getProjectionKind();
@@ -160,6 +177,16 @@ class TypeTransformingVisitor extends JetVisitor<JetType, Void> {
throw new AlternativeSignatureMismatchException("Projection kind mismatch, actual: %s, in alternative signature: %s",
projectionKind, altProjectionKind);
}
if (altProjectionKind != INVARIANT && parameter.getVariance() != INVARIANT) {
if (altProjectionKind == parameter.getVariance()) {
// TODO report redundant if in strict mode
}
else {
throw new AlternativeSignatureMismatchException("Projection kind '%s' is conflicting with variance of %s",
altProjectionKind, DescriptorUtils.getFQName(typeConstructor.getDeclarationDescriptor()));
}
altProjectionKind = projectionKind;
}
}
else {
altProjectionKind = projectionKind;
@@ -167,17 +194,6 @@ class TypeTransformingVisitor extends JetVisitor<JetType, Void> {
altArguments.add(new TypeProjection(altProjectionKind, alternativeArgumentType));
}
TypeConstructor typeConstructor;
if (classFromLibrary != null) {
typeConstructor = classFromLibrary.getTypeConstructor();
}
else {
typeConstructor = originalTypeConstructor;
}
ClassifierDescriptor typeConstructorClassifier = typeConstructor.getDeclarationDescriptor();
if (typeConstructorClassifier instanceof TypeParameterDescriptor && originalToAltTypeParameters.containsKey(typeConstructorClassifier)) {
typeConstructor = originalToAltTypeParameters.get(typeConstructorClassifier).getTypeConstructor();
}
JetScope memberScope;
if (typeConstructorClassifier instanceof TypeParameterDescriptor) {
memberScope = ((TypeParameterDescriptor) typeConstructorClassifier).getUpperBoundsAsType().getMemberScope();
@@ -5,8 +5,8 @@ import java.util.*;
import jet.runtime.typeinfo.KotlinSignature;
public class MethodWithMappedClasses {
@KotlinSignature("fun <T> copy(dest : MutableList<in T>, src : List<out T>)")
public <T> void copy(List<? super T> dest, List<? extends T> src) {
@KotlinSignature("fun <T> copy(dest : MutableList<in T>, src : List<T>)")
public <T> void copy(List<? super T> dest, List<T> src) {
throw new UnsupportedOperationException();
}
}
@@ -3,5 +3,5 @@ package test
import java.util.*
public open class MethodWithMappedClasses : Object() {
public open fun <T> copy(p0 : MutableList<in T>, p1 : List<out T>) {}
public open fun <T> copy(p0 : MutableList<in T>, p1 : List<T>) {}
}
@@ -2,5 +2,5 @@ package test
public open class MethodWithMappedClasses : java.lang.Object {
public constructor MethodWithMappedClasses()
public open fun </*0*/ T> copy(/*0*/ p0 : jet.MutableList<in T>, /*1*/ p1 : jet.List<out T>) : Unit
public open fun </*0*/ T> copy(/*0*/ p0 : jet.MutableList<in T>, /*1*/ p1 : jet.List<T>) : Unit
}
@@ -8,7 +8,7 @@ import java.util.List;
import jet.runtime.typeinfo.KotlinSignature;
public class MethodWithTypeParameters {
@KotlinSignature("fun <A, B : Runnable> foo(a : A, b : List<out B>, c: MutableList<in String?>) where B : List<Cloneable>")
@KotlinSignature("fun <A, B : Runnable> foo(a : A, b : List<B>, c: MutableList<in String?>) where B : List<Cloneable>")
public <A, B extends Runnable & List<Cloneable>> void foo(A a, List<? extends B> b, List<? super String> list) {
}
}
@@ -3,6 +3,6 @@ package test
import java.util.*
public open class MethodWithTypeParameters : Object() {
public open fun <erased A, erased B : Runnable> foo(p0 : A, p1 : List<out B>, p2: MutableList<in String?>) where B : List<Cloneable> {
public open fun <erased A, erased B : Runnable> foo(p0 : A, p1 : List<B>, p2: MutableList<in String?>) where B : List<Cloneable> {
}
}
@@ -2,5 +2,5 @@ package test
public open class MethodWithTypeParameters : java.lang.Object {
public constructor MethodWithTypeParameters()
public open fun </*0*/ A, /*1*/ B> foo(/*0*/ p0 : A, /*1*/ p1 : jet.List<out B>, /*2*/ p2 : jet.MutableList<in jet.String?>) : Unit where B : java.lang.Runnable, B : jet.List<java.lang.Cloneable>
public open fun </*0*/ A, /*1*/ B> foo(/*0*/ p0 : A, /*1*/ p1 : jet.List<B>, /*2*/ p2 : jet.MutableList<in jet.String?>) : Unit where B : java.lang.Runnable, B : jet.List<java.lang.Cloneable>
}
@@ -0,0 +1,15 @@
package test;
import java.lang.Number;
import java.util.*;
import jet.runtime.typeinfo.KotlinSignature;
import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError;
public class ConflictingProjectionKind {
@ExpectLoadError("Projection kind 'in' is conflicting with variance of jet.List")
@KotlinSignature("fun foo(list: List<in Number>)")
public void foo(List<Number> list) {
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,7 @@
package test
public open class ConflictingProjectionKind : Object() {
public open fun foo(p0: List<Number>?) {
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,6 @@
package test
public open class ConflictingProjectionKind : java.lang.Object {
public constructor ConflictingProjectionKind()
public open fun foo(/*0*/ p0 : jet.List<jet.Number>?) : Unit
}
@@ -0,0 +1,14 @@
package test;
import java.lang.Number;
import java.util.*;
import jet.runtime.typeinfo.KotlinSignature;
import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError;
public class RedundantProjectionKind {
@KotlinSignature("fun foo(list: List<out Number>)")
public void foo(List<Number> list) {
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,7 @@
package test
public open class RedundantProjectionKind : Object() {
public open fun foo(p0: List<Number>) {
throw UnsupportedOperationException()
}
}
@@ -0,0 +1,6 @@
package test
public open class RedundantProjectionKind : java.lang.Object {
public constructor RedundantProjectionKind()
public open fun foo(/*0*/ p0 : jet.List<jet.Number>) : Unit
}
@@ -343,6 +343,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/kotlinSignature/error"), "java", true);
}
@TestMetadata("ConflictingProjectionKind.java")
public void testConflictingProjectionKind() throws Exception {
doTest("compiler/testData/loadJava/kotlinSignature/error/ConflictingProjectionKind.java");
}
@TestMetadata("ExplicitFieldGettersAndSetters.java")
public void testExplicitFieldGettersAndSetters() throws Exception {
doTest("compiler/testData/loadJava/kotlinSignature/error/ExplicitFieldGettersAndSetters.java");
@@ -368,6 +373,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
doTest("compiler/testData/loadJava/kotlinSignature/error/NotVarargReplacedWithVararg.java");
}
@TestMetadata("RedundantProjectionKind.java")
public void testRedundantProjectionKind() throws Exception {
doTest("compiler/testData/loadJava/kotlinSignature/error/RedundantProjectionKind.java");
}
@TestMetadata("ReturnTypeMissing.java")
public void testReturnTypeMissing() throws Exception {
doTest("compiler/testData/loadJava/kotlinSignature/error/ReturnTypeMissing.java");
@@ -1312,6 +1312,11 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/loadJava/kotlinSignature/error"), "kt", true);
}
@TestMetadata("ConflictingProjectionKind.kt")
public void testConflictingProjectionKind() throws Exception {
doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/kotlinSignature/error/ConflictingProjectionKind.kt");
}
@TestMetadata("ExplicitFieldGettersAndSetters.kt")
public void testExplicitFieldGettersAndSetters() throws Exception {
doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/kotlinSignature/error/ExplicitFieldGettersAndSetters.kt");
@@ -1337,6 +1342,11 @@ public class LazyResolveNamespaceComparingTestGenerated extends AbstractLazyReso
doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/kotlinSignature/error/NotVarargReplacedWithVararg.kt");
}
@TestMetadata("RedundantProjectionKind.kt")
public void testRedundantProjectionKind() throws Exception {
doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/kotlinSignature/error/RedundantProjectionKind.kt");
}
@TestMetadata("ReturnTypeMissing.kt")
public void testReturnTypeMissing() throws Exception {
doTestNotCheckingPrimaryConstructors("compiler/testData/loadJava/kotlinSignature/error/ReturnTypeMissing.kt");