Redundant/conflicting projections
This commit is contained in:
@@ -86,11 +86,13 @@ public interface Errors {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SimpleDiagnosticFactory<JetTypeProjection> PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = SimpleDiagnosticFactory.create(ERROR, PROJECTION_MODIFIER);
|
||||
SimpleDiagnosticFactory<JetTypeProjection> PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = SimpleDiagnosticFactory.create(ERROR, VARIANCE_IN_PROJECTION);
|
||||
DiagnosticFactory2<JetTypeReference, JetType, JetType> UPPER_BOUND_VIOLATED = DiagnosticFactory2.create(ERROR);
|
||||
SimpleDiagnosticFactory<JetNullableType> REDUNDANT_NULLABLE = SimpleDiagnosticFactory.create(WARNING, NULLABLE_TYPE);
|
||||
DiagnosticFactory1<JetNullableType, JetType> BASE_WITH_NULLABLE_UPPER_BOUND = DiagnosticFactory1.create(WARNING, NULLABLE_TYPE);
|
||||
DiagnosticFactory1<JetElement, Integer> WRONG_NUMBER_OF_TYPE_ARGUMENTS = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<JetTypeProjection, ClassifierDescriptor> CONFLICTING_PROJECTION = DiagnosticFactory1.create(ERROR, VARIANCE_IN_PROJECTION);
|
||||
DiagnosticFactory1<JetTypeProjection, ClassifierDescriptor> REDUNDANT_PROJECTION = DiagnosticFactory1.create(WARNING, VARIANCE_IN_PROJECTION);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -121,7 +123,7 @@ public interface Errors {
|
||||
// Classes and traits
|
||||
|
||||
SimpleDiagnosticFactory<JetTypeProjection> PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE =
|
||||
SimpleDiagnosticFactory.create(ERROR, PROJECTION_MODIFIER);
|
||||
SimpleDiagnosticFactory.create(ERROR, VARIANCE_IN_PROJECTION);
|
||||
|
||||
SimpleDiagnosticFactory<PsiElement> CYCLIC_INHERITANCE_HIERARCHY = SimpleDiagnosticFactory.create(ERROR);
|
||||
|
||||
|
||||
@@ -183,7 +183,8 @@ public class PositioningStrategies {
|
||||
};
|
||||
}
|
||||
|
||||
public static final PositioningStrategy<JetModifierListOwner> VARIANCE_MODIFIER = modifierSetPosition(JetTokens.IN_KEYWORD, JetTokens.OUT_KEYWORD);
|
||||
public static final PositioningStrategy<JetModifierListOwner> VARIANCE_MODIFIER = modifierSetPosition(JetTokens.IN_KEYWORD,
|
||||
JetTokens.OUT_KEYWORD);
|
||||
|
||||
public static PositioningStrategy<JetModifierListOwner> modifierSetPosition(final JetKeywordToken... tokens) {
|
||||
return new PositioningStrategy<JetModifierListOwner>() {
|
||||
@@ -233,7 +234,7 @@ public class PositioningStrategies {
|
||||
}
|
||||
};
|
||||
|
||||
public static final PositioningStrategy<JetTypeProjection> PROJECTION_MODIFIER = new PositioningStrategy<JetTypeProjection>() {
|
||||
public static final PositioningStrategy<JetTypeProjection> VARIANCE_IN_PROJECTION = new PositioningStrategy<JetTypeProjection>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<TextRange> mark(@NotNull JetTypeProjection element) {
|
||||
|
||||
+2
@@ -320,6 +320,8 @@ public class DefaultErrorMessages {
|
||||
NAME);
|
||||
|
||||
MAP.put(VARIANCE_ON_FUNCTION_OR_PROPERTY_PARAMETER, "Variance annotations are only allowed for type parameters of classes and traits");
|
||||
MAP.put(REDUNDANT_PROJECTION, "Projection is redundant: the corresponding type parameter of {0} has the same variance", NAME);
|
||||
MAP.put(CONFLICTING_PROJECTION, "Projection is conflicting with variance of the corresponding type parameter of {0}. Remove the projection or replace it with ''*''", NAME);
|
||||
|
||||
MAP.put(TYPE_MISMATCH_IN_FOR_LOOP, "The loop iterates over values of type {0} but the parameter is declared to be {1}", RENDER_TYPE,
|
||||
RENDER_TYPE);
|
||||
|
||||
@@ -38,6 +38,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.types.Variance.*;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -269,7 +270,7 @@ public class TypeResolver {
|
||||
arguments.add(SubstitutionUtils.makeStarProjection(parameterDescriptor));
|
||||
}
|
||||
else {
|
||||
arguments.add(new TypeProjection(Variance.OUT_VARIANCE, ErrorUtils.createErrorType("*")));
|
||||
arguments.add(new TypeProjection(OUT_VARIANCE, ErrorUtils.createErrorType("*")));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -278,16 +279,27 @@ public class TypeResolver {
|
||||
Variance kind = null;
|
||||
switch (projectionKind) {
|
||||
case IN:
|
||||
kind = Variance.IN_VARIANCE;
|
||||
kind = IN_VARIANCE;
|
||||
break;
|
||||
case OUT:
|
||||
kind = Variance.OUT_VARIANCE;
|
||||
kind = OUT_VARIANCE;
|
||||
break;
|
||||
case NONE:
|
||||
kind = Variance.INVARIANT;
|
||||
kind = INVARIANT;
|
||||
break;
|
||||
}
|
||||
assert kind != null;
|
||||
if (constructor.getParameters().size() > i) {
|
||||
TypeParameterDescriptor parameterDescriptor = constructor.getParameters().get(i);
|
||||
if (kind != INVARIANT && parameterDescriptor.getVariance() != INVARIANT) {
|
||||
if (kind == parameterDescriptor.getVariance()) {
|
||||
trace.report(REDUNDANT_PROJECTION.on(argumentElement, constructor.getDeclarationDescriptor()));
|
||||
}
|
||||
else {
|
||||
trace.report(CONFLICTING_PROJECTION.on(argumentElement, constructor.getDeclarationDescriptor()));
|
||||
}
|
||||
}
|
||||
}
|
||||
arguments.add(new TypeProjection(kind, type));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import <!UNRESOLVED_REFERENCE!>utils<!>.*
|
||||
import java.io.PrintStream
|
||||
import <!PLATFORM_CLASS_MAPPED_TO_KOTLIN!>java.lang.Comparable<!> as Com
|
||||
|
||||
val l : List<in Int> = ArrayList<Int>()
|
||||
val l : MutableList<in Int> = ArrayList<Int>()
|
||||
|
||||
fun test(<!UNUSED_PARAMETER!>l<!> : <!PLATFORM_CLASS_MAPPED_TO_KOTLIN!>java.util.List<Int><!>) {
|
||||
val <!UNUSED_VARIABLE!>x<!> : java.<!UNRESOLVED_REFERENCE!>List<!>
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
class In<in T>
|
||||
class Out<out T>
|
||||
class Inv<T>
|
||||
class X
|
||||
|
||||
fun f1(<!UNUSED_PARAMETER!>p<!>: In<<!REDUNDANT_PROJECTION!>in<!> X>) {}
|
||||
fun f2(<!UNUSED_PARAMETER!>p<!>: In<<!CONFLICTING_PROJECTION!>out<!> X>) {}
|
||||
fun f3(<!UNUSED_PARAMETER!>p<!>: In<X>) {}
|
||||
|
||||
fun f4(<!UNUSED_PARAMETER!>p<!>: Out<<!REDUNDANT_PROJECTION!>out<!> X>) {}
|
||||
fun f5(<!UNUSED_PARAMETER!>p<!>: Out<<!CONFLICTING_PROJECTION!>in<!> X>) {}
|
||||
fun f6(<!UNUSED_PARAMETER!>p<!>: Out<X>) {}
|
||||
|
||||
fun f6(<!UNUSED_PARAMETER!>p<!>: Inv<X>) {}
|
||||
fun f7(<!UNUSED_PARAMETER!>p<!>: Inv<in X>) {}
|
||||
fun f8(<!UNUSED_PARAMETER!>p<!>: Inv<out X>) {}
|
||||
|
||||
fun f9(<!UNUSED_PARAMETER!>p<!>: In<*>) {}
|
||||
fun f10(<!UNUSED_PARAMETER!>p<!>: Out<*>) {}
|
||||
fun f11(<!UNUSED_PARAMETER!>p<!>: Inv<*>) {}
|
||||
@@ -17,24 +17,19 @@ class Inv<T>() {
|
||||
|
||||
fun testInOut() {
|
||||
In<String>().f("1");
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<in String>).f("1")
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<out String>).f(<!TYPE_MISMATCH!>"1"<!>) // Wrong Arg
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<<!REDUNDANT_PROJECTION!>in<!> String>).f("1")
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<*>).f(<!TYPE_MISMATCH!>"1"<!>) // Wrong Arg
|
||||
|
||||
In<String>().f(1);
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<in String>).f(1)
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<out String>).f(1)
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<out String>).<!UNRESOLVED_REFERENCE!>f1<!>(1) // !!
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<<!REDUNDANT_PROJECTION!>in<!> String>).f(1)
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> In<*>).f(1);
|
||||
|
||||
Out<Int>().f(1)
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<out Int>).f(1)
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<in Int>).f(1)
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<<!REDUNDANT_PROJECTION!>out<!> Int>).f(1)
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<*>).f(1)
|
||||
|
||||
Out<Int>().f()
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<out Int>).f()
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<in Int>).f()
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<<!REDUNDANT_PROJECTION!>out<!> Int>).f()
|
||||
(null <!CAST_NEVER_SUCCEEDS!>as<!> Out<*>).f()
|
||||
|
||||
Inv<Int>().f(1)
|
||||
|
||||
@@ -36,8 +36,8 @@ fun test1() {
|
||||
|
||||
val i = both(1, "")
|
||||
val j = both(id(1), id(""))
|
||||
i : Comparable<out Any?>
|
||||
j : Comparable<out Any?>
|
||||
i : Comparable<*>
|
||||
j : Comparable<*>
|
||||
}
|
||||
|
||||
fun list<T>(value: T) : ArrayList<T> {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//+JDK
|
||||
package d
|
||||
|
||||
public fun <T> Collection<out T>.filterToMy(result : MutableList<in T>, filter : (T) -> Boolean) : Collection<out T> {
|
||||
public fun <T> MutableCollection<out T>.filterToMy(result : MutableList<in T>, filter : (T) -> Boolean) : MutableCollection<out T> {
|
||||
for (t in this){
|
||||
if (filter(t)){
|
||||
result.add(t)
|
||||
@@ -11,13 +11,13 @@ public fun <T> Collection<out T>.filterToMy(result : MutableList<in T>, filter :
|
||||
return this
|
||||
}
|
||||
|
||||
fun foo(result: MutableList<in String>, val collection: Collection<String>, prefix : String){
|
||||
fun foo(result: MutableList<in String>, val collection: MutableCollection<String>, prefix : String){
|
||||
collection.filterToMy(result, {it.startsWith(prefix)})
|
||||
}
|
||||
|
||||
fun test(result: MutableList<in Any>, val collection: Collection<String>, prefix : String){
|
||||
fun test(result: MutableList<in Any>, val collection: MutableCollection<String>, prefix : String){
|
||||
val c = collection.filterToMy(result, {it.startsWith(prefix)})
|
||||
c: Collection<out String>
|
||||
c: MutableCollection<out String>
|
||||
}
|
||||
|
||||
//from library
|
||||
|
||||
@@ -13,9 +13,9 @@ fun foo() : G<Point> {
|
||||
|
||||
class Out<out T>() {}
|
||||
|
||||
fun fout<T>(<!UNUSED_PARAMETER!>expression<!> : T) : Out<out T> = Out<T>()
|
||||
fun fout<T>(<!UNUSED_PARAMETER!>expression<!> : T) : Out<<!REDUNDANT_PROJECTION!>out<!> T> = Out<T>()
|
||||
|
||||
fun fooout() : Out<Point> {
|
||||
val p = Point();
|
||||
return fout<Point>(p);
|
||||
}
|
||||
}
|
||||
@@ -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: List<in String?>) where B : List<Cloneable>")
|
||||
@KotlinSignature("fun <A, B : Runnable> foo(a : A, b : List<out 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: List<in String?>) where B : List<Cloneable> {
|
||||
public open fun <erased A, erased B : Runnable> foo(p0 : A, p1 : List<out B>, p2: MutableList<in String?>) where B : List<Cloneable> {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,5 +2,5 @@ namespace test
|
||||
|
||||
public open class test.MethodWithTypeParameters : java.lang.Object {
|
||||
public final /*constructor*/ fun <init>(): test.MethodWithTypeParameters
|
||||
public open fun </*0*/ A : jet.Any?, /*1*/ B : java.lang.Runnable & jet.List<java.lang.Cloneable>>foo(/*0*/ p0: A, /*1*/ p1: jet.List<out B>, /*2*/ p2: jet.List<in jet.String?>): jet.Tuple0
|
||||
public open fun </*0*/ A : jet.Any?, /*1*/ B : java.lang.Runnable & jet.List<java.lang.Cloneable>>foo(/*0*/ p0: A, /*1*/ p1: jet.List<out B>, /*2*/ p2: jet.MutableList<in jet.String?>): jet.Tuple0
|
||||
}
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError;
|
||||
|
||||
public class WrongTypeParameterBoundStructure1 {
|
||||
@ExpectLoadError("'java.lang.Runnable?' type in method signature has 0 type arguments, while 'Runnable<Int>' in alternative signature has 1 of them")
|
||||
@KotlinSignature("fun <A, B : Runnable<Int>> foo(a : A, b : List<out B>, c: List<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) {
|
||||
@KotlinSignature("fun <A, B : Runnable<Int>> foo(a : A, b : List<out B>) where B : List<Cloneable>")
|
||||
public <A, B extends Runnable & List<Cloneable>> void foo(A a, List<? extends B> b) {
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@ package test
|
||||
import java.util.*
|
||||
|
||||
public open class WrongTypeParameterBoundStructure1 : Object() {
|
||||
public open fun <erased A, erased B : Runnable?> foo(p0 : A?, p1 : List<out B>?, p2: List<in String?>?) where B : List<Cloneable?>? {
|
||||
public open fun <erased A, erased B : Runnable?> foo(p0 : A?, p1 : List<out B>?) where B : List<Cloneable?>? {
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@ namespace test
|
||||
|
||||
public open class test.WrongTypeParameterBoundStructure1 : java.lang.Object {
|
||||
public final /*constructor*/ fun <init>(): test.WrongTypeParameterBoundStructure1
|
||||
public open fun </*0*/ A : jet.Any?, /*1*/ B : java.lang.Runnable? & jet.List<java.lang.Cloneable?>?>foo(/*0*/ p0: A?, /*1*/ p1: jet.List<out B>?, /*2*/ p2: jet.List<in jet.String?>?): jet.Tuple0
|
||||
public open fun </*0*/ A : jet.Any?, /*1*/ B : java.lang.Runnable? & jet.List<java.lang.Cloneable?>?>foo(/*0*/ p0: A?, /*1*/ p1: jet.List<out B>?): jet.Tuple0
|
||||
}
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError;
|
||||
|
||||
public class WrongTypeParameterBoundStructure2 {
|
||||
@ExpectLoadError("'jet.List<java.lang.Cloneable?>?' type in method signature has 1 type arguments, while 'List' in alternative signature has 0 of them")
|
||||
@KotlinSignature("fun <A, B : Runnable> foo(a : A, b : List<out B>, c: List<in String?>) where B : List")
|
||||
public <A, B extends Runnable & List<Cloneable>> void foo(A a, List<? extends B> b, List<? super String> list) {
|
||||
@KotlinSignature("fun <A, B : Runnable> foo(a : A, b : List<out B>) where B : List")
|
||||
public <A, B extends Runnable & List<Cloneable>> void foo(A a, List<? extends B> b) {
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@ package test
|
||||
import java.util.*
|
||||
|
||||
public open class WrongTypeParameterBoundStructure2 : Object() {
|
||||
public open fun <erased A, erased B : Runnable?> foo(p0 : A?, p1 : List<out B>?, p2: List<in String?>?) where B : List<Cloneable?>? {
|
||||
public open fun <erased A, erased B : Runnable?> foo(p0 : A?, p1 : List<out B>?) where B : List<Cloneable?>? {
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@ namespace test
|
||||
|
||||
public open class test.WrongTypeParameterBoundStructure2 : java.lang.Object {
|
||||
public final /*constructor*/ fun <init>(): test.WrongTypeParameterBoundStructure2
|
||||
public open fun </*0*/ A : jet.Any?, /*1*/ B : java.lang.Runnable? & jet.List<java.lang.Cloneable?>?>foo(/*0*/ p0: A?, /*1*/ p1: jet.List<out B>?, /*2*/ p2: jet.List<in jet.String?>?): jet.Tuple0
|
||||
public open fun </*0*/ A : jet.Any?, /*1*/ B : java.lang.Runnable? & jet.List<java.lang.Cloneable?>?>foo(/*0*/ p0: A?, /*1*/ p1: jet.List<out B>?): jet.Tuple0
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import jet.runtime.typeinfo.KotlinSignature;
|
||||
import org.jetbrains.jet.jvm.compiler.annotation.ExpectLoadError;
|
||||
|
||||
public class WrongTypeVariance {
|
||||
@ExpectLoadError("Variance mismatch, actual: in, in alternative signature: ")
|
||||
@ExpectLoadError("Variance mismatch, actual: out, in alternative signature: ")
|
||||
@KotlinSignature("fun copy(a : List<out Number>, b : List<Number>) : MutableList<Number>")
|
||||
public List<Number> copy(List<? extends Number> from, List<? super Number> to) {
|
||||
public List<Number> copy(List<? extends Number> from, List<? extends Number> to) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package test
|
||||
import java.util.*
|
||||
|
||||
public open class WrongTypeVariance : Object() {
|
||||
public open fun copy(p0 : List<out jet.Number?>?, p1 : List<in jet.Number?>?) : MutableList<jet.Number?>? {
|
||||
public open fun copy(p0 : List<out jet.Number?>?, p1 : List<out jet.Number?>?) : MutableList<jet.Number?>? {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,5 +2,5 @@ namespace test
|
||||
|
||||
public open class test.WrongTypeVariance : java.lang.Object {
|
||||
public final /*constructor*/ fun <init>(): test.WrongTypeVariance
|
||||
public open fun copy(/*0*/ p0: jet.List<out jet.Number?>?, /*1*/ p1: jet.List<in jet.Number?>?): jet.MutableList<jet.Number?>?
|
||||
public open fun copy(/*0*/ p0: jet.List<out jet.Number?>?, /*1*/ p1: jet.List<out jet.Number?>?): jet.MutableList<jet.Number?>?
|
||||
}
|
||||
|
||||
@@ -1382,6 +1382,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
doTest("compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ConflictingAndRedundantProjections.kt")
|
||||
public void testConflictingAndRedundantProjections() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/declarationChecks/ConflictingAndRedundantProjections.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("DataFlowInMultiDeclInFor.kt")
|
||||
public void testDataFlowInMultiDeclInFor() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/declarationChecks/DataFlowInMultiDeclInFor.kt");
|
||||
|
||||
@@ -5,7 +5,7 @@ import <error>utils</error>.*
|
||||
import java.io.PrintStream
|
||||
import <warning>java.lang.Comparable</warning> as Com
|
||||
|
||||
val l : List<in Int> = ArrayList<Int>()
|
||||
val l : MutableList<in Int> = ArrayList<Int>()
|
||||
|
||||
fun test(<warning>l</warning> : List<Int>) {
|
||||
val <warning>x</warning> : java.<error>List</error>
|
||||
|
||||
Reference in New Issue
Block a user