From d5932e1a3370e40fdf399e7cb89cb9b08a30f9d7 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 10 Nov 2014 00:12:55 +0200 Subject: [PATCH] Nullability of dynamic types --- .../org/jetbrains/jet/lang/resolve/TypeResolver.kt | 5 +++-- .../diagnostics/tests/dynamicTypes/nullable.kt | 11 +++++++++++ .../diagnostics/tests/dynamicTypes/nullable.txt | 3 +++ .../jet/checkers/JetDiagnosticsTestGenerated.java | 6 ++++++ .../calls/inference/ConstraintSystemImpl.java | 2 +- .../org/jetbrains/jet/lang/types/dynamicTypes.kt | 14 +++++++++----- 6 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/dynamicTypes/nullable.kt create mode 100644 compiler/testData/diagnostics/tests/dynamicTypes/nullable.txt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.kt index 00f3ad749e4..bff32bab41b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.kt @@ -199,8 +199,9 @@ public class TypeResolver( } override fun visitNullableType(nullableType: JetNullableType) { - val baseType = resolveTypeElement(c, annotations, nullableType.getInnerType()) - if (baseType.isNullable()) { + val innerType = nullableType.getInnerType() + val baseType = resolveTypeElement(c, annotations, innerType) + if (baseType.isNullable() || innerType is JetNullableType || innerType is JetDynamicType) { c.trace.report(REDUNDANT_NULLABLE.on(nullableType)) } else if (!baseType.isBare() && TypeUtils.hasNullableSuperType(baseType.getActualType())) { diff --git a/compiler/testData/diagnostics/tests/dynamicTypes/nullable.kt b/compiler/testData/diagnostics/tests/dynamicTypes/nullable.kt new file mode 100644 index 00000000000..c4f12537e2b --- /dev/null +++ b/compiler/testData/diagnostics/tests/dynamicTypes/nullable.kt @@ -0,0 +1,11 @@ +// !CHECK_TYPE + +// MODULE[js]: m1 +// FILE: k.kt + +fun foo(dn: dynamic?, d: dynamic, dnn: dynamic??) { + dn.checkType { it : _} + dn.checkType { it : _?>} + d.checkType { it : _} + d.checkType { it : _?>} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/dynamicTypes/nullable.txt b/compiler/testData/diagnostics/tests/dynamicTypes/nullable.txt new file mode 100644 index 00000000000..70883988245 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dynamicTypes/nullable.txt @@ -0,0 +1,3 @@ +package + +internal fun foo(/*0*/ dn: dynamic, /*1*/ 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 1f284023e93..81f94e5bdd4 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("nullable.kt") + public void testNullable() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/nullable.kt"); + doTest(fileName); + } + @TestMetadata("overloading.kt") public void testOverloading() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/dynamicTypes/overloading.kt"); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java index 3286ff61247..f6859d4ed98 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java @@ -389,7 +389,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { // can be equal for the recursive invocations: // fun foo(i: Int) : T { ... return foo(i); } => T <: T - if (JetTypeChecker.DEFAULT.equalTypes(subType, superType)) return; + if (isMyTypeVariable(subType) && isMyTypeVariable(superType) && JetTypeChecker.DEFAULT.equalTypes(subType, superType)) return; assert !isMyTypeVariable(subType) || !isMyTypeVariable(superType) : "The constraint shouldn't contain different type variables on both sides: " + subType + " <: " + superType; 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 5eb81235e2b..07639b419b7 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/dynamicTypes.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/dynamicTypes.kt @@ -37,6 +37,8 @@ object DynamicType : DelegatingFlexibleType( DynamicTypeCapabilities ) { override fun getDelegate() = upperBound + + override fun isNullable() = false } fun JetType.isDynamic(): Boolean = this.getCapability(javaClass()) != null @@ -47,18 +49,20 @@ public object DynamicTypeCapabilities : FlexibleTypeCapabilities { override fun getCapability(capabilityClass: Class, jetType: JetType, flexibility: Flexibility): T? { if (capabilityClass.isAssignableFrom(javaClass())) [suppress("UNCHECKED_CAST")] - return Impl(jetType, flexibility) as T + return Impl 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 + private object Impl : Dynamicity, Specificity, NullAwareness { override fun getSpecificityRelationTo(otherType: JetType): Specificity.Relation { return if (!otherType.isDynamic()) Specificity.Relation.LESS_SPECIFIC else Specificity.Relation.DONT_KNOW } + + override fun makeNullableAsSpecified(nullable: Boolean): JetType { + // Nullability has no effect on dynamics + return DynamicType + } } }