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.TypeParameterDescriptor
import org.jetbrains.jet.lang.descriptors.annotations.Annotations 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.Variance.*
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns 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.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 class CapturedTypeConstructor(
public val typeProjection: TypeProjection public val typeProjection: TypeProjection
@@ -56,10 +61,30 @@ public class CapturedTypeConstructor(
override fun toString() = "Captured($typeProjection)" override fun toString() = "Captured($typeProjection)"
} }
public fun createCapturedType(typeProjection: TypeProjection): JetType { public class CapturedType(
val scope = ErrorUtils.createErrorScope("No member resolution should be done on captured type, " + private val typeProjection: TypeProjection
"it used only during constraint system resolution", true) ): DelegatingType(), SubtypingRepresentatives {
return JetTypeImpl(Annotations.EMPTY, CapturedTypeConstructor(typeProjection), false, listOf(), scope)
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 public fun JetType.isCaptured(): Boolean = getConstructor() is CapturedTypeConstructor
@@ -31,9 +31,11 @@ public trait Specificity : TypeCapability {
public fun getSpecificityRelationTo(otherType: JetType): Relation 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, // 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 // 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? = public fun JetType.getCustomTypeVariable(): CustomTypeVariable? =
this.getCapability(javaClass<CustomTypeVariable>())?.let { this.getCapability(javaClass<CustomTypeVariable>())?.let {
if (it.isTypeVariable) it else null 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) { public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) {
if (TypesPackage.isFlexible(subtype)) { if (TypesPackage.sameTypeConstructors(subtype, supertype)) {
return isSubtypeOf(TypesPackage.flexibility(subtype).getLowerBound(), supertype); return !subtype.isMarkedNullable() || supertype.isMarkedNullable();
} }
if (TypesPackage.isFlexible(supertype)) { JetType subtypeRepresentative = TypesPackage.getSubtypeRepresentative(subtype);
return isSubtypeOf(subtype, TypesPackage.flexibility(supertype).getUpperBound()); 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()) { if (subtype.isError() || supertype.isError()) {
return true; return true;
} }
@@ -34,7 +34,7 @@ public trait FlexibleTypeCapabilities {
} }
} }
public trait Flexibility : TypeCapability { public trait Flexibility : TypeCapability, SubtypingRepresentatives {
class object { 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, // 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?). // it creates a flexible type, e.g. (Foo..Foo?).
@@ -48,6 +48,14 @@ public trait Flexibility : TypeCapability {
public val upperBound: JetType public val upperBound: JetType
public val extraCapabilities: FlexibleTypeCapabilities 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 public fun JetType.isFlexible(): Boolean = this.getCapability(javaClass<Flexibility>()) != null