From 1a34dffb1f9df3ff2b34178953741a6605836930 Mon Sep 17 00:00:00 2001 From: svtk Date: Tue, 19 Nov 2013 23:03:52 +0400 Subject: [PATCH] Fixed inference in a simple case. Try number lower bounds before upper bounds when computing a value. --- .../tryNumberLowerBoundsBeforeUpperBounds.kt | 6 +++ .../numbers/numbersInSimpleConstraints.kt | 48 +++++++++++-------- .../checkers/JetDiagnosticsTestGenerated.java | 5 ++ .../calls/inference/TypeBoundsImpl.java | 20 ++++---- 4 files changed, 50 insertions(+), 29 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/tryNumberLowerBoundsBeforeUpperBounds.kt diff --git a/compiler/testData/diagnostics/tests/inference/tryNumberLowerBoundsBeforeUpperBounds.kt b/compiler/testData/diagnostics/tests/inference/tryNumberLowerBoundsBeforeUpperBounds.kt new file mode 100644 index 00000000000..37cb33c319e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/tryNumberLowerBoundsBeforeUpperBounds.kt @@ -0,0 +1,6 @@ +public inline fun iterate(initialValue: T, nextFunction: (T) -> T?): Iterator = + throw Exception("$initialValue $nextFunction") + +fun foo() { + iterate(3) { n -> if (n > 0) n - 1 else null } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/numbers/numbersInSimpleConstraints.kt b/compiler/testData/diagnostics/tests/numbers/numbersInSimpleConstraints.kt index f492aad3524..5f5f9585445 100644 --- a/compiler/testData/diagnostics/tests/numbers/numbersInSimpleConstraints.kt +++ b/compiler/testData/diagnostics/tests/numbers/numbersInSimpleConstraints.kt @@ -1,5 +1,7 @@ package a +class TypeOf(t: T) + fun id(t: T): T = t fun either(t1: T, t2: T): T = t1 @@ -9,62 +11,68 @@ fun other(s: String) {} fun otherGeneric(l: List) {} fun test() { - val a: Byte = id(1) + val a: Byte = id(1) - val b: Byte = id(300) + val b: Byte = id(300) - val c: Int = id(9223372036854775807) + val c: Int = id(9223372036854775807) val d = id(22) d: Int val e = id(9223372036854775807) - e: Int - e: Long + TypeOf(e): TypeOf - val f: Byte = either(1, 2) + val f: Byte = either(1, 2) - val g: Byte = either(1, 300) + val g: Byte = either(1, 300) other(11) otherGeneric(1) val r = either(1, "") - r: Int - r: String - r: Any + TypeOf(r): TypeOf + + use(a, b, c, d, e, f, g, r) } +fun use(vararg a: Any?) = a + trait Inv -fun exactBound(t: T, l: Inv) {} +fun exactBound(t: T, l: Inv): T = throw Exception("$t $l") -fun testExactBound(invS: Inv, invI: Inv) { +fun testExactBound(invS: Inv, invI: Inv, invB: Inv) { exactBound(1, invS) exactBound(1, invI) + + val b = exactBound(1, invB) + TypeOf(b): TypeOf } trait Cov -fun lowerBound(t: T, l: Cov) = t +fun lowerBound(t: T, l : Cov): T = throw Exception("$t $l") -fun testLowerBound(cov: Cov) { +fun testLowerBound(cov: Cov, covN: Cov) { val r = lowerBound(1, cov) - r: Any + TypeOf(r): TypeOf + + val n = lowerBound(1, covN) + TypeOf(n): TypeOf } trait Contr -fun upperBound(t: T, l: Contr) = t +fun upperBound(t: T, l: Contr): T = throw Exception("$t $l") fun testUpperBound(contrS: Contr, contrB: Contr, contrN: Contr) { upperBound(1, contrS) val n = upperBound(1, contrN) - n: Number - n: Int + TypeOf(n): TypeOf + val b = upperBound(1, contrB) - b: Byte - b: Int + TypeOf(b): TypeOf } diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 2cda468f7c8..05cac256d92 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -3291,6 +3291,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/inference/possibleCycleOnConstraints.kt"); } + @TestMetadata("tryNumberLowerBoundsBeforeUpperBounds.kt") + public void testTryNumberLowerBoundsBeforeUpperBounds() throws Exception { + doTest("compiler/testData/diagnostics/tests/inference/tryNumberLowerBoundsBeforeUpperBounds.kt"); + } + @TestMetadata("typeConstructorMismatch.kt") public void testTypeConstructorMismatch() throws Exception { doTest("compiler/testData/diagnostics/tests/inference/typeConstructorMismatch.kt"); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.java index e54129eb27d..3f278faeec5 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.java @@ -185,19 +185,10 @@ public class TypeBoundsImpl implements TypeBounds { } ContainerUtil.addIfNotNull(superTypeOfLowerBounds, values); - Set upperBounds = filterBounds(bounds, BoundKind.UPPER_BOUND, values); - JetType intersectionOfUpperBounds = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds); - if (!upperBounds.isEmpty() && intersectionOfUpperBounds != null) { - if (tryPossibleAnswer(intersectionOfUpperBounds)) { - return Collections.singleton(intersectionOfUpperBounds); - } - } //todo //fun foo(t: T, consumer: Consumer): T //foo(1, c: Consumer) - infer Int, not Any here - values.addAll(filterBounds(bounds, BoundKind.UPPER_BOUND)); - JetType superTypeOfNumberLowerBounds = TypeUtils.commonSupertypeForNumberTypes(numberLowerBounds); if (tryPossibleAnswer(superTypeOfNumberLowerBounds)) { return Collections.singleton(superTypeOfNumberLowerBounds); @@ -211,6 +202,17 @@ public class TypeBoundsImpl implements TypeBounds { return Collections.singleton(superTypeOfAllLowerBounds); } } + + Set upperBounds = filterBounds(bounds, BoundKind.UPPER_BOUND, values); + JetType intersectionOfUpperBounds = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds); + if (!upperBounds.isEmpty() && intersectionOfUpperBounds != null) { + if (tryPossibleAnswer(intersectionOfUpperBounds)) { + return Collections.singleton(intersectionOfUpperBounds); + } + } + + values.addAll(filterBounds(bounds, BoundKind.UPPER_BOUND)); + return values; }