Delegation and nullability turned into capabilities

Otherwise they did not sustain substitutions
This commit is contained in:
Andrey Breslav
2014-11-13 02:55:12 +02:00
parent 845f30975d
commit d2e6767c07
7 changed files with 43 additions and 13 deletions
@@ -31,15 +31,13 @@ class DynamicTypesAllowed: DynamicTypesSettings() {
trait Dynamicity : TypeCapability
// Object is created only for convenience here. Dynamic types may occur in the form of DelegatingFlexibleTypes,
// which are produced by substitutions
object DynamicType : DelegatingFlexibleType(
KotlinBuiltIns.getInstance().getNothingType(),
KotlinBuiltIns.getInstance().getNullableAnyType(),
DynamicTypeCapabilities
) {
override fun getDelegate() = upperBound
override fun isNullable() = false
}
)
fun JetType.isDynamic(): Boolean = this.getCapability(javaClass<Dynamicity>()) != null
@@ -49,12 +47,13 @@ public object DynamicTypeCapabilities : FlexibleTypeCapabilities {
override fun <T : TypeCapability> getCapability(capabilityClass: Class<T>, jetType: JetType, flexibility: Flexibility): T? {
if (capabilityClass.isAssignableFrom(javaClass<Impl>()))
[suppress("UNCHECKED_CAST")]
return Impl as T
return Impl(flexibility) as T
else return null
}
private object Impl : Dynamicity, Specificity, NullAwareness {
private class Impl(flexibility: Flexibility) : Dynamicity, Specificity, NullAwareness, FlexibleTypeDelegation {
override val delegateType: JetType = flexibility.upperBound
override fun getSpecificityRelationTo(otherType: JetType): Specificity.Relation {
return if (!otherType.isDynamic()) Specificity.Relation.LESS_SPECIFIC else Specificity.Relation.DONT_KNOW
@@ -64,5 +63,7 @@ public object DynamicTypeCapabilities : FlexibleTypeCapabilities {
// Nullability has no effect on dynamics
return DynamicType
}
override fun computeIsNullable() = false
}
}
@@ -90,6 +90,7 @@ public fun JetType.upperIfFlexible(): JetType = if (this.isFlexible()) this.flex
public trait NullAwareness : TypeCapability {
public fun makeNullableAsSpecified(nullable: Boolean): JetType
public fun computeIsNullable(): Boolean
}
public trait Approximation : TypeCapability {
@@ -124,12 +125,15 @@ public fun JetType.getApproximationTo(
extras: Approximation.DataFlowExtras = Approximation.DataFlowExtras.EMPTY
): Approximation.Info? = this.getCapability(javaClass<Approximation>())?.approximateToExpectedType(expectedType, extras)
trait FlexibleTypeDelegation : TypeCapability {
public val delegateType: JetType
}
public open class DelegatingFlexibleType protected (
override val lowerBound: JetType,
override val upperBound: JetType,
override val extraCapabilities: FlexibleTypeCapabilities
) : DelegatingType(), NullAwareness, Flexibility, Approximation {
) : DelegatingType(), NullAwareness, Flexibility, FlexibleTypeDelegation, Approximation {
class object {
platformStatic fun create(lowerBound: JetType, upperBound: JetType, extraCapabilities: FlexibleTypeCapabilities): JetType {
if (lowerBound == upperBound) return lowerBound
@@ -157,6 +161,10 @@ public open class DelegatingFlexibleType protected (
extraCapabilities)
}
override fun computeIsNullable() = delegateType.isNullable()
override fun isNullable(): Boolean = getCapability(javaClass<NullAwareness>())!!.computeIsNullable()
override fun approximateToExpectedType(expectedType: JetType, dataFlowExtras: Approximation.DataFlowExtras): Approximation.Info? {
// val foo: Any? = foo() : Foo!
if (JetTypeChecker.DEFAULT.isSubtypeOf(upperBound, expectedType)) return null
@@ -171,7 +179,9 @@ public open class DelegatingFlexibleType protected (
return Approximation.Info(this, expectedType, dataFlowExtras.presentableText)
}
override fun getDelegate() = lowerBound
override val delegateType: JetType = lowerBound
override fun getDelegate() = getCapability(javaClass<FlexibleTypeDelegation>())!!.delegateType
override fun toString() = "('$lowerBound'..'$upperBound')"
}