diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java index ccaaaf8b12b..5b08a12a67b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java @@ -47,7 +47,7 @@ public class ConstraintsUtil { Collection conflictingTypes = constraintSystem.getTypeBounds(firstConflictingParameter).getValues(); - ArrayList> substitutionContexts = Lists.newArrayList(); + List> substitutionContexts = Lists.newArrayList(); for (JetType type : conflictingTypes) { Map context = Maps.newLinkedHashMap(); context.put(firstConflictingParameter.getTypeConstructor(), new TypeProjectionImpl(type)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java index f2b3ec4c286..2efdcb6c8fc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/AbstractTracingStrategy.java @@ -226,6 +226,9 @@ public abstract class AbstractTracingStrategy implements TracingStrategy { assert !noExpectedType(data.expectedType) : "Expected type doesn't exist, but there is an expected type mismatch error"; trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(reference, data.expectedType, substitutedReturnType)); } + //else if (status.hasConflictWithCapturedType()) { + // trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(reference, data)); + //} else if (status.hasViolatedUpperBound()) { trace.report(TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(reference, data)); } diff --git a/compiler/testData/capturedTypeApproximation/contravariant.kt b/compiler/testData/capturedTypeApproximation/contravariant.kt new file mode 100644 index 00000000000..68f95b0ba34 --- /dev/null +++ b/compiler/testData/capturedTypeApproximation/contravariant.kt @@ -0,0 +1,11 @@ +class Contr + +fun foo(a: Contr) {} + +// T captures 'in Int' +// lower: Contr +// upper: Contr + +// T captures 'out Int' +// lower: Contr +// upper: Contr diff --git a/compiler/testData/capturedTypeApproximation/covariant.kt b/compiler/testData/capturedTypeApproximation/covariant.kt new file mode 100644 index 00000000000..a92cb853e38 --- /dev/null +++ b/compiler/testData/capturedTypeApproximation/covariant.kt @@ -0,0 +1,11 @@ +class Cov + +fun foo(a: Cov) {} + +// T captures 'in Int' +// lower: Cov +// upper: Cov + +// T captures 'out Int' +// lower: Cov +// upper: Cov diff --git a/compiler/testData/capturedTypeApproximation/invariant.kt b/compiler/testData/capturedTypeApproximation/invariant.kt new file mode 100644 index 00000000000..6b9a115d553 --- /dev/null +++ b/compiler/testData/capturedTypeApproximation/invariant.kt @@ -0,0 +1,11 @@ +class Inv + +fun foo(a: Inv) {} + +// T captures 'in Int' +// lower: Nothing +// upper: Inv + +// T captures 'out Int' +// lower: Nothing +// upper: Inv diff --git a/compiler/testData/capturedTypeApproximation/nestedCov.kt b/compiler/testData/capturedTypeApproximation/nestedCov.kt new file mode 100644 index 00000000000..746b0b19b7c --- /dev/null +++ b/compiler/testData/capturedTypeApproximation/nestedCov.kt @@ -0,0 +1,12 @@ +class Cov +class Inv + +fun foo(a: Cov>) {} + +// T captures 'in Int' +// lower: Cov +// upper: Cov> + +// T captures 'out Int' +// lower: Cov +// upper: Cov> diff --git a/compiler/testData/capturedTypeApproximation/nestedInv.kt b/compiler/testData/capturedTypeApproximation/nestedInv.kt new file mode 100644 index 00000000000..85d56c3ca38 --- /dev/null +++ b/compiler/testData/capturedTypeApproximation/nestedInv.kt @@ -0,0 +1,11 @@ +class Inv + +fun foo(a: Inv>) {} + +// T captures 'in Int' +// lower: Nothing +// upper: Inv> + +// T captures 'out Int' +// lower: Nothing +// upper: Inv> diff --git a/compiler/testData/capturedTypeApproximation/nestedInvLevel2.kt b/compiler/testData/capturedTypeApproximation/nestedInvLevel2.kt new file mode 100644 index 00000000000..679118362da --- /dev/null +++ b/compiler/testData/capturedTypeApproximation/nestedInvLevel2.kt @@ -0,0 +1,11 @@ +class Inv + +fun foo(a: Inv>>) {} + +// T captures 'in Int' +// lower: Nothing +// upper: Inv>> + +// T captures 'out Int' +// lower: Nothing +// upper: Inv>> diff --git a/compiler/testData/capturedTypeApproximation/useSiteVarianceIn.kt b/compiler/testData/capturedTypeApproximation/useSiteVarianceIn.kt new file mode 100644 index 00000000000..6b07a31b157 --- /dev/null +++ b/compiler/testData/capturedTypeApproximation/useSiteVarianceIn.kt @@ -0,0 +1,11 @@ +class Inv + +fun foo(a: Inv) {} + +// T captures 'in Int' +// lower: Inv +// upper: Inv + +// T captures 'out Int' +// lower: Inv +// upper: Inv diff --git a/compiler/testData/capturedTypeApproximation/useSiteVarianceOut.kt b/compiler/testData/capturedTypeApproximation/useSiteVarianceOut.kt new file mode 100644 index 00000000000..1e3a5f5afa0 --- /dev/null +++ b/compiler/testData/capturedTypeApproximation/useSiteVarianceOut.kt @@ -0,0 +1,11 @@ +class Inv + +fun foo(a: Inv) {} + +// T captures 'in Int' +// lower: Inv +// upper: Inv + +// T captures 'out Int' +// lower: Inv +// upper: Inv diff --git a/compiler/testData/diagnostics/tests/MergePackagesWithJava.txt b/compiler/testData/diagnostics/tests/MergePackagesWithJava.txt index 3f981f8a349..926bb2fb3bb 100644 --- a/compiler/testData/diagnostics/tests/MergePackagesWithJava.txt +++ b/compiler/testData/diagnostics/tests/MergePackagesWithJava.txt @@ -14280,15 +14280,15 @@ package java { private final inner class EntryIterator : java.util.HashMap.HashIterator!> { private constructor EntryIterator() - public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ var index: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): kotlin.(Mutable)Map.(Mutable)Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -14342,15 +14342,15 @@ package java { private final inner class KeyIterator : java.util.HashMap.HashIterator { private constructor KeyIterator() - public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ var index: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): K! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -14377,15 +14377,15 @@ package java { private final inner class ValueIterator : java.util.HashMap.HashIterator { private constructor ValueIterator() - public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ var index: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): V! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -15376,14 +15376,14 @@ package java { public/*package*/ final inner class DescendingKeyIterator : java.util.TreeMap.PrivateEntryIterator { public/*package*/ constructor DescendingKeyIterator(/*0*/ p0: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): K! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -15510,14 +15510,14 @@ package java { public/*package*/ final inner class EntryIterator : java.util.TreeMap.PrivateEntryIterator!> { public/*package*/ constructor EntryIterator(/*0*/ p0: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): kotlin.(Mutable)Map.(Mutable)Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -15545,14 +15545,14 @@ package java { public/*package*/ final inner class KeyIterator : java.util.TreeMap.PrivateEntryIterator { public/*package*/ constructor KeyIterator(/*0*/ p0: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): K! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -15670,14 +15670,14 @@ package java { public/*package*/ constructor DescendingSubMapEntryIterator(/*0*/ p0: java.util.TreeMap.Entry!, /*1*/ p1: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ val fenceKey: kotlin.Any! - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): kotlin.(Mutable)Map.(Mutable)Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ fun remove(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeAscending(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeDescending(): kotlin.Unit @@ -15688,14 +15688,14 @@ package java { public/*package*/ constructor DescendingSubMapKeyIterator(/*0*/ p0: java.util.TreeMap.Entry!, /*1*/ p1: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ val fenceKey: kotlin.Any! - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): K! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ fun remove(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeAscending(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeDescending(): kotlin.Unit @@ -15728,14 +15728,14 @@ package java { public/*package*/ constructor SubMapEntryIterator(/*0*/ p0: java.util.TreeMap.Entry!, /*1*/ p1: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ val fenceKey: kotlin.Any! - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): kotlin.(Mutable)Map.(Mutable)Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ fun remove(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeAscending(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeDescending(): kotlin.Unit @@ -15764,14 +15764,14 @@ package java { public/*package*/ constructor SubMapKeyIterator(/*0*/ p0: java.util.TreeMap.Entry!, /*1*/ p1: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ val fenceKey: kotlin.Any! - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): K! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ fun remove(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeAscending(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeDescending(): kotlin.Unit @@ -15833,14 +15833,14 @@ package java { public/*package*/ final inner class ValueIterator : java.util.TreeMap.PrivateEntryIterator { public/*package*/ constructor ValueIterator(/*0*/ p0: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): V! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/captureForPlatformTypes.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/captureForPlatformTypes.kt new file mode 100644 index 00000000000..5fc463b5d0a --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/captureForPlatformTypes.kt @@ -0,0 +1,29 @@ +// !CHECK_TYPE +// !DIAGNOSTICS: -UNUSED_VARIABLE +// FILE: A.java +public class A { + public static Class foo(Class clazz) { + return clazz; + } + + public static Class> bar(Class clazz) { + throw new Exception(); + } +} + +// FILE: b.kt +fun test1(clazz: Class) { + val foo0: Class = A.foo(clazz) + val foo1 = A.foo(clazz) + foo1 checkType { it: _< Class > } +// should be ok + foo1 checkType { it: _< Class > } +} + +fun tes2t(clazz: Class) { + val foo0: Class> = A.bar(clazz) + val foo1 = A.bar(clazz) + foo1 checkType { it: _< Class> > } +// should be ok + foo1 checkType { it: _< Class> > } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/captureForPlatformTypes.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/captureForPlatformTypes.txt new file mode 100644 index 00000000000..92fe99f03c9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/captureForPlatformTypes.txt @@ -0,0 +1,15 @@ +package + +internal fun tes2t(/*0*/ clazz: java.lang.Class): kotlin.Unit +internal fun test1(/*0*/ clazz: java.lang.Class): kotlin.Unit + +public open class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public open fun bar(/*0*/ clazz: java.lang.Class!): java.lang.Class!>! + public open fun foo(/*0*/ clazz: java.lang.Class!): java.lang.Class! +} diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedType.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedType.kt new file mode 100644 index 00000000000..a3b06dddff0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedType.kt @@ -0,0 +1,16 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// !CHECK_TYPE + +fun foo(array: Array): Array = array + +fun test1(a1: Array) { + val b1: Array = foo(a1) + val c1 = foo(a1) + c1 checkType { it : _> } +} + +fun test2(a2: Array) { + val b2: Array = foo(a2) + val c2 = foo(a2) + c2 checkType { it : _> } +} diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedType.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedType.txt new file mode 100644 index 00000000000..95c4749e805 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedType.txt @@ -0,0 +1,5 @@ +package + +internal fun foo(/*0*/ array: kotlin.Array): kotlin.Array +internal fun test1(/*0*/ a1: kotlin.Array): kotlin.Unit +internal fun test2(/*0*/ a2: kotlin.Array): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeAndApproximation.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeAndApproximation.kt new file mode 100644 index 00000000000..669d7db8b8c --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeAndApproximation.kt @@ -0,0 +1,16 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// !CHECK_TYPE + +fun foo(a: Array): Array> = throw Exception() + +fun test1(a1: Array) { + val b1: Array> = foo(a1) + val c1 = foo(a1) + c1 checkType { it : _>> } +} + +fun test2(a2: Array) { + val b2: Array> = foo(a2) + val c2 = foo(a2) + c2 checkType { it : _>> } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeAndApproximation.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeAndApproximation.txt new file mode 100644 index 00000000000..e3bf8ce2aa0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeAndApproximation.txt @@ -0,0 +1,5 @@ +package + +internal fun foo(/*0*/ a: kotlin.Array): kotlin.Array> +internal fun test1(/*0*/ a1: kotlin.Array): kotlin.Unit +internal fun test2(/*0*/ a2: kotlin.Array): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2570.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2570.kt new file mode 100644 index 00000000000..9f65199bb2d --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2570.kt @@ -0,0 +1,9 @@ +// !CHECK_TYPE +// !DIAGNOSTICS: -UNUSED_VARIABLE + +fun foo(l: MutableList): MutableList = l +fun test(l: MutableList) { + val a: MutableList = foo(l) + val b = foo(l) + b checkType { it: _< MutableList > } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2570.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2570.txt new file mode 100644 index 00000000000..b5ef01bc9b9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2570.txt @@ -0,0 +1,4 @@ +package + +internal fun foo(/*0*/ l: kotlin.MutableList): kotlin.MutableList +internal fun test(/*0*/ l: kotlin.MutableList): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2872.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2872.kt new file mode 100644 index 00000000000..bd8fe9249b7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2872.kt @@ -0,0 +1,6 @@ +fun Array.foo() {} + +fun test(array: Array) { + array.foo() + array.foo<out Int>() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2872.txt b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2872.txt new file mode 100644 index 00000000000..eb32a926636 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/kt2872.txt @@ -0,0 +1,4 @@ +package + +internal fun test(/*0*/ array: kotlin.Array): kotlin.Unit +internal fun kotlin.Array.foo(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/scopes/kt955.txt b/compiler/testData/diagnostics/tests/scopes/kt955.txt index 668b2ba2793..8a760c2ef3a 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt955.txt +++ b/compiler/testData/diagnostics/tests/scopes/kt955.txt @@ -14286,15 +14286,15 @@ package java { private final inner class EntryIterator : java.util.HashMap.HashIterator!> { private constructor EntryIterator() - public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ var index: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): kotlin.(Mutable)Map.(Mutable)Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -14348,15 +14348,15 @@ package java { private final inner class KeyIterator : java.util.HashMap.HashIterator { private constructor KeyIterator() - public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ var index: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): K! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -14383,15 +14383,15 @@ package java { private final inner class ValueIterator : java.util.HashMap.HashIterator { private constructor ValueIterator() - public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var current: java.util.HashMap.Entry! public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ var index: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): V! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.HashMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -15382,14 +15382,14 @@ package java { public/*package*/ final inner class DescendingKeyIterator : java.util.TreeMap.PrivateEntryIterator { public/*package*/ constructor DescendingKeyIterator(/*0*/ p0: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): K! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -15516,14 +15516,14 @@ package java { public/*package*/ final inner class EntryIterator : java.util.TreeMap.PrivateEntryIterator!> { public/*package*/ constructor EntryIterator(/*0*/ p0: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): kotlin.(Mutable)Map.(Mutable)Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -15551,14 +15551,14 @@ package java { public/*package*/ final inner class KeyIterator : java.util.TreeMap.PrivateEntryIterator { public/*package*/ constructor KeyIterator(/*0*/ p0: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): K! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } @@ -15676,14 +15676,14 @@ package java { public/*package*/ constructor DescendingSubMapEntryIterator(/*0*/ p0: java.util.TreeMap.Entry!, /*1*/ p1: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ val fenceKey: kotlin.Any! - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): kotlin.(Mutable)Map.(Mutable)Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ fun remove(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeAscending(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeDescending(): kotlin.Unit @@ -15694,14 +15694,14 @@ package java { public/*package*/ constructor DescendingSubMapKeyIterator(/*0*/ p0: java.util.TreeMap.Entry!, /*1*/ p1: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ val fenceKey: kotlin.Any! - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): K! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ fun remove(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeAscending(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeDescending(): kotlin.Unit @@ -15734,14 +15734,14 @@ package java { public/*package*/ constructor SubMapEntryIterator(/*0*/ p0: java.util.TreeMap.Entry!, /*1*/ p1: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ val fenceKey: kotlin.Any! - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): kotlin.(Mutable)Map.(Mutable)Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ fun remove(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeAscending(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeDescending(): kotlin.Unit @@ -15770,14 +15770,14 @@ package java { public/*package*/ constructor SubMapKeyIterator(/*0*/ p0: java.util.TreeMap.Entry!, /*1*/ p1: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int public/*package*/ final override /*1*/ /*fake_override*/ val fenceKey: kotlin.Any! - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): K! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ fun remove(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeAscending(): kotlin.Unit public/*package*/ final override /*1*/ /*fake_override*/ fun removeDescending(): kotlin.Unit @@ -15839,14 +15839,14 @@ package java { public/*package*/ final inner class ValueIterator : java.util.TreeMap.PrivateEntryIterator { public/*package*/ constructor ValueIterator(/*0*/ p0: java.util.TreeMap.Entry!) public/*package*/ final override /*1*/ /*fake_override*/ var expectedModCount: kotlin.Int - public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var lastReturned: java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ var next: java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final override /*1*/ /*fake_override*/ fun hasNext(): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ fun next(): V! - public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! - public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun nextEntry(): java.util.TreeMap.Entry! + public/*package*/ final override /*1*/ /*fake_override*/ fun prevEntry(): java.util.TreeMap.Entry! public open override /*1*/ /*fake_override*/ fun remove(): kotlin.Unit public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 27457ead0d5..1c687543c7c 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -4899,7 +4899,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { @TestMetadata("compiler/testData/diagnostics/tests/inference") @TestDataPath("$PROJECT_ROOT") - @InnerTestClasses({Inference.Constraints.class, Inference.NestedCalls.class, Inference.Regressions.class, Inference.ReportingImprovements.class, Inference.Substitutions.class, Inference.UpperBounds.class, Inference.Varargs.class}) + @InnerTestClasses({Inference.CapturedTypes.class, Inference.Constraints.class, Inference.NestedCalls.class, Inference.Regressions.class, Inference.ReportingImprovements.class, Inference.Substitutions.class, Inference.UpperBounds.class, Inference.Varargs.class}) @RunWith(JUnit3RunnerWithInners.class) public static class Inference extends AbstractJetDiagnosticsTest { public void testAllFilesPresentInInference() throws Exception { @@ -5086,6 +5086,45 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CapturedTypes extends AbstractJetDiagnosticsTest { + public void testAllFilesPresentInCapturedTypes() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/capturedTypes"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("captureForPlatformTypes.kt") + public void testCaptureForPlatformTypes() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/captureForPlatformTypes.kt"); + doTest(fileName); + } + + @TestMetadata("capturedType.kt") + public void testCapturedType() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedType.kt"); + doTest(fileName); + } + + @TestMetadata("capturedTypeAndApproximation.kt") + public void testCapturedTypeAndApproximation() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeAndApproximation.kt"); + doTest(fileName); + } + + @TestMetadata("kt2570.kt") + public void testKt2570() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/kt2570.kt"); + doTest(fileName); + } + + @TestMetadata("kt2872.kt") + public void testKt2872() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/kt2872.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/inference/constraints") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/jet/resolve/typeApproximation/AbstractCapturedTypeApproximationTest.kt b/compiler/tests/org/jetbrains/jet/resolve/typeApproximation/AbstractCapturedTypeApproximationTest.kt new file mode 100644 index 00000000000..03fa6b47258 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/resolve/typeApproximation/AbstractCapturedTypeApproximationTest.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.resolve.typeApproximation + +import org.jetbrains.jet.JetLiteFixture +import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment +import org.jetbrains.jet.ConfigurationKind +import java.io.File +import org.jetbrains.jet.lang.resolve.lazy.JvmResolveUtil +import org.jetbrains.jet.lang.resolve.BindingContext +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor +import org.jetbrains.jet.lang.types.TypeSubstitutor +import org.jetbrains.jet.lang.types.TypeProjectionImpl +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns +import org.jetbrains.jet.lang.types.Variance +import org.jetbrains.jet.lang.types.typesApproximation.approximateCapturedTypes +import org.jetbrains.jet.JetTestUtils +import org.jetbrains.jet.lang.psi.JetPsiFactory +import org.jetbrains.jet.lang.resolve.calls.inference.CapturedTypeConstructor +import org.jetbrains.jet.lang.types.JetTypeImpl +import org.jetbrains.jet.lang.resolve.calls.inference.createCapturedType + +abstract public class AbstractCapturedTypeApproximationTest() : JetLiteFixture() { + override fun createEnvironment(): JetCoreEnvironment = createEnvironmentWithMockJdk(ConfigurationKind.ALL) + + public fun doTest(filePath: String) { + val file = File(filePath) + val text = JetTestUtils.doLoadFile(file)!! + + val jetFile = JetPsiFactory(getProject()).createFile(text) + val bindingContext = JvmResolveUtil.analyzeOneFileWithJavaIntegration(jetFile).bindingContext + + val functions = bindingContext.getSliceContents(BindingContext.FUNCTION) + val functionFoo = functions.values().firstOrNull { it.getName().asString() == "foo" } ?: + throw AssertionError("Function 'foo' is not declared") + val typeParameter = functionFoo.getTypeParameters().first() + val parameter = functionFoo.getValueParameters().first().getType() + + val result = StringBuilder { + val endIndex = text.indexOf("// T captures") + appendln(if (endIndex == -1) text else text.substring(0, endIndex).trimTrailing()) + + for (variance in listOf(Variance.IN_VARIANCE, Variance.OUT_VARIANCE)) { + + val captured = createCapturedType(TypeProjectionImpl(variance, KotlinBuiltIns.getInstance().getIntType())) + val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter.getTypeConstructor() to TypeProjectionImpl(captured))) + val typeWithCapturedType = typeSubstitutor.substituteWithoutApproximation( + TypeProjectionImpl(Variance.INVARIANT, parameter))!!.getType() + + val (lower, upper) = approximateCapturedTypes(typeWithCapturedType) + + appendln() + appendln("// T captures '${(captured.getConstructor() as CapturedTypeConstructor).typeProjection}'") + appendln("// lower: $lower") + appendln("// upper: $upper") + } + }.toString() + + JetTestUtils.assertEqualsToFile(file, result) + } +} diff --git a/compiler/tests/org/jetbrains/jet/resolve/typeApproximation/CapturedTypeApproximationTestGenerated.java b/compiler/tests/org/jetbrains/jet/resolve/typeApproximation/CapturedTypeApproximationTestGenerated.java new file mode 100644 index 00000000000..3da38c221c3 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/resolve/typeApproximation/CapturedTypeApproximationTestGenerated.java @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.resolve.typeApproximation; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.jet.JUnit3RunnerWithInners; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.test.InnerTestClasses; +import org.jetbrains.jet.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("compiler/testData/capturedTypeApproximation") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class CapturedTypeApproximationTestGenerated extends AbstractCapturedTypeApproximationTest { + public void testAllFilesPresentInCapturedTypeApproximation() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/capturedTypeApproximation"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("contravariant.kt") + public void testContravariant() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/capturedTypeApproximation/contravariant.kt"); + doTest(fileName); + } + + @TestMetadata("covariant.kt") + public void testCovariant() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/capturedTypeApproximation/covariant.kt"); + doTest(fileName); + } + + @TestMetadata("invariant.kt") + public void testInvariant() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/capturedTypeApproximation/invariant.kt"); + doTest(fileName); + } + + @TestMetadata("nestedCov.kt") + public void testNestedCov() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/capturedTypeApproximation/nestedCov.kt"); + doTest(fileName); + } + + @TestMetadata("nestedInv.kt") + public void testNestedInv() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/capturedTypeApproximation/nestedInv.kt"); + doTest(fileName); + } + + @TestMetadata("nestedInvLevel2.kt") + public void testNestedInvLevel2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/capturedTypeApproximation/nestedInvLevel2.kt"); + doTest(fileName); + } + + @TestMetadata("useSiteVarianceIn.kt") + public void testUseSiteVarianceIn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/capturedTypeApproximation/useSiteVarianceIn.kt"); + doTest(fileName); + } + + @TestMetadata("useSiteVarianceOut.kt") + public void testUseSiteVarianceOut() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/capturedTypeApproximation/useSiteVarianceOut.kt"); + doTest(fileName); + } +} diff --git a/compiler/tests/org/jetbrains/jet/types/TypeSubstitutorTest.java b/compiler/tests/org/jetbrains/jet/types/TypeSubstitutorTest.java index 29a76e906e2..b31b0cb497c 100644 --- a/compiler/tests/org/jetbrains/jet/types/TypeSubstitutorTest.java +++ b/compiler/tests/org/jetbrains/jet/types/TypeSubstitutorTest.java @@ -235,7 +235,7 @@ public class TypeSubstitutorTest extends KotlinTestWithEnvironment { public void testOutInProjection() throws Exception { doTest( - "C", + "C", "C", map("T", "in String") ); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/CapturedTypeConstructor.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/CapturedTypeConstructor.kt new file mode 100644 index 00000000000..660fbddba60 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/CapturedTypeConstructor.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.calls.inference + +import org.jetbrains.jet.lang.types.JetType +import org.jetbrains.jet.lang.types.TypeProjection +import org.jetbrains.jet.lang.types.TypeConstructor +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor +import org.jetbrains.jet.lang.descriptors.annotations.Annotations +import org.jetbrains.jet.lang.types.Variance +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns +import org.jetbrains.jet.lang.types.JetTypeImpl +import org.jetbrains.jet.lang.types.ErrorUtils + +public class CapturedTypeConstructor( + public val typeProjection: TypeProjection +): TypeConstructor { + { + assert(typeProjection.getProjectionKind() != Variance.INVARIANT) { + "Only nontrivial projections can be captured, not: $typeProjection" + } + } + + override fun getParameters(): List = listOf() + + override fun getSupertypes(): Collection { + val superType = if (typeProjection.getProjectionKind() == Variance.OUT_VARIANCE) + typeProjection.getType() + else + KotlinBuiltIns.getInstance().getNullableAnyType() + return listOf(superType) + } + + override fun isFinal() = true + + override fun isDenotable() = false + + override fun getDeclarationDescriptor() = null + + override fun getAnnotations() = Annotations.EMPTY + + override fun toString() = "Captured($typeProjection)" +} + +public fun createCapturedType(typeProjection: TypeProjection): JetType { + val scope = ErrorUtils.createErrorScope("No member resolution should be done on captured type, " + + "it used only during constraint system resolution", true) + return JetTypeImpl(Annotations.EMPTY, CapturedTypeConstructor(typeProjection), false, listOf(), scope) +} + +public fun JetType.isCaptured(): Boolean = getConstructor() is CapturedTypeConstructor \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.kt index aa473f24352..b0c4b2f6d31 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.kt @@ -43,6 +43,8 @@ public trait ConstraintPosition { val kind: ConstraintPositionKind fun isStrong(): Boolean = kind != TYPE_BOUND_POSITION + + fun isCaptureAllowed(): Boolean = kind in setOf(VALUE_PARAMETER_POSITION, RECEIVER_POSITION) } private open data class ConstraintPositionImpl(override val kind: ConstraintPositionKind) : ConstraintPosition { @@ -53,14 +55,11 @@ private data class ConstraintPositionWithIndex(override val kind: ConstraintPosi } class CompoundConstraintPosition( - val positions: Collection + vararg positions: ConstraintPosition ) : ConstraintPositionImpl(ConstraintPositionKind.COMPOUND_CONSTRAINT_POSITION) { + val positions: Collection = positions.toList() override fun isStrong() = positions.any { it.isStrong() } override fun toString() = "$kind(${positions.joinToString()}" -} - -public fun getCompoundConstraintPosition(vararg positions: ConstraintPosition): ConstraintPosition { - return CompoundConstraintPosition(positions.toList()) } \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.kt index 68316aaa35b..aed76d2da43 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.kt @@ -41,7 +41,6 @@ import org.jetbrains.jet.lang.resolve.calls.inference.constraintPosition.Constra import org.jetbrains.jet.lang.resolve.calls.inference.constraintPosition.ConstraintPositionKind import org.jetbrains.jet.lang.resolve.calls.inference.constraintPosition.ConstraintPositionKind.* import org.jetbrains.jet.lang.resolve.calls.inference.constraintPosition.CompoundConstraintPosition -import org.jetbrains.jet.lang.resolve.calls.inference.constraintPosition.getCompoundConstraintPosition import org.jetbrains.jet.lang.types.CustomTypeVariable import org.jetbrains.jet.lang.types.getCustomTypeVariable import org.jetbrains.jet.lang.types.isFlexible @@ -226,6 +225,14 @@ public class ConstraintSystemImpl : ConstraintSystem { return true } + override fun capture(typeVariable: JetType, typeProjection: TypeProjection): Boolean { + if (isMyTypeVariable(typeVariable) && constraintPosition.isCaptureAllowed()) { + generateTypeParameterCaptureConstraint(typeVariable, typeProjection, constraintPosition) + return true + } + return false + } + override fun noCorrespondingSupertype(subtype: JetType, supertype: JetType): Boolean { errorConstraintPositions.add(constraintPosition) return true @@ -303,9 +310,16 @@ public class ConstraintSystemImpl : ConstraintSystem { generateTypeParameterConstraint(superType, subType, boundKind, constraintPosition) return } - // if superType is nullable and subType is not nullable, unsafe call error will be generated later, + // if superType is nullable and subType is not nullable, unsafe call or type mismatch error will be generated later, // but constraint system should be solved anyway - typeCheckingProcedure.isSubtypeOf(TypeUtils.makeNotNullable(subType), TypeUtils.makeNotNullable(superType)) + val subTypeNotNullable = TypeUtils.makeNotNullable(subType) + val superTypeNotNullable = TypeUtils.makeNotNullable(superType) + if (constraintKind == EQUAL) { + typeCheckingProcedure.equalTypes(subTypeNotNullable, superTypeNotNullable) + } + else { + typeCheckingProcedure.isSubtypeOf(subTypeNotNullable, superTypeNotNullable) + } } simplifyConstraint(newSubType, superType) } @@ -352,6 +366,16 @@ public class ConstraintSystemImpl : ConstraintSystem { } } + private fun generateTypeParameterCaptureConstraint( + parameterType: JetType, + constrainingTypeProjection: TypeProjection, + constraintPosition: ConstraintPosition + ) { + val typeBounds = getTypeBounds(parameterType) + val capturedType = createCapturedType(constrainingTypeProjection) + typeBounds.addBound(EXACT_BOUND, capturedType, constraintPosition) + } + public fun processDeclaredBoundConstraints() { for ((typeParameterDescriptor, typeBounds) in typeParameterBounds) { for (declaredUpperBound in typeParameterDescriptor.getUpperBounds()) { @@ -359,7 +383,7 @@ public class ConstraintSystemImpl : ConstraintSystem { val bounds = ArrayList(typeBounds.bounds) for (bound in bounds) { if (bound.kind == LOWER_BOUND || bound.kind == EXACT_BOUND) { - val position = getCompoundConstraintPosition( + val position = CompoundConstraintPosition( TYPE_BOUND_POSITION.position(typeParameterDescriptor.getIndex()), bound.position) addSubtypeConstraint(bound.constrainingType, declaredUpperBound, position) } @@ -368,7 +392,7 @@ public class ConstraintSystemImpl : ConstraintSystem { val typeBoundsForUpperBound = getTypeBounds(declaredUpperBound) for (bound in typeBoundsForUpperBound.bounds) { if (bound.kind == UPPER_BOUND || bound.kind == EXACT_BOUND) { - val position = getCompoundConstraintPosition( + val position = CompoundConstraintPosition( TYPE_BOUND_POSITION.position(typeParameterDescriptor.getIndex()), bound.position) typeBounds.addBound(UPPER_BOUND, bound.constrainingType, position) } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.kt index de4c72e2b14..a3703ee7ab9 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.kt @@ -156,7 +156,8 @@ public class TypeBoundsImpl( private fun tryPossibleAnswer(possibleAnswer: JetType?): Boolean { if (possibleAnswer == null) return false - if (!possibleAnswer.getConstructor().isDenotable()) return false + // a captured type might be an answer + if (!possibleAnswer.getConstructor().isDenotable() && !possibleAnswer.isCaptured()) return false for (bound in bounds) { when (bound.kind) { diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/CapturedTypeApproximation.kt b/core/descriptors/src/org/jetbrains/jet/lang/types/CapturedTypeApproximation.kt new file mode 100644 index 00000000000..2c72ead8421 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/CapturedTypeApproximation.kt @@ -0,0 +1,136 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.types.typesApproximation + +import org.jetbrains.jet.lang.types.JetType +import org.jetbrains.jet.lang.types.checker.JetTypeChecker +import org.jetbrains.jet.lang.types.TypeProjection +import org.jetbrains.jet.lang.types.TypeProjectionImpl +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns +import org.jetbrains.jet.lang.types.Variance +import java.util.ArrayList +import org.jetbrains.jet.lang.types.JetTypeImpl +import org.jetbrains.jet.lang.types.TypeUtils +import org.jetbrains.jet.lang.resolve.calls.inference.CapturedTypeConstructor +import org.jetbrains.jet.lang.types.TypeSubstitutor +import org.jetbrains.jet.lang.types.TypeSubstitution +import org.jetbrains.jet.lang.types.TypeConstructor +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor +import org.jetbrains.jet.lang.types.LazyType +import org.jetbrains.jet.lang.resolve.calls.inference.isCaptured + +public data class ApproximationBounds( + public val lower: T, + public val upper: T +) + +private class TypeArgument( + val typeParameter: TypeParameterDescriptor, + val inProjection: JetType, + val outProjection: JetType +) { + val isConsistent: Boolean + get() = JetTypeChecker.DEFAULT.isSubtypeOf(inProjection, outProjection) +} + +private val NULLABLE_ANY = KotlinBuiltIns.getInstance().getNullableAnyType() + +private val NOTHING = KotlinBuiltIns.getInstance().getNothingType() + +private fun TypeArgument.toTypeProjection(): TypeProjection { + assert(isConsistent) { "Only consistent enhanced type propection can be converted to type projection" } + fun removeProjectionIfRedundant(variance: Variance) = if (variance == typeParameter.getVariance()) Variance.INVARIANT else variance + return when { + inProjection == outProjection -> TypeProjectionImpl(inProjection) + inProjection == NOTHING -> TypeProjectionImpl(removeProjectionIfRedundant(Variance.OUT_VARIANCE), outProjection) + outProjection == NULLABLE_ANY -> TypeProjectionImpl(removeProjectionIfRedundant(Variance.IN_VARIANCE), inProjection) + else -> throw AssertionError("Enhanced type projection can't be converted to type projection: $this") + } +} + +private fun TypeProjection.toTypeArgument(typeParameter: TypeParameterDescriptor) = + when (TypeSubstitutor.combine(typeParameter.getVariance(), getProjectionKind()) : Variance) { + Variance.INVARIANT -> TypeArgument(typeParameter, getType(), getType()) + Variance.IN_VARIANCE -> TypeArgument(typeParameter, getType(), NULLABLE_ANY) + Variance.OUT_VARIANCE -> TypeArgument(typeParameter, NOTHING, getType()) + } + +public fun approximateCapturedTypesIfNecessary(typeProjection: TypeProjection?): TypeProjection? { + if (typeProjection == null) return null + + val type = typeProjection.getType() + if (!TypeUtils.containsSpecialType(type, { it.isCaptured() })) { + return typeProjection + } + val howThisTypeIsUsed = typeProjection.getProjectionKind() + if (howThisTypeIsUsed == Variance.OUT_VARIANCE) { + // only 'return' type containing captured types should be over-approximated + val approximation = approximateCapturedTypes(type) + return TypeProjectionImpl(howThisTypeIsUsed, approximation.upper) + } + return substituteCapturedTypes(typeProjection) +} + +private fun substituteCapturedTypes(typeProjection: TypeProjection): TypeProjection? { + val typeSubstitutor = TypeSubstitutor.create(object : TypeSubstitution { + override fun get(typeConstructor: TypeConstructor?): TypeProjection? { + return (typeConstructor as? CapturedTypeConstructor)?.typeProjection + } + override fun isEmpty() = false + }) + return typeSubstitutor.substituteWithoutApproximation(typeProjection) +} + +public fun approximateCapturedTypes(type: JetType): ApproximationBounds { + val typeConstructor = type.getConstructor() + if (type.isCaptured()) { + val typeProjection = (typeConstructor as CapturedTypeConstructor).typeProjection + + return when (typeProjection.getProjectionKind()) { + Variance.IN_VARIANCE -> ApproximationBounds(typeProjection.getType(), NULLABLE_ANY) + Variance.OUT_VARIANCE -> ApproximationBounds(NOTHING, typeProjection.getType()) + else -> throw AssertionError("Only nontrivial projections should have been captured, not: $typeProjection") + } + } + if (type.getArguments().isEmpty()) { + return ApproximationBounds(type, type) + } + val lowerBoundArguments = ArrayList() + val upperBoundArguments = ArrayList() + for ((typeProjection, typeParameter) in type.getArguments().zip(typeConstructor.getParameters())) { + val (lower, upper) = approximateProjection(typeProjection.toTypeArgument(typeParameter)) + lowerBoundArguments.add(lower) + upperBoundArguments.add(upper) + } + val lowerBoundIsTrivial = lowerBoundArguments.any { !it.isConsistent } + return ApproximationBounds( + if (lowerBoundIsTrivial) NOTHING else type.replaceTypeArguments(lowerBoundArguments), + type.replaceTypeArguments(upperBoundArguments)) +} + +private fun JetType.replaceTypeArguments(newTypeArguments: List): JetType { + assert(getArguments().size() == newTypeArguments.size()) { "Incorrect type arguments $newTypeArguments" } + return JetTypeImpl(getAnnotations(), getConstructor(), isMarkedNullable(), newTypeArguments.map { it.toTypeProjection() }, getMemberScope()) +} + +private fun approximateProjection(typeArgument: TypeArgument): ApproximationBounds { + val (inLower, inUpper) = approximateCapturedTypes(typeArgument.inProjection) + val (outLower, outUpper) = approximateCapturedTypes(typeArgument.outProjection) + return ApproximationBounds( + lower = TypeArgument(typeArgument.typeParameter, inUpper, outLower), + upper = TypeArgument(typeArgument.typeParameter, inLower, outUpper)) +} \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java index 913d03abb34..0238be9e7b4 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java @@ -22,6 +22,7 @@ import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.typeUtil.TypeUtilPackage; +import org.jetbrains.jet.lang.types.typesApproximation.TypesApproximationPackage; import java.util.*; @@ -60,18 +61,22 @@ public class TypeSubstitutor { } } + @NotNull public static TypeSubstitutor create(@NotNull TypeSubstitution substitution) { return new TypeSubstitutor(substitution); } + @NotNull public static TypeSubstitutor create(@NotNull TypeSubstitution... substitutions) { return create(new CompositeTypeSubstitution(substitutions)); } + @NotNull public static TypeSubstitutor create(@NotNull Map substitutionContext) { return create(new MapToTypeSubstitutionAdapter(substitutionContext)); } + @NotNull public static TypeSubstitutor create(@NotNull JetType context) { return create(buildSubstitutionContext(context.getConstructor().getParameters(), context.getArguments())); } @@ -135,6 +140,12 @@ public class TypeSubstitutor { @Nullable public TypeProjection substitute(@NotNull TypeProjection typeProjection) { + TypeProjection substitutedTypeProjection = substituteWithoutApproximation(typeProjection); + return TypesApproximationPackage.approximateCapturedTypesIfNecessary(substitutedTypeProjection); + } + + @Nullable + public TypeProjection substituteWithoutApproximation(@NotNull TypeProjection typeProjection) { if (isEmpty()) { return typeProjection; } @@ -159,14 +170,15 @@ public class TypeSubstitutor { unsafeSubstitute(new TypeProjectionImpl(originalProjectionKind, flexibility.getLowerBound()), recursionDepth + 1); TypeProjection substitutedUpper = unsafeSubstitute(new TypeProjectionImpl(originalProjectionKind, flexibility.getUpperBound()), recursionDepth + 1); - // todo: projection kind is neglected - return new TypeProjectionImpl(originalProjectionKind, - DelegatingFlexibleType.create( - substitutedLower.getType(), - substitutedUpper.getType(), - flexibility.getExtraCapabilities() - ) - ); + + Variance substitutedProjectionKind = substitutedLower.getProjectionKind(); + assert (substitutedProjectionKind == substitutedUpper.getProjectionKind()) && + originalProjectionKind == Variance.INVARIANT || originalProjectionKind == substitutedProjectionKind : + "Unexpected substituted projection kind: " + substitutedProjectionKind + "; original: " + originalProjectionKind; + + JetType substitutedFlexibleType = DelegatingFlexibleType.create( + substitutedLower.getType(), substitutedUpper.getType(), flexibility.getExtraCapabilities()); + return new TypeProjectionImpl(substitutedProjectionKind, substitutedFlexibleType); } if (KotlinBuiltIns.isNothing(type) || type.isError()) return originalProjection; @@ -174,15 +186,12 @@ public class TypeSubstitutor { TypeProjection replacement = substitution.get(type.getConstructor()); if (replacement != null) { - // It must be a type parameter: only they can be directly substituted for - TypeParameterDescriptor typeParameter = (TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor(); - switch (conflictType(originalProjectionKind, replacement.getProjectionKind())) { case OUT_IN_IN_POSITION: throw new SubstitutionException("Out-projection in in-position"); case IN_IN_OUT_POSITION: - //noinspection ConstantConditions - return TypeUtils.makeStarProjection(typeParameter); + // todo use the right type parameter variance and upper bound + return new TypeProjectionImpl(Variance.OUT_VARIANCE, KotlinBuiltIns.getInstance().getNullableAnyType()); case NO_CONFLICT: JetType substitutedType; CustomTypeVariable typeVariable = TypesPackage.getCustomTypeVariable(type); @@ -191,7 +200,7 @@ public class TypeSubstitutor { } else { // this is a simple type T or T?: if it's T, we should just take replacement, if T? - we make replacement nullable - substitutedType = type.isMarkedNullable() ? TypeUtils.makeNullable(replacement.getType()) : replacement.getType(); + substitutedType = TypeUtils.makeNullableIfNeeded(replacement.getType(), type.isMarkedNullable()); } Variance resultingProjectionKind = combine(originalProjectionKind, replacement.getProjectionKind()); @@ -201,14 +210,21 @@ public class TypeSubstitutor { } } // The type is not within the substitution range, i.e. Foo, Bar etc. - return substituteCompoundType(type, originalProjectionKind, recursionDepth); + return substituteCompoundType(originalProjection, recursionDepth); } private TypeProjection substituteCompoundType( - final JetType type, - Variance projectionKind, + TypeProjection originalProjection, int recursionDepth ) throws SubstitutionException { + final JetType type = originalProjection.getType(); + Variance projectionKind = originalProjection.getProjectionKind(); + if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) { + // substitution can't change type parameter + // todo substitute bounds + return originalProjection; + } + List substitutedArguments = substituteTypeArguments( type.getConstructor().getParameters(), type.getArguments(), recursionDepth); @@ -265,10 +281,12 @@ public class TypeSubstitutor { return substitutedArguments; } - private static Variance combine(Variance typeParameterVariance, Variance projectionKind) { + @NotNull + public static Variance combine(@NotNull Variance typeParameterVariance, @NotNull Variance projectionKind) { if (typeParameterVariance == Variance.INVARIANT) return projectionKind; if (projectionKind == Variance.INVARIANT) return typeParameterVariance; if (typeParameterVariance == projectionKind) return projectionKind; + //todo ask why? return Variance.IN_VARIANCE; } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckerTypingConstraints.java b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckerTypingConstraints.java index 498f919eb36..0a053ad2b7d 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckerTypingConstraints.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckerTypingConstraints.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.types.checker; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeConstructor; +import org.jetbrains.jet.lang.types.TypeProjection; class TypeCheckerTypingConstraints implements TypingConstraints { @Override @@ -36,6 +37,11 @@ class TypeCheckerTypingConstraints implements TypingConstraints { return typeCheckingProcedure.isSubtypeOf(subtype, supertype); } + @Override + public boolean capture(@NotNull JetType type, @NotNull TypeProjection typeProjection) { + return false; + } + @Override public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) { return false; // type checking fails diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java index 0df208a10f4..1f4903e3867 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypeCheckingProcedure.java @@ -106,6 +106,9 @@ public class TypeCheckingProcedure { TypeProjection typeProjection1 = type1Arguments.get(i); TypeParameterDescriptor typeParameter2 = constructor2.getParameters().get(i); TypeProjection typeProjection2 = type2Arguments.get(i); + if (capture(typeProjection1, typeProjection2, typeParameter1)) { + continue; + } if (getEffectiveProjectionKind(typeParameter1, typeProjection1) != getEffectiveProjectionKind(typeParameter2, typeProjection2)) { return false; } @@ -225,6 +228,8 @@ public class TypeCheckingProcedure { JetType superIn = getInType(parameter, superArgument); JetType superOut = getOutType(parameter, superArgument); + if (capture(subArgument, superArgument, parameter)) continue; + boolean argumentIsErrorType = subArgument.getType().isError() || superArgument.getType().isError(); if (!argumentIsErrorType && parameter.getVariance() == INVARIANT && subArgument.getProjectionKind() == INVARIANT && superArgument.getProjectionKind() == INVARIANT) { @@ -237,4 +242,25 @@ public class TypeCheckingProcedure { } return true; } + + private boolean capture( + @NotNull TypeProjection firstProjection, + @NotNull TypeProjection secondProjection, + @NotNull TypeParameterDescriptor parameter + ) { + // Capturing makes sense only for invariant classes + if (parameter.getVariance() != INVARIANT) return false; + + // Now, both subtype and supertype relations transform to equality constraints on type arguments: + // Array is a subtype, supertype or equal to Array then T captures a type that extends Int: 'Captured(out Int)' + // Array is a subtype, supertype or equal to Array then T captures a type that extends Int: 'Captured(in Int)' + + if (firstProjection.getProjectionKind() == INVARIANT && secondProjection.getProjectionKind() != INVARIANT) { + return constraints.capture(firstProjection.getType(), secondProjection); + } + if (firstProjection.getProjectionKind() != INVARIANT && secondProjection.getProjectionKind() == INVARIANT) { + return constraints.capture(secondProjection.getType(), firstProjection); + } + return false; + } } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypingConstraints.java b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypingConstraints.java index 3254818b9c8..51a3072c11c 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypingConstraints.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/checker/TypingConstraints.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.types.checker; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeConstructor; +import org.jetbrains.jet.lang.types.TypeProjection; /** * Methods of this class return true to continue type checking and false to fail @@ -30,5 +31,7 @@ public interface TypingConstraints { boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure); + boolean capture(@NotNull JetType type, @NotNull TypeProjection typeProjection); + boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype); } diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index cc05cf028fd..1b173f235a8 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -116,6 +116,7 @@ import org.jetbrains.jet.lang.resolve.java.AbstractJavaTypeSubstitutorTest import org.jetbrains.jet.plugin.intentions.declarations.AbstractJoinLinesTest import org.jetbrains.jet.codegen.AbstractScriptCodegenTest import org.jetbrains.jet.plugin.parameterInfo.AbstractFunctionParameterInfoTest +import org.jetbrains.jet.resolve.typeApproximation.AbstractCapturedTypeApproximationTest import org.jetbrains.jet.psi.patternMatching.AbstractJetPsiUnifierTest import org.jetbrains.jet.completion.weighers.AbstractBasicCompletionWeigherTest import org.jetbrains.jet.completion.weighers.AbstractSmartCompletionWeigherTest @@ -167,6 +168,10 @@ fun main(args: Array) { model("constraintSystem", extension = "bounds") } + testClass(javaClass()) { + model("capturedTypeApproximation") + } + testClass(javaClass()) { model("psi", testMethod = "doParsingTest", pattern = "^(.*)\\.kts?$") model("parseCodeFragment/expression", testMethod = "doExpressionCodeFragmentParsingTest", extension = "kt")