From 65794183e7b7b92bb845dcc0a64066068b8e3a77 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Sun, 9 Nov 2014 14:05:58 +0200 Subject: [PATCH] Specificity supported for dynamic types --- .../jet/lang/resolve/OverloadUtil.java | 5 +-- .../tests/dynamicTypes/overloading.kt | 26 ++++++++++++++++ .../tests/dynamicTypes/overloading.txt | 8 +++++ .../checkers/JetDiagnosticsTestGenerated.java | 6 ++++ .../jet/lang/types/TypeCapabilities.kt | 2 ++ .../jetbrains/jet/lang/types/dynamicTypes.kt | 31 +++++++++++++++++-- spec-docs/dynamic-types.md | 1 + 7 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/dynamicTypes/overloading.kt create mode 100644 compiler/testData/diagnostics/tests/dynamicTypes/overloading.txt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java index 8bf3e2fc931..b9cbc06497f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java @@ -22,6 +22,7 @@ import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypesPackage; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import java.util.List; @@ -70,8 +71,8 @@ public class OverloadUtil { for (int i = 0; i < superValueParameters.size(); ++i) { JetType superValueParameterType = OverridingUtil.getUpperBound(superValueParameters.get(i)); JetType subValueParameterType = OverridingUtil.getUpperBound(subValueParameters.get(i)); - // TODO: compare erasure - if (!JetTypeChecker.DEFAULT.equalTypes(superValueParameterType, subValueParameterType)) { + if (!JetTypeChecker.DEFAULT.equalTypes(superValueParameterType, subValueParameterType) + || TypesPackage.oneMoreSpecificThanAnother(subValueParameterType, superValueParameterType)) { return OverridingUtil.OverrideCompatibilityInfo .valueParameterTypeMismatch(superValueParameterType, subValueParameterType, INCOMPATIBLE); } diff --git a/compiler/testData/diagnostics/tests/dynamicTypes/overloading.kt b/compiler/testData/diagnostics/tests/dynamicTypes/overloading.kt new file mode 100644 index 00000000000..35f33166c31 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dynamicTypes/overloading.kt @@ -0,0 +1,26 @@ +// !CHECK_TYPE +// !DIAGNOSTICS: -UNUSED_PARAMETER + +// MODULE[js]: m1 +// FILE: k.kt + +fun dyn(d: dynamic) {} + +fun foo(d: dynamic): String = "" +fun foo(d: Int): Int = 1 + +fun nothing(d: dynamic): Int = 1 +fun nothing(d: Nothing): String = "" + +fun test(d: dynamic) { + dyn(1) + dyn("") + + foo(1).checkType { it : _ } + foo("").checkType { it : _ } + + // Checking specificity of `dynamic` vs `Nothing` + nothing(d).checkType { it : _ } + nothing("").checkType { it : _ } + [suppress("UNREACHABLE_CODE")] nothing(null!!).checkType { it : _ } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/dynamicTypes/overloading.txt b/compiler/testData/diagnostics/tests/dynamicTypes/overloading.txt new file mode 100644 index 00000000000..3c681b4dd3a --- /dev/null +++ b/compiler/testData/diagnostics/tests/dynamicTypes/overloading.txt @@ -0,0 +1,8 @@ +package + +internal fun dyn(/*0*/ d: (kotlin.Nothing..kotlin.Any?)): kotlin.Unit +internal fun foo(/*0*/ d: (kotlin.Nothing..kotlin.Any?)): kotlin.String +internal fun foo(/*0*/ d: kotlin.Int): kotlin.Int +internal fun nothing(/*0*/ d: dynamic): kotlin.Int +internal fun nothing(/*0*/ d: kotlin.Nothing): kotlin.String +internal fun test(/*0*/ d: dynamic): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 2d0f1daf642..1f284023e93 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -3722,6 +3722,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("overloading.kt") + public void testOverloading() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/overloading.kt"); + doTest(fileName); + } + @TestMetadata("unsupported.kt") public void testUnsupported() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/unsupported.kt"); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeCapabilities.kt b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeCapabilities.kt index 65d81aa9903..aef1963a5f9 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeCapabilities.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeCapabilities.kt @@ -33,6 +33,8 @@ public trait Specificity : TypeCapability { fun JetType.getSpecificityRelationTo(otherType: JetType) = this.getCapability(javaClass())?.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 + // 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 // (i.e. it is not derived from a type parameter), see isTypeVariable diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/dynamicTypes.kt b/core/descriptors/src/org/jetbrains/jet/lang/types/dynamicTypes.kt index 696fdd86589..5eb81235e2b 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/dynamicTypes.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/dynamicTypes.kt @@ -17,6 +17,7 @@ package org.jetbrains.jet.lang.types import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns +import kotlin.platform.platformStatic open class DynamicTypesSettings { open val dynamicTypesAllowed: Boolean @@ -28,10 +29,36 @@ class DynamicTypesAllowed: DynamicTypesSettings() { get() = true } +trait Dynamicity : TypeCapability + object DynamicType : DelegatingFlexibleType( KotlinBuiltIns.getInstance().getNothingType(), KotlinBuiltIns.getInstance().getNullableAnyType(), - FlexibleTypeCapabilities.NONE + DynamicTypeCapabilities ) { override fun getDelegate() = upperBound -} \ No newline at end of file +} + +fun JetType.isDynamic(): Boolean = this.getCapability(javaClass()) != null + +public object DynamicTypeCapabilities : FlexibleTypeCapabilities { + override val id: String get() = "kotlin.DynamicType" + + override fun getCapability(capabilityClass: Class, jetType: JetType, flexibility: Flexibility): T? { + if (capabilityClass.isAssignableFrom(javaClass())) + [suppress("UNCHECKED_CAST")] + return Impl(jetType, flexibility) as T + else return null + } + + + private class Impl(val type: JetType, val flexibility: Flexibility) : Dynamicity, Specificity { + + private val lowerBound: JetType get() = flexibility.lowerBound + private val upperBound: JetType get() = flexibility.upperBound + + override fun getSpecificityRelationTo(otherType: JetType): Specificity.Relation { + return if (!otherType.isDynamic()) Specificity.Relation.LESS_SPECIFIC else Specificity.Relation.DONT_KNOW + } + } +} diff --git a/spec-docs/dynamic-types.md b/spec-docs/dynamic-types.md index 7e5514cfd8b..8d9777e6a7d 100644 --- a/spec-docs/dynamic-types.md +++ b/spec-docs/dynamic-types.md @@ -32,6 +32,7 @@ fun jsFun(p: dynamic): dynamic - ??? `glb(T, dynamic) = T` - `dynamic` can't be substituted for reified parameters of function/constructor calls (this means that it's not possible to create an array of `dynamic`) - `dynamic` can't be used as a supertype or upper bound for a tpe parameter +- `dynamic` is less specific than any other type ## Syntax