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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user