diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/CapturedTypeConstructor.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/CapturedTypeConstructor.kt index 660fbddba60..eeef9741285 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/CapturedTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/CapturedTypeConstructor.kt @@ -22,9 +22,14 @@ import org.jetbrains.jet.lang.types.TypeConstructor import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor import org.jetbrains.jet.lang.descriptors.annotations.Annotations import org.jetbrains.jet.lang.types.Variance +import org.jetbrains.jet.lang.types.Variance.* import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns -import org.jetbrains.jet.lang.types.JetTypeImpl import org.jetbrains.jet.lang.types.ErrorUtils +import org.jetbrains.jet.lang.types.SubtypingRepresentatives +import org.jetbrains.jet.lang.types.AbstractJetType +import org.jetbrains.jet.lang.types.DelegatingType +import org.jetbrains.jet.lang.types.JetTypeImpl +import org.jetbrains.jet.lang.types.TypeUtils public class CapturedTypeConstructor( public val typeProjection: TypeProjection @@ -56,10 +61,30 @@ public class CapturedTypeConstructor( override fun toString() = "Captured($typeProjection)" } -public fun createCapturedType(typeProjection: TypeProjection): JetType { - val scope = ErrorUtils.createErrorScope("No member resolution should be done on captured type, " + - "it used only during constraint system resolution", true) - return JetTypeImpl(Annotations.EMPTY, CapturedTypeConstructor(typeProjection), false, listOf(), scope) +public class CapturedType( + private val typeProjection: TypeProjection +): DelegatingType(), SubtypingRepresentatives { + + private val delegateType = run { + val scope = ErrorUtils.createErrorScope( + "No member resolution should be done on captured type, it used only during constraint system resolution", true) + JetTypeImpl(Annotations.EMPTY, CapturedTypeConstructor(typeProjection), false, listOf(), scope) + } + + override fun getDelegate(): JetType = delegateType + + override val subTypeRepresentative: JetType + get() = representative(OUT_VARIANCE, KotlinBuiltIns.getInstance().getNullableAnyType()) + + override val superTypeRepresentative: JetType + get() = representative(IN_VARIANCE, KotlinBuiltIns.getInstance().getNothingType()) + + private fun representative(variance: Variance, default: JetType) = + if (typeProjection.getProjectionKind() == variance) typeProjection.getType() else default + + override fun sameTypeConstructor(type: JetType) = delegateType.getConstructor() === type.getConstructor() } +public fun createCapturedType(typeProjection: TypeProjection): JetType = CapturedType(typeProjection) + public fun JetType.isCaptured(): Boolean = getConstructor() is CapturedTypeConstructor \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeCapabilities.kt b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeCapabilities.kt index aef1963a5f9..2fd069483ff 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeCapabilities.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeCapabilities.kt @@ -31,9 +31,11 @@ public trait Specificity : TypeCapability { public fun getSpecificityRelationTo(otherType: JetType): Relation } -fun JetType.getSpecificityRelationTo(otherType: JetType) = this.getCapability(javaClass())?.getSpecificityRelationTo(otherType) ?: Specificity.Relation.DONT_KNOW +fun JetType.getSpecificityRelationTo(otherType: JetType) = + this.getCapability(javaClass())?.getSpecificityRelationTo(otherType) ?: Specificity.Relation.DONT_KNOW -fun oneMoreSpecificThanAnother(a: JetType, b: JetType) = a.getSpecificityRelationTo(b) != Specificity.Relation.DONT_KNOW || b.getSpecificityRelationTo(a) != Specificity.Relation.DONT_KNOW +fun oneMoreSpecificThanAnother(a: JetType, b: JetType) = + a.getSpecificityRelationTo(b) != Specificity.Relation.DONT_KNOW || b.getSpecificityRelationTo(a) != Specificity.Relation.DONT_KNOW // To facilitate laziness, any JetType implementation may inherit from this trait, // even if it turns out that the type an instance represents is not actually a type variable @@ -52,4 +54,23 @@ public fun JetType.isCustomTypeVariable(): Boolean = this.getCapability(javaClas public fun JetType.getCustomTypeVariable(): CustomTypeVariable? = this.getCapability(javaClass())?.let { if (it.isTypeVariable) it else null - } \ No newline at end of file + } + +public trait SubtypingRepresentatives : TypeCapability { + public val subTypeRepresentative: JetType + public val superTypeRepresentative: JetType + + public fun sameTypeConstructor(type: JetType): Boolean +} + +public fun JetType.getSubtypeRepresentative(): JetType = + this.getCapability(javaClass())?.subTypeRepresentative ?: this + +public fun JetType.getSupertypeRepresentative(): JetType = + this.getCapability(javaClass())?.superTypeRepresentative ?: this + +public fun sameTypeConstructors(first: JetType, second: JetType): Boolean { + val typeRangeCapability = javaClass() + return first.getCapability(typeRangeCapability)?.sameTypeConstructor(second) ?: false + || second.getCapability(typeRangeCapability)?.sameTypeConstructor(first) ?: false +} diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java index 1f4903e3867..b46c1e79ad6 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java @@ -183,12 +183,19 @@ public class TypeCheckingProcedure { } public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) { - if (TypesPackage.isFlexible(subtype)) { - return isSubtypeOf(TypesPackage.flexibility(subtype).getLowerBound(), supertype); + if (TypesPackage.sameTypeConstructors(subtype, supertype)) { + return !subtype.isMarkedNullable() || supertype.isMarkedNullable(); } - if (TypesPackage.isFlexible(supertype)) { - return isSubtypeOf(subtype, TypesPackage.flexibility(supertype).getUpperBound()); + JetType subtypeRepresentative = TypesPackage.getSubtypeRepresentative(subtype); + JetType supertypeRepresentative = TypesPackage.getSupertypeRepresentative(supertype); + if (subtypeRepresentative != subtype || supertypeRepresentative != supertype) { + // recursive invocation for possible chain of representatives + return isSubtypeOf(subtypeRepresentative, supertypeRepresentative); } + return isSubtypeOfForRepresentatives(subtype, supertype); + } + + private boolean isSubtypeOfForRepresentatives(JetType subtype, JetType supertype) { if (subtype.isError() || supertype.isError()) { return true; } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt b/core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt index 28af1b75766..5921328bcb8 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/flexibleTypes.kt @@ -34,7 +34,7 @@ public trait FlexibleTypeCapabilities { } } -public trait Flexibility : TypeCapability { +public trait Flexibility : TypeCapability, SubtypingRepresentatives { class object { // This is a "magic" classifier: when type resolver sees it in the code, e.g. ft, instead of creating a normal type, // it creates a flexible type, e.g. (Foo..Foo?). @@ -48,6 +48,14 @@ public trait Flexibility : TypeCapability { public val upperBound: JetType public val extraCapabilities: FlexibleTypeCapabilities + + override val subTypeRepresentative: JetType + get() = lowerBound + + override val superTypeRepresentative: JetType + get() = upperBound + + override fun sameTypeConstructor(type: JetType) = false } public fun JetType.isFlexible(): Boolean = this.getCapability(javaClass()) != null