From cd359a046c1622bea62087a3e2d084a39c2a9244 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Tue, 23 Sep 2014 15:29:47 +0400 Subject: [PATCH] Added captured types and approximation CapturedType captures type projection while solving the constraint system. During the substitution type containing captured types is approximated to get rid of captured types and (for simple cases) replace them with corresponding type projections. Note that Array> is (over)approximated by Array> See 'Mixed-site variance' by Ross Tate for details. #KT-2570 Fixed #KT-2872 Fixed #KT-3213 Fixed --- .../calls/inference/ConstraintsUtil.java | 2 +- .../calls/tasks/AbstractTracingStrategy.java | 3 + .../contravariant.kt | 11 ++ .../capturedTypeApproximation/covariant.kt | 11 ++ .../capturedTypeApproximation/invariant.kt | 11 ++ .../capturedTypeApproximation/nestedCov.kt | 12 ++ .../capturedTypeApproximation/nestedInv.kt | 11 ++ .../nestedInvLevel2.kt | 11 ++ .../useSiteVarianceIn.kt | 11 ++ .../useSiteVarianceOut.kt | 11 ++ .../tests/MergePackagesWithJava.txt | 82 +++++------ .../capturedTypes/captureForPlatformTypes.kt | 29 ++++ .../capturedTypes/captureForPlatformTypes.txt | 15 ++ .../inference/capturedTypes/capturedType.kt | 16 +++ .../inference/capturedTypes/capturedType.txt | 5 + .../capturedTypeAndApproximation.kt | 16 +++ .../capturedTypeAndApproximation.txt | 5 + .../tests/inference/capturedTypes/kt2570.kt | 9 ++ .../tests/inference/capturedTypes/kt2570.txt | 4 + .../tests/inference/capturedTypes/kt2872.kt | 6 + .../tests/inference/capturedTypes/kt2872.txt | 4 + .../diagnostics/tests/scopes/kt955.txt | 82 +++++------ .../checkers/JetDiagnosticsTestGenerated.java | 41 +++++- .../AbstractCapturedTypeApproximationTest.kt | 75 ++++++++++ ...apturedTypeApproximationTestGenerated.java | 86 +++++++++++ .../jet/types/TypeSubstitutorTest.java | 2 +- .../inference/CapturedTypeConstructor.kt | 65 +++++++++ .../calls/inference/ConstraintPosition.kt | 9 +- .../calls/inference/ConstraintSystemImpl.kt | 34 ++++- .../resolve/calls/inference/TypeBoundsImpl.kt | 3 +- .../lang/types/CapturedTypeApproximation.kt | 136 ++++++++++++++++++ .../jet/lang/types/TypeSubstitutor.java | 54 ++++--- .../checker/TypeCheckerTypingConstraints.java | 6 + .../types/checker/TypeCheckingProcedure.java | 26 ++++ .../lang/types/checker/TypingConstraints.java | 3 + .../jet/generators/tests/GenerateTests.kt | 5 + 36 files changed, 798 insertions(+), 114 deletions(-) create mode 100644 compiler/testData/capturedTypeApproximation/contravariant.kt create mode 100644 compiler/testData/capturedTypeApproximation/covariant.kt create mode 100644 compiler/testData/capturedTypeApproximation/invariant.kt create mode 100644 compiler/testData/capturedTypeApproximation/nestedCov.kt create mode 100644 compiler/testData/capturedTypeApproximation/nestedInv.kt create mode 100644 compiler/testData/capturedTypeApproximation/nestedInvLevel2.kt create mode 100644 compiler/testData/capturedTypeApproximation/useSiteVarianceIn.kt create mode 100644 compiler/testData/capturedTypeApproximation/useSiteVarianceOut.kt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/captureForPlatformTypes.kt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/captureForPlatformTypes.txt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/capturedType.kt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/capturedType.txt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeAndApproximation.kt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeAndApproximation.txt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/kt2570.kt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/kt2570.txt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/kt2872.kt create mode 100644 compiler/testData/diagnostics/tests/inference/capturedTypes/kt2872.txt create mode 100644 compiler/tests/org/jetbrains/jet/resolve/typeApproximation/AbstractCapturedTypeApproximationTest.kt create mode 100644 compiler/tests/org/jetbrains/jet/resolve/typeApproximation/CapturedTypeApproximationTestGenerated.java create mode 100644 core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/CapturedTypeConstructor.kt create mode 100644 core/descriptors/src/org/jetbrains/jet/lang/types/CapturedTypeApproximation.kt 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")