Lower bound must be a subtype of the upper bound.

The change in CommonSupertypes:

 We used to say that commonSupertype(Inv<A>, Inv<B>) = Inv<in Intersect(A, B)). This is counter-intuitive, should be Inv<out commonSupertype(A, B)>
This commit is contained in:
Andrey Breslav
2014-08-25 17:51:02 +04:00
parent e232697da1
commit 6cb1d2e3f7
4 changed files with 16 additions and 8 deletions
+5 -1
View File
@@ -36,4 +36,8 @@ open class ArrayList<E>() : Any, AbstractList<E?>, List<E?>
fun f() : Unit {} fun f() : Unit {}
fun f(a : Int) : Int {a} fun f(a : Int) : Int {a}
fun f(a : Float, b : Int) : Float {a} fun f(a : Float, b : Int) : Float {a}
fun f<T>(a : Float) : T {a} fun f<T>(a : Float) : T {a}
trait Parent
trait A: Parent
trait B: Parent
@@ -200,6 +200,8 @@ public class JetTypeCheckerTest extends JetLiteFixture {
assertCommonSupertype("Base_T<in Int>", "Derived_T<Int>", "Base_T<in Int>"); assertCommonSupertype("Base_T<in Int>", "Derived_T<Int>", "Base_T<in Int>");
assertCommonSupertype("Base_T<in Int>", "Derived_T<in Int>", "Base_T<Int>"); assertCommonSupertype("Base_T<in Int>", "Derived_T<in Int>", "Base_T<Int>");
assertCommonSupertype("Base_T<*>", "Base_T<Int>", "Base_T<*>"); assertCommonSupertype("Base_T<*>", "Base_T<Int>", "Base_T<*>");
assertCommonSupertype("Base_T<out Parent>", "Base_T<A>", "Base_T<B>");
} }
public void testIntersect() throws Exception { public void testIntersect() throws Exception {
@@ -237,21 +237,18 @@ public class CommonSupertypes {
} }
} }
if (outs != null) {
Variance projectionKind = variance == OUT_VARIANCE ? Variance.INVARIANT : OUT_VARIANCE;
return new TypeProjectionImpl(projectionKind, commonSupertype(outs));
}
if (ins != null) { if (ins != null) {
JetType intersection = TypeUtils.intersect(JetTypeChecker.DEFAULT, ins); JetType intersection = TypeUtils.intersect(JetTypeChecker.DEFAULT, ins);
if (intersection == null) { if (intersection == null) {
if (outs != null) {
return new TypeProjectionImpl(OUT_VARIANCE, commonSupertype(outs));
}
return new TypeProjectionImpl(OUT_VARIANCE, commonSupertype(parameterDescriptor.getUpperBounds())); return new TypeProjectionImpl(OUT_VARIANCE, commonSupertype(parameterDescriptor.getUpperBounds()));
} }
Variance projectionKind = variance == IN_VARIANCE ? Variance.INVARIANT : IN_VARIANCE; Variance projectionKind = variance == IN_VARIANCE ? Variance.INVARIANT : IN_VARIANCE;
return new TypeProjectionImpl(projectionKind, intersection); return new TypeProjectionImpl(projectionKind, intersection);
} }
else if (outs != null) {
Variance projectionKind = variance == OUT_VARIANCE ? Variance.INVARIANT : OUT_VARIANCE;
return new TypeProjectionImpl(projectionKind, commonSupertype(outs));
}
else { else {
Variance projectionKind = variance == OUT_VARIANCE ? Variance.INVARIANT : OUT_VARIANCE; Variance projectionKind = variance == OUT_VARIANCE ? Variance.INVARIANT : OUT_VARIANCE;
return new TypeProjectionImpl(projectionKind, commonSupertype(parameterDescriptor.getUpperBounds())); return new TypeProjectionImpl(projectionKind, commonSupertype(parameterDescriptor.getUpperBounds()));
@@ -16,6 +16,8 @@
package org.jetbrains.jet.lang.types package org.jetbrains.jet.lang.types
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
public trait FlexibleType : JetType { public trait FlexibleType : JetType {
public val lowerBound: JetType public val lowerBound: JetType
public val upperBound: JetType public val upperBound: JetType
@@ -33,6 +35,9 @@ public open class DelegatingFlexibleType(
{ {
assert (!lowerBound.isFlexible()) { "Lower bound of a flexible type can not be flexible: $lowerBound" } assert (!lowerBound.isFlexible()) { "Lower bound of a flexible type can not be flexible: $lowerBound" }
assert (!upperBound.isFlexible()) { "Upper bound of a flexible type can not be flexible: $upperBound" } assert (!upperBound.isFlexible()) { "Upper bound of a flexible type can not be flexible: $upperBound" }
assert (JetTypeChecker.DEFAULT.isSubtypeOf(lowerBound, upperBound)) {
"Lower bound $lowerBound of a flexible type must be a subtype of the upper bound $upperBound"
}
} }
override fun getDelegate() = lowerBound override fun getDelegate() = lowerBound