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
@@ -11,8 +11,8 @@ fun test(d: dynamic) {
val v3 = d.foo(1, "")
v3.isDynamic() // to check that anything is resolvable
// val v4 = d.foo<String>()
// v4.isDynamic() // to check that anything is resolvable
val v4 = d.foo<String>()
v4.isDynamic() // to check that anything is resolvable
val v5 = d.foo
v5.isDynamic() // to check that anything is resolvable
@@ -0,0 +1,10 @@
// MODULE[js]: m1
// FILE: k.kt
fun test(d: dynamic) {
val v1 = d?.foo()
v1.isDynamic() // to check that anything is resolvable
val v2 = d!!.foo(1)
v2.isDynamic() // to check that anything is resolvable
}
@@ -0,0 +1,3 @@
package
internal fun test(/*0*/ d: dynamic): kotlin.Unit
@@ -11,8 +11,8 @@ fun (dynamic).test() {
val v3 = foo(1, "")
v3.isDynamic() // to check that anything is resolvable
// val v4 = foo<String>()
// v4.isDynamic() // to check that anything is resolvable
val v4 = foo<String>()
v4.isDynamic() // to check that anything is resolvable
val v5 = foo
v5.isDynamic() // to check that anything is resolvable
@@ -3728,6 +3728,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("dynamicSafeCalls.kt")
public void testDynamicSafeCalls() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/dynamicSafeCalls.kt");
doTest(fileName);
}
@TestMetadata("implicitDynamicReceiver.kt")
public void testImplicitDynamicReceiver() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/implicitDynamicReceiver.kt");
@@ -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')"
}