Delegation and nullability turned into capabilities
Otherwise they did not sustain substitutions
This commit is contained in:
@@ -11,8 +11,8 @@ fun test(d: dynamic) {
|
|||||||
val v3 = d.foo(1, "")
|
val v3 = d.foo(1, "")
|
||||||
v3.isDynamic() // to check that anything is resolvable
|
v3.isDynamic() // to check that anything is resolvable
|
||||||
|
|
||||||
// val v4 = d.foo<String>()
|
val v4 = d.foo<String>()
|
||||||
// v4.isDynamic() // to check that anything is resolvable
|
v4.isDynamic() // to check that anything is resolvable
|
||||||
|
|
||||||
val v5 = d.foo
|
val v5 = d.foo
|
||||||
v5.isDynamic() // to check that anything is resolvable
|
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, "")
|
val v3 = foo(1, "")
|
||||||
v3.isDynamic() // to check that anything is resolvable
|
v3.isDynamic() // to check that anything is resolvable
|
||||||
|
|
||||||
// val v4 = foo<String>()
|
val v4 = foo<String>()
|
||||||
// v4.isDynamic() // to check that anything is resolvable
|
v4.isDynamic() // to check that anything is resolvable
|
||||||
|
|
||||||
val v5 = foo
|
val v5 = foo
|
||||||
v5.isDynamic() // to check that anything is resolvable
|
v5.isDynamic() // to check that anything is resolvable
|
||||||
|
|||||||
@@ -3728,6 +3728,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("implicitDynamicReceiver.kt")
|
||||||
public void testImplicitDynamicReceiver() throws Exception {
|
public void testImplicitDynamicReceiver() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/implicitDynamicReceiver.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/implicitDynamicReceiver.kt");
|
||||||
|
|||||||
@@ -31,15 +31,13 @@ class DynamicTypesAllowed: DynamicTypesSettings() {
|
|||||||
|
|
||||||
trait Dynamicity : TypeCapability
|
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(
|
object DynamicType : DelegatingFlexibleType(
|
||||||
KotlinBuiltIns.getInstance().getNothingType(),
|
KotlinBuiltIns.getInstance().getNothingType(),
|
||||||
KotlinBuiltIns.getInstance().getNullableAnyType(),
|
KotlinBuiltIns.getInstance().getNullableAnyType(),
|
||||||
DynamicTypeCapabilities
|
DynamicTypeCapabilities
|
||||||
) {
|
)
|
||||||
override fun getDelegate() = upperBound
|
|
||||||
|
|
||||||
override fun isNullable() = false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun JetType.isDynamic(): Boolean = this.getCapability(javaClass<Dynamicity>()) != null
|
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? {
|
override fun <T : TypeCapability> getCapability(capabilityClass: Class<T>, jetType: JetType, flexibility: Flexibility): T? {
|
||||||
if (capabilityClass.isAssignableFrom(javaClass<Impl>()))
|
if (capabilityClass.isAssignableFrom(javaClass<Impl>()))
|
||||||
[suppress("UNCHECKED_CAST")]
|
[suppress("UNCHECKED_CAST")]
|
||||||
return Impl as T
|
return Impl(flexibility) as T
|
||||||
else return null
|
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 {
|
override fun getSpecificityRelationTo(otherType: JetType): Specificity.Relation {
|
||||||
return if (!otherType.isDynamic()) Specificity.Relation.LESS_SPECIFIC else Specificity.Relation.DONT_KNOW
|
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
|
// Nullability has no effect on dynamics
|
||||||
return DynamicType
|
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 trait NullAwareness : TypeCapability {
|
||||||
public fun makeNullableAsSpecified(nullable: Boolean): JetType
|
public fun makeNullableAsSpecified(nullable: Boolean): JetType
|
||||||
|
public fun computeIsNullable(): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
public trait Approximation : TypeCapability {
|
public trait Approximation : TypeCapability {
|
||||||
@@ -124,12 +125,15 @@ public fun JetType.getApproximationTo(
|
|||||||
extras: Approximation.DataFlowExtras = Approximation.DataFlowExtras.EMPTY
|
extras: Approximation.DataFlowExtras = Approximation.DataFlowExtras.EMPTY
|
||||||
): Approximation.Info? = this.getCapability(javaClass<Approximation>())?.approximateToExpectedType(expectedType, extras)
|
): Approximation.Info? = this.getCapability(javaClass<Approximation>())?.approximateToExpectedType(expectedType, extras)
|
||||||
|
|
||||||
|
trait FlexibleTypeDelegation : TypeCapability {
|
||||||
|
public val delegateType: JetType
|
||||||
|
}
|
||||||
|
|
||||||
public open class DelegatingFlexibleType protected (
|
public open class DelegatingFlexibleType protected (
|
||||||
override val lowerBound: JetType,
|
override val lowerBound: JetType,
|
||||||
override val upperBound: JetType,
|
override val upperBound: JetType,
|
||||||
override val extraCapabilities: FlexibleTypeCapabilities
|
override val extraCapabilities: FlexibleTypeCapabilities
|
||||||
) : DelegatingType(), NullAwareness, Flexibility, Approximation {
|
) : DelegatingType(), NullAwareness, Flexibility, FlexibleTypeDelegation, Approximation {
|
||||||
class object {
|
class object {
|
||||||
platformStatic fun create(lowerBound: JetType, upperBound: JetType, extraCapabilities: FlexibleTypeCapabilities): JetType {
|
platformStatic fun create(lowerBound: JetType, upperBound: JetType, extraCapabilities: FlexibleTypeCapabilities): JetType {
|
||||||
if (lowerBound == upperBound) return lowerBound
|
if (lowerBound == upperBound) return lowerBound
|
||||||
@@ -157,6 +161,10 @@ public open class DelegatingFlexibleType protected (
|
|||||||
extraCapabilities)
|
extraCapabilities)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun computeIsNullable() = delegateType.isNullable()
|
||||||
|
|
||||||
|
override fun isNullable(): Boolean = getCapability(javaClass<NullAwareness>())!!.computeIsNullable()
|
||||||
|
|
||||||
override fun approximateToExpectedType(expectedType: JetType, dataFlowExtras: Approximation.DataFlowExtras): Approximation.Info? {
|
override fun approximateToExpectedType(expectedType: JetType, dataFlowExtras: Approximation.DataFlowExtras): Approximation.Info? {
|
||||||
// val foo: Any? = foo() : Foo!
|
// val foo: Any? = foo() : Foo!
|
||||||
if (JetTypeChecker.DEFAULT.isSubtypeOf(upperBound, expectedType)) return null
|
if (JetTypeChecker.DEFAULT.isSubtypeOf(upperBound, expectedType)) return null
|
||||||
@@ -171,7 +179,9 @@ public open class DelegatingFlexibleType protected (
|
|||||||
return Approximation.Info(this, expectedType, dataFlowExtras.presentableText)
|
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')"
|
override fun toString() = "('$lowerBound'..'$upperBound')"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user