diff --git a/compiler/testData/diagnostics/tests/functionLiterals/kt7383_starProjectedFunction.kt b/compiler/testData/diagnostics/tests/functionLiterals/kt7383_starProjectedFunction.kt index 10691a9c534..54e02ed4d81 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/kt7383_starProjectedFunction.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/kt7383_starProjectedFunction.kt @@ -2,5 +2,5 @@ fun foo() { val f : Function1<*, *> = { x -> x.toString() } - f(1) + f(1) } diff --git a/compiler/testData/diagnostics/tests/generics/Projections.kt b/compiler/testData/diagnostics/tests/generics/Projections.kt index d7dd8d9253d..7ee0af5c475 100644 --- a/compiler/testData/diagnostics/tests/generics/Projections.kt +++ b/compiler/testData/diagnostics/tests/generics/Projections.kt @@ -36,13 +36,13 @@ fun testInOut() { Inv().f(1) (null as Inv).f(1) - (null as Inv).f(1) // !! - (null as Inv<*>).f(1) // !! + (null as Inv).f(1) // !! + (null as Inv<*>).f(1) // !! Inv().inf(1) (null as Inv).inf(1) - (null as Inv).inf(1) // !! - (null as Inv<*>).inf(1) // !! + (null as Inv).inf(1) // !! + (null as Inv<*>).inf(1) // !! Inv().outf() checkSubtype((null as Inv).outf()) // Type mismatch diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/simpleOutUseSite.kt b/compiler/testData/diagnostics/tests/generics/innerClasses/simpleOutUseSite.kt index cd486f63f12..76e834d15c0 100644 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/simpleOutUseSite.kt +++ b/compiler/testData/diagnostics/tests/generics/innerClasses/simpleOutUseSite.kt @@ -28,10 +28,9 @@ fun main() { checkSubtype.Inner>(outer.bar()) checkSubtype.Inner>(outer.Inner()) - // Should not actually work as in Java (captured constructor type mismatch) - outer.set(outer.bar()) - outer.set(outer.Inner()) + outer.set(.Inner)!>outer.bar()) + outer.set(.Inner)!>outer.Inner()) val x: Outer.Inner = factoryString() - outer.set(x) + outer.set(.Inner)!>x) } diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/MLOut.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/MLOut.kt new file mode 100644 index 00000000000..8f573bce36f --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/MLOut.kt @@ -0,0 +1,18 @@ +// !CHECK_TYPE + +// FILE: A.java +public class A { + public java.util.List foo() {} +} + +// FILE: main.kt + +fun foo2(x: A, y: MutableList) { + x.foo().isEmpty() + x.foo().get(0) checkType { _() } + x.foo().iterator() checkType { _>() } + + y.isEmpty() + y.get(0) checkType { _() } + y.iterator() checkType { _>() } +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/MLOut.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/MLOut.txt new file mode 100644 index 00000000000..d27266c8fd0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/MLOut.txt @@ -0,0 +1,11 @@ +package + +public fun foo2(/*0*/ x: A, /*1*/ y: kotlin.MutableList): 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 fun foo(): (kotlin.MutableList..kotlin.List?) + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/addAll.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/addAll.kt new file mode 100644 index 00000000000..e6e4396601b --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/addAll.kt @@ -0,0 +1,27 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +interface C +interface MC : C { + fun addAll(x: C): Boolean + fun addAllMC(x: MC): Boolean +} + +interface Open +class Derived : Open + +fun mc(): MC = null!! +fun c(): C = null!! + +fun foo(x: MC) { + x.addAll(; MC)!>x) + x.addAllMC(; MC)!>x) + + x.addAll(; MC)!>mc()) + x.addAllMC(; MC)!>mc()) + + x.addAll(; MC)!>mc()) + x.addAllMC(; MC)!>mc()) + + x.addAll(c()) + x.addAll(c()) +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/addAll.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/addAll.txt new file mode 100644 index 00000000000..ae151570fd4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/addAll.txt @@ -0,0 +1,32 @@ +package + +public fun c(): C +public fun foo(/*0*/ x: MC): kotlin.Unit +public fun mc(): MC + +public interface C { + 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 +} + +public final class Derived : Open { + public constructor Derived() + 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 +} + +public interface MC : C { + public abstract fun addAll(/*0*/ x: C): kotlin.Boolean + public abstract fun addAllMC(/*0*/ x: MC): kotlin.Boolean + 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 +} + +public interface Open { + 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 +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/extensionResultSubstitution.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/extensionResultSubstitution.kt new file mode 100644 index 00000000000..a200e8f6eee --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/extensionResultSubstitution.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class A { + fun foo() = 1 +} + +interface B + +public fun E.bar() : A = null!! + +fun baz(x: B) { + x.bar().foo() +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/extensionResultSubstitution.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/extensionResultSubstitution.txt new file mode 100644 index 00000000000..2203ce4ed67 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/extensionResultSubstitution.txt @@ -0,0 +1,18 @@ +package + +public fun baz(/*0*/ x: B): kotlin.Unit +public fun E.bar(): A + +public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun foo(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface B { + 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 +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.kt new file mode 100644 index 00000000000..4f8daf124d9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.kt @@ -0,0 +1,14 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE +// !CHECK_TYPE +import java.util.ArrayList + +class ListOfLists(public val x : ArrayList>) + +fun main(args : Array) { + val a : ArrayList> = ArrayList() + val b : ListOfLists = ListOfLists(a) + val c : ListOfLists<*> = b + val d : ArrayList> = c.x + + c.x checkType { _>>() } +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.txt new file mode 100644 index 00000000000..9e283e3e56e --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.txt @@ -0,0 +1,11 @@ +package + +public fun main(/*0*/ args: kotlin.Array): kotlin.Unit + +public final class ListOfLists { + public constructor ListOfLists(/*0*/ x: java.util.ArrayList>) + public final val x: java.util.ArrayList> + 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 +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/kt8647.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/kt8647.kt new file mode 100644 index 00000000000..0873de21fd3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/kt8647.kt @@ -0,0 +1,8 @@ +interface Subscriber + +interface Observable { + fun subscribe(s: Subscriber) +} + +fun foo(o: Observable, y: Subscriber) = o.subscribe(y) // type safe + diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/kt8647.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/kt8647.txt new file mode 100644 index 00000000000..5655ea25147 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/kt8647.txt @@ -0,0 +1,16 @@ +package + +public fun foo(/*0*/ o: Observable, /*1*/ y: Subscriber): kotlin.Unit + +public interface Observable { + 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 abstract fun subscribe(/*0*/ s: Subscriber): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface Subscriber { + 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 +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/lambdaArgument.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/lambdaArgument.kt new file mode 100644 index 00000000000..8a6cf24aa9f --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/lambdaArgument.kt @@ -0,0 +1,16 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !CHECK_TYPE + +class A { + fun foo(f: (T) -> Unit) {} +} + +fun test(a: A, b: A) { + a.foo { + it checkType { _() } + } + + b.foo { + it checkType { _() } + } +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/lambdaArgument.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/lambdaArgument.txt new file mode 100644 index 00000000000..c4a9a5bb2e4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/lambdaArgument.txt @@ -0,0 +1,11 @@ +package + +public fun test(/*0*/ a: A, /*1*/ b: A): kotlin.Unit + +public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun foo(/*0*/ f: (T) -> kotlin.Unit): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/recursiveUpperBoundStar.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/recursiveUpperBoundStar.kt new file mode 100644 index 00000000000..2fbe845857a --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/recursiveUpperBoundStar.kt @@ -0,0 +1,10 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// See KT-7296 +interface A +interface B : A> + +fun foo(x : B<*>) { + bar(x) // this should not be valid +} + +fun bar(x : A>) { } diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/recursiveUpperBoundStar.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/recursiveUpperBoundStar.txt new file mode 100644 index 00000000000..cd0f39dae8b --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/recursiveUpperBoundStar.txt @@ -0,0 +1,16 @@ +package + +public fun bar(/*0*/ x: A>): kotlin.Unit +public fun foo(/*0*/ x: B<*>): kotlin.Unit + +public interface 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 +} + +public interface B : 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 +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullability.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullability.kt new file mode 100644 index 00000000000..d2fa6b9320e --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullability.kt @@ -0,0 +1,16 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !CHECK_TYPE +// See KT-9893 +open class A + +public interface I { + public fun foo(): T? +} + +fun acceptA(a: A) { +} + +fun main(i: I<*>) { + i.foo() checkType { _() } + acceptA(i.foo()) // i.foo() should be nullable but isn't +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullability.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullability.txt new file mode 100644 index 00000000000..c7bde7be8d7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullability.txt @@ -0,0 +1,18 @@ +package + +public fun acceptA(/*0*/ a: A): kotlin.Unit +public fun main(/*0*/ i: I<*>): 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 +} + +public interface I { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(): T? + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullabilityRecursive.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullabilityRecursive.kt new file mode 100644 index 00000000000..2b1566a3263 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullabilityRecursive.kt @@ -0,0 +1,8 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// !CHECK_TYPE +interface A?> { + fun foo(): T? +} +fun testA(a: A<*>) { + a.foo() checkType { _?>() } +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullabilityRecursive.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullabilityRecursive.txt new file mode 100644 index 00000000000..56b19f16002 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/starNullabilityRecursive.txt @@ -0,0 +1,10 @@ +package + +public fun testA(/*0*/ a: A<*>): kotlin.Unit + +public interface A?> { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(): T? + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/superClass.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/superClass.kt new file mode 100644 index 00000000000..5acc03145cd --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/superClass.kt @@ -0,0 +1,12 @@ +// !CHECK_TYPE + +interface Clazz { + val t: T + fun getSuperClass(): Clazz +} + +fun test(clazz: Clazz<*>) { + clazz.t checkType { _() } + clazz.getSuperClass() checkType { _>() } + clazz.getSuperClass().t checkType { _() } +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/superClass.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/superClass.txt new file mode 100644 index 00000000000..3efbf66519a --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/superClass.txt @@ -0,0 +1,11 @@ +package + +public fun test(/*0*/ clazz: Clazz<*>): kotlin.Unit + +public interface Clazz { + public abstract val t: T + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun getSuperClass(): Clazz + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.kt new file mode 100644 index 00000000000..653a6e9875e --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.kt @@ -0,0 +1,43 @@ +// !CHECK_TYPE +// !DIAGNOSTICS: -UNUSED_PARAMETER + +class Out +class In +class Inv + +class A { + fun > foo1(x: E) = 1 + fun > foo2(x: F) = 1 + fun > foo3(x: G) = 1 +} + +fun foo2(a: A, b: A) { + a.foo1(Out()) + a.foo1<Out>(Out()) + + a.foo1(Out()) + a.foo1(Out()) + + a.foo2(Inv()) + a.foo2(Inv()) + a.foo2<Inv>(Inv()) + + a.foo3(In()) + a.foo3(In()) + a.foo3>(In()) + + b.foo1(Out()) + b.foo1(Out()) + b.foo1>(Out()) + + b.foo2(Inv()) + b.foo2(Inv()) + b.foo2<Inv>(Inv()) + + + b.foo3(In()) + b.foo3<In>(In()) + + b.foo3(In()) + b.foo3(In()) +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.txt new file mode 100644 index 00000000000..9bdec591019 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.txt @@ -0,0 +1,34 @@ +package + +public fun foo2(/*0*/ a: A, /*1*/ b: A): kotlin.Unit + +public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final fun > foo1(/*0*/ x: E): kotlin.Int + public final fun > foo2(/*0*/ x: F): kotlin.Int + public final fun > foo3(/*0*/ x: G): kotlin.Int + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public final class In { + public constructor In() + 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 +} + +public final class Inv { + public constructor Inv() + 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 +} + +public final class Out { + public constructor Out() + 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 +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.kt b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.kt new file mode 100644 index 00000000000..c310b307b1b --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.kt @@ -0,0 +1,9 @@ + +interface A { + fun foo(x: @UnsafeVariance K): Unit +} + +fun test(a: A<*>) { + a.foo(null) + a.foo(Any()) +} diff --git a/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.txt b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.txt new file mode 100644 index 00000000000..ee021c9b089 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.txt @@ -0,0 +1,10 @@ +package + +public fun test(/*0*/ a: A<*>): kotlin.Unit + +public interface A { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract fun foo(/*0*/ x: @kotlin.UnsafeVariance() K): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/inference/capturedTypes/memberScopeOfCaptured.kt b/compiler/testData/diagnostics/tests/inference/capturedTypes/memberScopeOfCaptured.kt index 08aada3de83..4fa525294fa 100644 --- a/compiler/testData/diagnostics/tests/inference/capturedTypes/memberScopeOfCaptured.kt +++ b/compiler/testData/diagnostics/tests/inference/capturedTypes/memberScopeOfCaptured.kt @@ -7,5 +7,6 @@ class A { fun A.bar(): A = this fun baz(x: A) { + x.bar() checkType { _>() } x.bar().foo() checkType { _() } // See KT-10448 } diff --git a/compiler/testData/diagnostics/tests/j+k/arrayOfStarParametrized.kt b/compiler/testData/diagnostics/tests/j+k/arrayOfStarParametrized.kt new file mode 100644 index 00000000000..79debb0c3f1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/arrayOfStarParametrized.kt @@ -0,0 +1,14 @@ +// !CHECK_TYPE + +// FILE: A.java +public class A { + public A[] baz() { return null; } +} + + +// FILE: main.kt + +fun foo1(x: A<*>) = x.baz() +fun foo2(x: A<*>) { + x.baz() checkType { _>>() } +} diff --git a/compiler/testData/diagnostics/tests/j+k/arrayOfStarParametrized.txt b/compiler/testData/diagnostics/tests/j+k/arrayOfStarParametrized.txt new file mode 100644 index 00000000000..65ad05bf908 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/arrayOfStarParametrized.txt @@ -0,0 +1,12 @@ +package + +public fun foo1(/*0*/ x: A<*>): kotlin.Array> +public fun foo2(/*0*/ x: A<*>): kotlin.Unit + +public open class A { + public constructor A() + public open fun baz(): kotlin.Array<(out) 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 +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/addAllProjection.kt b/compiler/testData/diagnostics/testsWithStdLib/addAllProjection.kt new file mode 100644 index 00000000000..f9445104988 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/addAllProjection.kt @@ -0,0 +1,13 @@ +fun test(mc: MutableCollection) { + mc.addAll(mc) + + mc.addAll(arrayListOf()) + mc.addAll(arrayListOf()) + + mc.addAll(listOf("")) + mc.addAll(listOf("")) + mc.addAll(listOf("")) + + mc.addAll(emptyList()) + mc.addAll(emptyList()) +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/addAllProjection.txt b/compiler/testData/diagnostics/testsWithStdLib/addAllProjection.txt new file mode 100644 index 00000000000..5ea8d2e45c8 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/addAllProjection.txt @@ -0,0 +1,3 @@ +package + +public fun test(/*0*/ mc: kotlin.MutableCollection): kotlin.Unit diff --git a/compiler/testData/resolve/Projections.resolve b/compiler/testData/resolve/Projections.resolve index 449219ea108..3831c12fdda 100644 --- a/compiler/testData/resolve/Projections.resolve +++ b/compiler/testData/resolve/Projections.resolve @@ -18,13 +18,13 @@ class Inv() { fun testInOut() { In().`In.f:T->Unit`f("1"); (return as In).`In.f:T->Unit`f("1"); - (return as In).`In.f:Int->Int`f("1") - (return as In<*>).`In.f:Int->Int`f("1"); + (return as In).`In.f:T->Unit`f("1") + (return as In<*>).`In.f:T->Unit`f("1"); In().`In.f:Int->Int`f(1); (return as In).`In.f:Int->Int`f(1); (return as In).`In.f:Int->Int`f(1) - (return as In).`!`f1(1) + (return as In).`In.f1`f1(1) (return as In<*>).`In.f:Int->Int`f(1); Out().`Out.f(a)`f(1) @@ -39,13 +39,13 @@ fun testInOut() { Inv().`Inv.f`f(1) (return as Inv).`Inv.f`f(1) - (return as Inv).`!`f(1) - (return as Inv<*>).`!`f(1) + (return as Inv).`Inv.f`f(1) + (return as Inv<*>).`Inv.f`f(1) Inv().`Inv.inf`inf(1) (return as Inv).`Inv.inf`inf(1) - (return as Inv).`!`inf(1) - (return as Inv<*>).`!`inf(1) + (return as Inv).`Inv.inf`inf(1) + (return as Inv<*>).`Inv.inf`inf(1) Inv().`Inv.outf`outf() ((return as Inv).`Inv.outf`outf())`:kotlin::Any` diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 12074d84893..4c48eb0b875 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -7116,6 +7116,87 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { } } + @TestMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ProjectionsScope extends AbstractDiagnosticsTest { + @TestMetadata("addAll.kt") + public void testAddAll() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/addAll.kt"); + doTest(fileName); + } + + public void testAllFilesPresentInProjectionsScope() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/generics/projectionsScope"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("extensionResultSubstitution.kt") + public void testExtensionResultSubstitution() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/extensionResultSubstitution.kt"); + doTest(fileName); + } + + @TestMetadata("kt7296.kt") + public void testKt7296() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/kt7296.kt"); + doTest(fileName); + } + + @TestMetadata("kt8647.kt") + public void testKt8647() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/kt8647.kt"); + doTest(fileName); + } + + @TestMetadata("lambdaArgument.kt") + public void testLambdaArgument() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/lambdaArgument.kt"); + doTest(fileName); + } + + @TestMetadata("MLOut.kt") + public void testMLOut() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/MLOut.kt"); + doTest(fileName); + } + + @TestMetadata("recursiveUpperBoundStar.kt") + public void testRecursiveUpperBoundStar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/recursiveUpperBoundStar.kt"); + doTest(fileName); + } + + @TestMetadata("starNullability.kt") + public void testStarNullability() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/starNullability.kt"); + doTest(fileName); + } + + @TestMetadata("starNullabilityRecursive.kt") + public void testStarNullabilityRecursive() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/starNullabilityRecursive.kt"); + doTest(fileName); + } + + @TestMetadata("superClass.kt") + public void testSuperClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/superClass.kt"); + doTest(fileName); + } + + @TestMetadata("typeParameterBounds.kt") + public void testTypeParameterBounds() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/typeParameterBounds.kt"); + doTest(fileName); + } + + @TestMetadata("unsafeVarianceStar.kt") + public void testUnsafeVarianceStar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/projectionsScope/unsafeVarianceStar.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/generics/starProjections") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -9447,6 +9528,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("arrayOfStarParametrized.kt") + public void testArrayOfStarParametrized() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/arrayOfStarParametrized.kt"); + doTest(fileName); + } + @TestMetadata("canDeclareIfSamAdapterIsInherited.kt") public void testCanDeclareIfSamAdapterIsInherited() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/j+k/canDeclareIfSamAdapterIsInherited.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java index 84365996d30..f45f25ad3b4 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithStdLibGenerated.java @@ -31,6 +31,12 @@ import java.util.regex.Pattern; @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestWithStdLib { + @TestMetadata("addAllProjection.kt") + public void testAddAllProjection() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/addAllProjection.kt"); + doTest(fileName); + } + public void testAllFilesPresentInTestsWithStdLib() throws Exception { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib"), Pattern.compile("^(.+)\\.kt$"), true); } diff --git a/compiler/tests/org/jetbrains/kotlin/resolve/typeApproximation/CapturedTypeApproximationTest.kt b/compiler/tests/org/jetbrains/kotlin/resolve/typeApproximation/CapturedTypeApproximationTest.kt index 290ec111629..1d3b8a5b059 100644 --- a/compiler/tests/org/jetbrains/kotlin/resolve/typeApproximation/CapturedTypeApproximationTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/resolve/typeApproximation/CapturedTypeApproximationTest.kt @@ -16,26 +16,25 @@ package org.jetbrains.kotlin.resolve.typeApproximation -import org.jetbrains.kotlin.test.KotlinLiteFixture import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.test.ConfigurationKind -import java.io.File -import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.diagnostics.Severity +import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.resolve.calls.inference.createCapturedType +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform +import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil +import org.jetbrains.kotlin.test.ConfigurationKind +import org.jetbrains.kotlin.test.KotlinLiteFixture +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.types.TypeProjection import org.jetbrains.kotlin.types.TypeProjectionImpl -import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.Variance.* import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes -import org.jetbrains.kotlin.test.KotlinTestUtils -import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.resolve.calls.inference.createCapturedType -import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypesIfNecessary -import java.util.ArrayList -import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform +import java.io.File +import java.util.* public class CapturedTypeApproximationTest() : KotlinLiteFixture() { @@ -85,7 +84,7 @@ public class CapturedTypeApproximationTest() : KotlinLiteFixture() { fun createTestSubstitutor(testSubstitution: Map): TypeSubstitutor { val substitutionContext = testSubstitution.map { val (typeParameter, typeProjection) = it - typeParameter.getTypeConstructor() to TypeProjectionImpl(createCapturedType(typeProjection)) + typeParameter.typeConstructor to TypeProjectionImpl(createCapturedType(typeProjection)) }.toMap() return TypeSubstitutor.create(substitutionContext) } @@ -111,7 +110,9 @@ public class CapturedTypeApproximationTest() : KotlinLiteFixture() { val typeWithCapturedType = typeSubstitutor.substituteWithoutApproximation(TypeProjectionImpl(INVARIANT, type!!))!!.getType() val (lower, upper) = approximateCapturedTypes(typeWithCapturedType) - val substitution = approximateCapturedTypesIfNecessary(TypeProjectionImpl(INVARIANT, typeWithCapturedType)) + val substitution = + approximateCapturedTypesIfNecessary( + TypeProjectionImpl(INVARIANT, typeWithCapturedType), approximateContravariant = false) append(" ") for (typeParameter in testSubstitution.keySet()) { diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractReceiverParameterDescriptor.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractReceiverParameterDescriptor.java index 6e21f769200..5fc23f14821 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractReceiverParameterDescriptor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractReceiverParameterDescriptor.java @@ -41,7 +41,20 @@ public abstract class AbstractReceiverParameterDescriptor extends DeclarationDes @Override public ReceiverParameterDescriptor substitute(@NotNull TypeSubstitutor substitutor) { if (substitutor.isEmpty()) return this; - KotlinType substitutedType = substitutor.substitute(getType(), Variance.INVARIANT); + + KotlinType substitutedType; + if (getContainingDeclaration() instanceof ClassDescriptor) { + // Due to some reasons we check that receiver value type is a subtype of dispatch parameter + // (although we get members exactly from it's scope) + // So to make receiver with projections be a subtype of parameter's type with captured type arguments, + // we approximate latter to it's upper bound. + // See approximateDispatchReceiver.kt test for clarification + substitutedType = substitutor.substitute(getType(), Variance.OUT_VARIANCE); + } + else { + substitutedType = substitutor.substitute(getType(), Variance.INVARIANT); + } + if (substitutedType == null) return null; return new ReceiverParameterDescriptorImpl(getContainingDeclaration(), new TransientReceiver(substitutedType)); diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt index 5e43fee276a..d2e419ec1f6 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt @@ -96,3 +96,34 @@ public class CapturedType( public fun createCapturedType(typeProjection: TypeProjection): KotlinType = CapturedType(typeProjection) public fun KotlinType.isCaptured(): Boolean = getConstructor() is CapturedTypeConstructor + +public fun TypeSubstitution.wrapWithCapturingSubstitution(): TypeSubstitution = + if (this is IndexedParametersSubstitution) + IndexedParametersSubstitution( + this.parameters, + this.arguments.zip(this.parameters).map { + it.first.createCapturedIfNeeded(it.second) + }.toTypedArray(), + approximateCapturedTypes = true) + else + object : DelegatedTypeSubstitution(this@wrapWithCapturingSubstitution) { + override fun approximateContravariantCapturedTypes() = true + override fun get(key: KotlinType) = super.get(key)?.createCapturedIfNeeded(key.constructor.declarationDescriptor as? TypeParameterDescriptor) + } + +private fun TypeProjection.createCapturedIfNeeded(typeParameterDescriptor: TypeParameterDescriptor?): TypeProjection { + if (typeParameterDescriptor == null || projectionKind == Variance.INVARIANT) return this + + // Treat consistent projections as invariant + if (typeParameterDescriptor.variance == projectionKind) { + // TODO: Make star projection type lazy + return if (isStarProjection) + TypeProjectionImpl(object : DelegatingType() { + override fun getDelegate() = this@createCapturedIfNeeded.type + }) + else + TypeProjectionImpl(this@createCapturedIfNeeded.type) + } + + return TypeProjectionImpl(createCapturedType(this)) +} diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/SubstitutingScope.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/SubstitutingScope.kt index c20546dc2bf..f3624eb84cb 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/SubstitutingScope.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/scopes/SubstitutingScope.kt @@ -19,29 +19,37 @@ package org.jetbrains.kotlin.resolve.scopes import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.calls.inference.wrapWithCapturingSubstitution import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.newHashSetWithExpectedSize +import org.jetbrains.kotlin.utils.sure import java.util.* -public class SubstitutingScope(private val workerScope: MemberScope, private val substitutor: TypeSubstitutor) : MemberScope { +public class SubstitutingScope(private val workerScope: MemberScope, givenSubstitutor: TypeSubstitutor) : MemberScope { - private var substitutedDescriptors: MutableMap? = null + private val substitutor = givenSubstitutor.substitution.wrapWithCapturingSubstitution().buildSubstitutor() + + private var substitutedDescriptors: MutableMap? = null private val _allDescriptors by lazy { substitute(workerScope.getContributedDescriptors()) } - private fun substitute(descriptor: D?): D? { - if (descriptor == null) return null - if (substitutor.isEmpty()) return descriptor + private fun substitute(descriptor: D): D { + if (substitutor.isEmpty) return descriptor if (substitutedDescriptors == null) { - substitutedDescriptors = HashMap() + substitutedDescriptors = HashMap() } - val substituted = substitutedDescriptors!!.getOrPut(descriptor, { descriptor.substitute(substitutor) }) + val substituted = substitutedDescriptors!!.getOrPut(descriptor, { + descriptor.substitute(substitutor).sure { + "We expect that no conflict should happen while substitution is guaranteed to generate invariant projection, " + + "but $descriptor substitution fails" + } + }) @Suppress("UNCHECKED_CAST") - return substituted as D? + return substituted as D } private fun substitute(descriptors: Collection): Collection { @@ -51,9 +59,7 @@ public class SubstitutingScope(private val workerScope: MemberScope, private val val result = newHashSetWithExpectedSize(descriptors.size) for (descriptor in descriptors) { val substitute = substitute(descriptor) - if (substitute != null) { - result.add(substitute) - } + result.add(substitute) } return result @@ -61,7 +67,8 @@ public class SubstitutingScope(private val workerScope: MemberScope, private val override fun getContributedVariables(name: Name, location: LookupLocation) = substitute(workerScope.getContributedVariables(name, location)) - override fun getContributedClassifier(name: Name, location: LookupLocation) = substitute(workerScope.getContributedClassifier(name, location)) + override fun getContributedClassifier(name: Name, location: LookupLocation) = + workerScope.getContributedClassifier(name, location)?.let { substitute(it) } override fun getContributedFunctions(name: Name, location: LookupLocation) = substitute(workerScope.getContributedFunctions(name, location)) diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt b/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt index 56ddbafafe0..8e75ca5d6d4 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/CapturedTypeApproximation.kt @@ -59,7 +59,7 @@ private fun TypeProjection.toTypeArgument(typeParameter: TypeParameterDescriptor Variance.OUT_VARIANCE -> TypeArgument(typeParameter, typeParameter.builtIns.nothingType, type) } -public fun approximateCapturedTypesIfNecessary(typeProjection: TypeProjection?): TypeProjection? { +public fun approximateCapturedTypesIfNecessary(typeProjection: TypeProjection?, approximateContravariant: Boolean): TypeProjection? { if (typeProjection == null) return null if (typeProjection.isStarProjection()) return typeProjection @@ -73,10 +73,17 @@ public fun approximateCapturedTypesIfNecessary(typeProjection: TypeProjection?): val approximation = approximateCapturedTypes(type) return TypeProjectionImpl(howThisTypeIsUsed, approximation.upper) } - return substituteCapturedTypes(typeProjection) + + if (approximateContravariant) { + // TODO: assert that howThisTypeIsUsed is always IN + val approximation = approximateCapturedTypes(type).lower + return TypeProjectionImpl(howThisTypeIsUsed, approximation) + } + + return substituteCapturedTypesWithProjections(typeProjection) } -private fun substituteCapturedTypes(typeProjection: TypeProjection): TypeProjection? { +private fun substituteCapturedTypesWithProjections(typeProjection: TypeProjection): TypeProjection? { val typeSubstitutor = TypeSubstitutor.create(object : TypeConstructorSubstitution() { override fun get(key: TypeConstructor): TypeProjection? { return (key as? CapturedTypeConstructor)?.typeProjection diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java b/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java index 8b95525aa36..bee202cf7b5 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/DescriptorSubstitutor.java @@ -67,7 +67,7 @@ public class DescriptorSubstitutor { for (TypeParameterDescriptor descriptor : typeParameters) { TypeParameterDescriptorImpl substituted = substitutedMap.get(descriptor); for (KotlinType upperBound : descriptor.getUpperBounds()) { - KotlinType substitutedBound = substitutor.substitute(upperBound, Variance.INVARIANT); + KotlinType substitutedBound = substitutor.substitute(upperBound, Variance.IN_VARIANCE); assert substitutedBound != null : "Upper bound failed to substitute: " + descriptor; substituted.addUpperBound(substitutedBound); } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/DisjointKeysUnionTypeSubstitution.kt b/core/descriptors/src/org/jetbrains/kotlin/types/DisjointKeysUnionTypeSubstitution.kt index cae2f445a01..2e6b33ab691 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/DisjointKeysUnionTypeSubstitution.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/DisjointKeysUnionTypeSubstitution.kt @@ -37,6 +37,7 @@ public class DisjointKeysUnionTypeSubstitution private constructor( override fun isEmpty() = false override fun approximateCapturedTypes() = first.approximateCapturedTypes() || second.approximateCapturedTypes() + override fun approximateContravariantCapturedTypes() = first.approximateContravariantCapturedTypes() || second.approximateContravariantCapturedTypes() override fun filterAnnotations(annotations: Annotations) = second.filterAnnotations(first.filterAnnotations(annotations)) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt index 9e8edd10e97..df7efd01394 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitution.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.types +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotations @@ -34,6 +35,7 @@ public abstract class TypeSubstitution { open fun isEmpty(): Boolean = false open fun approximateCapturedTypes(): Boolean = false + open fun approximateContravariantCapturedTypes(): Boolean = false open fun filterAnnotations(annotations: Annotations) = annotations @@ -73,9 +75,10 @@ public abstract class TypeConstructorSubstitution : TypeSubstitution() { } } -public class IndexedParametersSubstitution private constructor( - private val parameters: Array, - private val arguments: Array +public class IndexedParametersSubstitution( + val parameters: Array, + val arguments: Array, + private val approximateCapturedTypes: Boolean = false ) : TypeSubstitution() { init { assert(parameters.size() <= arguments.size()) { @@ -89,6 +92,8 @@ public class IndexedParametersSubstitution private constructor( override fun isEmpty(): Boolean = arguments.isEmpty() + override fun approximateContravariantCapturedTypes() = approximateCapturedTypes + override fun get(key: KotlinType): TypeProjection? { val parameter = key.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return null val index = parameter.index @@ -164,6 +169,7 @@ private class CompositeTypeSubstitution( override fun isEmpty() = first.isEmpty() && second.isEmpty() override fun approximateCapturedTypes() = first.approximateCapturedTypes() || second.approximateCapturedTypes() + override fun approximateContravariantCapturedTypes() = first.approximateContravariantCapturedTypes() || second.approximateContravariantCapturedTypes() override fun filterAnnotations(annotations: Annotations): Annotations = second.filterAnnotations(first.filterAnnotations(annotations)) } @@ -174,6 +180,7 @@ public open class DelegatedTypeSubstitution(val substitution: TypeSubstitution): override fun isEmpty() = substitution.isEmpty() override fun approximateCapturedTypes() = substitution.approximateCapturedTypes() + override fun approximateContravariantCapturedTypes() = substitution.approximateContravariantCapturedTypes() override fun filterAnnotations(annotations: Annotations) = substitution.filterAnnotations(annotations) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java index 4eb64f46bd0..ba94ab40418 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSubstitutor.java @@ -104,10 +104,11 @@ public class TypeSubstitutor { @Nullable public TypeProjection substitute(@NotNull TypeProjection typeProjection) { TypeProjection substitutedTypeProjection = substituteWithoutApproximation(typeProjection); - if (!substitution.approximateCapturedTypes()) { + if (!substitution.approximateCapturedTypes() && !substitution.approximateContravariantCapturedTypes()) { return substitutedTypeProjection; } - return CapturedTypeApproximationKt.approximateCapturedTypesIfNecessary(substitutedTypeProjection); + return CapturedTypeApproximationKt.approximateCapturedTypesIfNecessary( + substitutedTypeProjection, substitution.approximateContravariantCapturedTypes()); } @Nullable diff --git a/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt b/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt index 07fc8d2dbf5..137f6ab5feb 100644 --- a/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt +++ b/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt @@ -1,4 +1,4 @@ -// PARAM_TYPES: kotlin.Array, kotlin.Cloneable, java.io.Serializable, Any +// PARAM_TYPES: kotlin.Array, Cloneable, java.io.Serializable, Any // PARAM_DESCRIPTOR: public fun kotlin.Array.test(): kotlin.Unit defined in root package // SIBLING: fun Array.test() { diff --git a/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt.after b/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt.after index 4c616909b0c..28c2bf2be88 100644 --- a/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt.after +++ b/idea/testData/refactoring/extractFunction/basic/extensionFunForArray.kt.after @@ -1,4 +1,4 @@ -// PARAM_TYPES: kotlin.Array, kotlin.Cloneable, java.io.Serializable, Any +// PARAM_TYPES: kotlin.Array, Cloneable, java.io.Serializable, Any // PARAM_DESCRIPTOR: public fun kotlin.Array.test(): kotlin.Unit defined in root package // SIBLING: fun Array.test() { diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt index 21ebbc873ff..e667142210f 100644 --- a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt @@ -1,4 +1,4 @@ -// PARAM_TYPES: kotlin.String, Comparable, CharSequence, java.io.Serializable, kotlin.Any +// PARAM_TYPES: kotlin.String, Comparable, CharSequence, java.io.Serializable, Any // PARAM_TYPES: X // PARAM_DESCRIPTOR: value-parameter val s: kotlin.String? defined in foo // PARAM_DESCRIPTOR: value-parameter val x: X defined in foo diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt.after b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt.after index ce94a04332e..69cbddd4a7a 100644 --- a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/nonNullableTypes.kt.after @@ -1,4 +1,4 @@ -// PARAM_TYPES: kotlin.String, Comparable, CharSequence, java.io.Serializable, kotlin.Any +// PARAM_TYPES: kotlin.String, Comparable, CharSequence, java.io.Serializable, Any // PARAM_TYPES: X // PARAM_DESCRIPTOR: value-parameter val s: kotlin.String? defined in foo // PARAM_DESCRIPTOR: value-parameter val x: X defined in foo diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/qualifiedThis.kt b/idea/testData/refactoring/extractFunction/parameters/extractThis/qualifiedThis.kt index df0398e9cf8..ee309db23a8 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/qualifiedThis.kt +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/qualifiedThis.kt @@ -1,4 +1,4 @@ -// PARAM_TYPES: kotlin.String, Comparable, CharSequence, java.io.Serializable, kotlin.Any +// PARAM_TYPES: kotlin.String, Comparable, CharSequence, java.io.Serializable, Any // PARAM_DESCRIPTOR: public fun kotlin.String.test(): kotlin.Unit defined in root package fun String.foo(f: () -> Unit) { f() diff --git a/idea/testData/refactoring/extractFunction/parameters/extractThis/qualifiedThis.kt.after b/idea/testData/refactoring/extractFunction/parameters/extractThis/qualifiedThis.kt.after index ac6491623bf..b91e5d14cf0 100644 --- a/idea/testData/refactoring/extractFunction/parameters/extractThis/qualifiedThis.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/extractThis/qualifiedThis.kt.after @@ -1,4 +1,4 @@ -// PARAM_TYPES: kotlin.String, Comparable, CharSequence, java.io.Serializable, kotlin.Any +// PARAM_TYPES: kotlin.String, Comparable, CharSequence, java.io.Serializable, Any // PARAM_DESCRIPTOR: public fun kotlin.String.test(): kotlin.Unit defined in root package fun String.foo(f: () -> Unit) { f()