Fixed 'subtype' for captured type

This commit is contained in:
Svetlana Isakova
2014-12-10 13:56:52 +03:00
parent 0149e8048c
commit 14a53a105b
4 changed files with 74 additions and 13 deletions
@@ -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
@@ -31,9 +31,11 @@ public trait Specificity : TypeCapability {
public fun getSpecificityRelationTo(otherType: JetType): Relation
}
fun JetType.getSpecificityRelationTo(otherType: JetType) = this.getCapability(javaClass<Specificity>())?.getSpecificityRelationTo(otherType) ?: Specificity.Relation.DONT_KNOW
fun JetType.getSpecificityRelationTo(otherType: JetType) =
this.getCapability(javaClass<Specificity>())?.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<CustomTypeVariable>())?.let {
if (it.isTypeVariable) it else null
}
}
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<SubtypingRepresentatives>())?.subTypeRepresentative ?: this
public fun JetType.getSupertypeRepresentative(): JetType =
this.getCapability(javaClass<SubtypingRepresentatives>())?.superTypeRepresentative ?: this
public fun sameTypeConstructors(first: JetType, second: JetType): Boolean {
val typeRangeCapability = javaClass<SubtypingRepresentatives>()
return first.getCapability(typeRangeCapability)?.sameTypeConstructor(second) ?: false
|| second.getCapability(typeRangeCapability)?.sameTypeConstructor(first) ?: false
}
@@ -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;
}
@@ -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<Foo, Foo?>, 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<Flexibility>()) != null