Refine member scope for types with projections

Instead of erasing descriptors with conflicting substitution,
use invariant CapturedType(<projection>) as replacement for type parameter
within default member scope.

After substitution leave such types 'as is' everywhere except return types,
use common approximation for them.

 #KT-9294 In Progress
 #KT-5411 Fixed
 #KT-8647 Fixed

 #KT-9462 Fixed
 #KT-9893 Fixed
 #KT-7581 Fixed
 #KT-7296 In Progress
This commit is contained in:
Denis Zharkov
2015-12-22 14:02:55 +03:00
parent 365ff593f3
commit e2c02f825f
50 changed files with 655 additions and 60 deletions
@@ -2,5 +2,5 @@
fun foo() {
val f : Function1<*, *> = { x -> x.toString() }
<!FUNCTION_EXPECTED, UNUSED_EXPRESSION!>f<!>(1)
f(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
}
@@ -36,13 +36,13 @@ fun testInOut() {
Inv<Int>().f(1)
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<in Int>).f(1)
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).<!UNRESOLVED_REFERENCE!>f<!>(1) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).<!UNRESOLVED_REFERENCE!>f<!>(1) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).f(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).f(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) // !!
Inv<Int>().inf(1)
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<in Int>).inf(1)
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).<!UNRESOLVED_REFERENCE!>inf<!>(1) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).<!UNRESOLVED_REFERENCE!>inf<!>(1) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).inf(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).inf(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) // !!
Inv<Int>().outf()
checkSubtype<Int>(<!TYPE_MISMATCH!>(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<in Int>).outf()<!>) // Type mismatch
@@ -28,10 +28,9 @@ fun main() {
checkSubtype<Outer<out CharSequence>.Inner>(outer.bar())
checkSubtype<Outer<out CharSequence>.Inner>(outer.Inner())
// Should not actually work as in Java (captured constructor type mismatch)
outer.set(outer.bar())
outer.set(outer.Inner())
outer.set(<!TYPE_MISMATCH(kotlin.Nothing; Outer<out kotlin.String>.Inner)!>outer.bar()<!>)
outer.set(<!TYPE_MISMATCH(kotlin.Nothing; Outer<out kotlin.String>.Inner)!>outer.Inner()<!>)
val x: Outer<String>.Inner = factoryString()
outer.set(x)
outer.set(<!TYPE_MISMATCH(kotlin.Nothing; Outer<kotlin.String>.Inner)!>x<!>)
}
@@ -0,0 +1,18 @@
// !CHECK_TYPE
// FILE: A.java
public class A {
public java.util.List<? extends CharSequence> foo() {}
}
// FILE: main.kt
fun foo2(x: A, y: MutableList<out CharSequence>) {
x.foo().isEmpty()
x.foo().get(0) checkType { _<CharSequence>() }
x.foo().iterator() checkType { _<MutableIterator<CharSequence>>() }
y.isEmpty()
y.get(0) checkType { _<CharSequence>() }
y.iterator() checkType { _<MutableIterator<CharSequence>>() }
}
@@ -0,0 +1,11 @@
package
public fun foo2(/*0*/ x: A, /*1*/ y: kotlin.MutableList<out kotlin.CharSequence>): 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<out kotlin.CharSequence!>..kotlin.List<kotlin.CharSequence!>?)
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,27 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
interface C<out T>
interface MC<T> : C<T> {
fun addAll(x: C<T>): Boolean
fun addAllMC(x: MC<out T>): Boolean
}
interface Open
class Derived : Open
fun <T> mc(): MC<T> = null!!
fun <T> c(): C<T> = null!!
fun foo(x: MC<out Open>) {
x.addAll(<!TYPE_MISMATCH(C<kotlin.Nothing>; MC<out Open>)!>x<!>)
x.addAllMC(<!TYPE_MISMATCH(MC<kotlin.Nothing>; MC<out Open>)!>x<!>)
x.addAll(<!TYPE_MISMATCH(C<kotlin.Nothing>; MC<Open>)!>mc<Open>()<!>)
x.addAllMC(<!TYPE_MISMATCH(MC<kotlin.Nothing>; MC<Open>)!>mc<Open>()<!>)
x.addAll(<!TYPE_MISMATCH(C<kotlin.Nothing>; MC<Derived>)!>mc<Derived>()<!>)
x.addAllMC(<!TYPE_MISMATCH(MC<kotlin.Nothing>; MC<Derived>)!>mc<Derived>()<!>)
x.addAll(c())
x.addAll(c<Nothing>())
}
@@ -0,0 +1,32 @@
package
public fun </*0*/ T> c(): C<T>
public fun foo(/*0*/ x: MC<out Open>): kotlin.Unit
public fun </*0*/ T> mc(): MC<T>
public interface C</*0*/ out T> {
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</*0*/ T> : C<T> {
public abstract fun addAll(/*0*/ x: C<T>): kotlin.Boolean
public abstract fun addAllMC(/*0*/ x: MC<out T>): 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
}
@@ -0,0 +1,13 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A<T> {
fun foo() = 1
}
interface B
public fun <E : B> E.bar() : A<out E> = null!!
fun baz(x: B) {
x.bar().foo()
}
@@ -0,0 +1,18 @@
package
public fun baz(/*0*/ x: B): kotlin.Unit
public fun </*0*/ E : B> E.bar(): A<out E>
public final class A</*0*/ T> {
public constructor A</*0*/ T>()
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
}
@@ -0,0 +1,14 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// !CHECK_TYPE
import java.util.ArrayList
class ListOfLists<T>(public val x : ArrayList<ArrayList<T>>)
fun main(args : Array<String>) {
val a : ArrayList<ArrayList<String>> = ArrayList()
val b : ListOfLists<String> = ListOfLists(a)
val c : ListOfLists<*> = b
val d : ArrayList<ArrayList<*>> = <!TYPE_MISMATCH!>c.x<!>
c.x checkType { _<ArrayList<out ArrayList<*>>>() }
}
@@ -0,0 +1,11 @@
package
public fun main(/*0*/ args: kotlin.Array<kotlin.String>): kotlin.Unit
public final class ListOfLists</*0*/ T> {
public constructor ListOfLists</*0*/ T>(/*0*/ x: java.util.ArrayList<java.util.ArrayList<T>>)
public final val x: java.util.ArrayList<java.util.ArrayList<T>>
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
}
@@ -0,0 +1,8 @@
interface Subscriber<T>
interface Observable<T> {
fun subscribe(s: Subscriber<in T>)
}
fun foo(o: Observable<out CharSequence>, y: Subscriber<in CharSequence>) = o.subscribe(y) // type safe
@@ -0,0 +1,16 @@
package
public fun foo(/*0*/ o: Observable<out kotlin.CharSequence>, /*1*/ y: Subscriber<in kotlin.CharSequence>): kotlin.Unit
public interface Observable</*0*/ T> {
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<in T>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface Subscriber</*0*/ T> {
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
}
@@ -0,0 +1,16 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !CHECK_TYPE
class A<T> {
fun foo(f: (T) -> Unit) {}
}
fun test(a: A<out Number>, b: A<in Number>) {
a.foo {
it checkType { _<Number>() }
}
b.foo {
it checkType { _<Any?>() }
}
}
@@ -0,0 +1,11 @@
package
public fun test(/*0*/ a: A<out kotlin.Number>, /*1*/ b: A<in kotlin.Number>): kotlin.Unit
public final class A</*0*/ T> {
public constructor A</*0*/ T>()
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
}
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// See KT-7296
interface A<T>
interface B<T> : A<A<T>>
fun foo(x : B<*>) {
bar(x) // this should not be valid
}
fun bar(x : A<A<*>>) { }
@@ -0,0 +1,16 @@
package
public fun bar(/*0*/ x: A<A<*>>): kotlin.Unit
public fun foo(/*0*/ x: B<*>): kotlin.Unit
public interface A</*0*/ T> {
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</*0*/ T> : A<A<T>> {
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
}
@@ -0,0 +1,16 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !CHECK_TYPE
// See KT-9893
open class A
public interface I<T : A> {
public fun foo(): T?
}
fun acceptA(a: A) {
}
fun main(i: I<*>) {
i.foo() checkType { _<A?>() }
acceptA(<!TYPE_MISMATCH!>i.foo()<!>) // i.foo() should be nullable but isn't
}
@@ -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</*0*/ T : 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
}
@@ -0,0 +1,8 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !CHECK_TYPE
interface A<T : A<T?>?> {
fun foo(): T?
}
fun testA(a: A<*>) {
a.foo() checkType { _<A<*>?>() }
}
@@ -0,0 +1,10 @@
package
public fun testA(/*0*/ a: A<*>): kotlin.Unit
public interface A</*0*/ T : A<T?>?> {
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
}
@@ -0,0 +1,12 @@
// !CHECK_TYPE
interface Clazz<T> {
val t: T
fun getSuperClass(): Clazz<in T>
}
fun test(clazz: Clazz<*>) {
clazz.t checkType { _<Any?>() }
clazz.getSuperClass() checkType { _<Clazz<*>>() }
clazz.getSuperClass().t checkType { _<Any?>() }
}
@@ -0,0 +1,11 @@
package
public fun test(/*0*/ clazz: Clazz<*>): kotlin.Unit
public interface Clazz</*0*/ T> {
public abstract val t: T
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun getSuperClass(): Clazz<in T>
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,43 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_PARAMETER
class Out<out X>
class In<in Y>
class Inv<Z>
class A<T> {
fun <E : Out<T>> foo1(x: E) = 1
fun <F : Inv<T>> foo2(x: F) = 1
fun <G : In<T>> foo3(x: G) = 1
}
fun foo2(a: A<out CharSequence>, b: A<in CharSequence>) {
a.<!TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo1<!>(Out<CharSequence>())
a.foo1<<!UPPER_BOUND_VIOLATED!>Out<CharSequence><!>>(Out())
a.foo1(Out())
a.foo1(Out<Nothing>())
a.<!TYPE_INFERENCE_INCORPORATION_ERROR!>foo2<!>(<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Inv<!>())
a.<!TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(Inv<CharSequence>())
a.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(Inv())
a.foo3(In())
a.foo3(In<CharSequence>())
a.foo3<In<CharSequence>>(In())
b.foo1(Out())
b.foo1(Out<CharSequence>())
b.foo1<Out<CharSequence>>(Out())
b.<!TYPE_INFERENCE_INCORPORATION_ERROR!>foo2<!>(<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>Inv<!>())
b.<!TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo2<!>(Inv<CharSequence>())
b.foo2<<!UPPER_BOUND_VIOLATED!>Inv<CharSequence><!>>(Inv())
b.<!TYPE_INFERENCE_UPPER_BOUND_VIOLATED!>foo3<!>(In<CharSequence>())
b.foo3<<!UPPER_BOUND_VIOLATED!>In<CharSequence><!>>(In())
b.foo3(In<Any?>())
b.foo3(In())
}
@@ -0,0 +1,34 @@
package
public fun foo2(/*0*/ a: A<out kotlin.CharSequence>, /*1*/ b: A<in kotlin.CharSequence>): kotlin.Unit
public final class A</*0*/ T> {
public constructor A</*0*/ T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun </*0*/ E : Out<T>> foo1(/*0*/ x: E): kotlin.Int
public final fun </*0*/ F : Inv<T>> foo2(/*0*/ x: F): kotlin.Int
public final fun </*0*/ G : In<T>> 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</*0*/ in Y> {
public constructor In</*0*/ in Y>()
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</*0*/ Z> {
public constructor Inv</*0*/ Z>()
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</*0*/ out X> {
public constructor Out</*0*/ out X>()
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
}
@@ -0,0 +1,9 @@
interface A<out K> {
fun foo(x: @UnsafeVariance K): Unit
}
fun test(a: A<*>) {
a.foo(null)
a.foo(Any())
}
@@ -0,0 +1,10 @@
package
public fun test(/*0*/ a: A<*>): kotlin.Unit
public interface A</*0*/ out K> {
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
}
@@ -7,5 +7,6 @@ class A<T> {
fun <E> A<E>.bar(): A<in E> = this
fun baz(x: A<out CharSequence>) {
x.bar() checkType { _<A<*>>() }
x.bar().foo() checkType { _<Any?>() } // See KT-10448
}
@@ -0,0 +1,14 @@
// !CHECK_TYPE
// FILE: A.java
public class A<T> {
public A<T>[] baz() { return null; }
}
// FILE: main.kt
fun foo1(x: A<*>) = x.baz()
fun foo2(x: A<*>) {
x.baz() checkType { _<Array<out A<*>>>() }
}
@@ -0,0 +1,12 @@
package
public fun foo1(/*0*/ x: A<*>): kotlin.Array<out A<out kotlin.Any!>>
public fun foo2(/*0*/ x: A<*>): kotlin.Unit
public open class A</*0*/ T : kotlin.Any!> {
public constructor A</*0*/ T : kotlin.Any!>()
public open fun baz(): kotlin.Array<(out) A<T!>!>!
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
}
@@ -0,0 +1,13 @@
fun test(mc: MutableCollection<out CharSequence>) {
mc.addAll(<!TYPE_MISMATCH!>mc<!>)
mc.addAll(<!TYPE_MISMATCH!>arrayListOf<CharSequence>()<!>)
mc.addAll(arrayListOf())
mc.addAll(<!TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>listOf("")<!>)
mc.addAll(<!TYPE_MISMATCH!>listOf<String>("")<!>)
mc.addAll(<!TYPE_MISMATCH!>listOf<CharSequence>("")<!>)
mc.addAll(emptyList())
mc.addAll(emptyList<Nothing>())
}
@@ -0,0 +1,3 @@
package
public fun test(/*0*/ mc: kotlin.MutableCollection<out kotlin.CharSequence>): kotlin.Unit
+7 -7
View File
@@ -18,13 +18,13 @@ class Inv<T>() {
fun testInOut() {
In<String>().`In.f:T->Unit`f("1");
(return as In<in String>).`In.f:T->Unit`f("1");
(return as In<out String>).`In.f:Int->Int`f("1")
(return as In<*>).`In.f:Int->Int`f("1");
(return as In<out String>).`In.f:T->Unit`f("1")
(return as In<*>).`In.f:T->Unit`f("1");
In<String>().`In.f:Int->Int`f(1);
(return as In<in String>).`In.f:Int->Int`f(1);
(return as In<out String>).`In.f:Int->Int`f(1)
(return as In<out String>).`!`f1(1)
(return as In<out String>).`In.f1`f1(1)
(return as In<*>).`In.f:Int->Int`f(1);
Out<Int>().`Out.f(a)`f(1)
@@ -39,13 +39,13 @@ fun testInOut() {
Inv<Int>().`Inv.f`f(1)
(return as Inv<in Int>).`Inv.f`f(1)
(return as Inv<out Int>).`!`f(1)
(return as Inv<*>).`!`f(1)
(return as Inv<out Int>).`Inv.f`f(1)
(return as Inv<*>).`Inv.f`f(1)
Inv<Int>().`Inv.inf`inf(1)
(return as Inv<in Int>).`Inv.inf`inf(1)
(return as Inv<out Int>).`!`inf(1)
(return as Inv<*>).`!`inf(1)
(return as Inv<out Int>).`Inv.inf`inf(1)
(return as Inv<*>).`Inv.inf`inf(1)
Inv<Int>().`Inv.outf`outf()
((return as Inv<in Int>).`Inv.outf`outf())`:kotlin::Any`
@@ -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");
@@ -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);
}
@@ -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<TypeParameterDescriptor, TypeProjection>): 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()) {
@@ -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));
@@ -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))
}
@@ -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<DeclarationDescriptor, DeclarationDescriptor?>? = null
private val substitutor = givenSubstitutor.substitution.wrapWithCapturingSubstitution().buildSubstitutor()
private var substitutedDescriptors: MutableMap<DeclarationDescriptor, DeclarationDescriptor>? = null
private val _allDescriptors by lazy { substitute(workerScope.getContributedDescriptors()) }
private fun <D : DeclarationDescriptor> substitute(descriptor: D?): D? {
if (descriptor == null) return null
if (substitutor.isEmpty()) return descriptor
private fun <D : DeclarationDescriptor> substitute(descriptor: D): D {
if (substitutor.isEmpty) return descriptor
if (substitutedDescriptors == null) {
substitutedDescriptors = HashMap<DeclarationDescriptor, DeclarationDescriptor?>()
substitutedDescriptors = HashMap<DeclarationDescriptor, DeclarationDescriptor>()
}
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 <D : DeclarationDescriptor> substitute(descriptors: Collection<D>): Collection<D> {
@@ -51,9 +59,7 @@ public class SubstitutingScope(private val workerScope: MemberScope, private val
val result = newHashSetWithExpectedSize<D>(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))
@@ -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
@@ -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);
}
@@ -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))
}
@@ -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<TypeParameterDescriptor>,
private val arguments: Array<TypeProjection>
public class IndexedParametersSubstitution(
val parameters: Array<TypeParameterDescriptor>,
val arguments: Array<TypeProjection>,
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)
}
@@ -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
@@ -1,4 +1,4 @@
// PARAM_TYPES: kotlin.Array<T>, kotlin.Cloneable, java.io.Serializable, Any
// PARAM_TYPES: kotlin.Array<T>, Cloneable, java.io.Serializable, Any
// PARAM_DESCRIPTOR: public fun <T> kotlin.Array<T>.test(): kotlin.Unit defined in root package
// SIBLING:
fun <T> Array<T>.test() {
@@ -1,4 +1,4 @@
// PARAM_TYPES: kotlin.Array<T>, kotlin.Cloneable, java.io.Serializable, Any
// PARAM_TYPES: kotlin.Array<T>, Cloneable, java.io.Serializable, Any
// PARAM_DESCRIPTOR: public fun <T> kotlin.Array<T>.test(): kotlin.Unit defined in root package
// SIBLING:
fun <T> Array<T>.test() {
@@ -1,4 +1,4 @@
// PARAM_TYPES: kotlin.String, Comparable<String>, CharSequence, java.io.Serializable, kotlin.Any
// PARAM_TYPES: kotlin.String, Comparable<String>, CharSequence, java.io.Serializable, Any
// PARAM_TYPES: X<kotlin.Any>
// PARAM_DESCRIPTOR: value-parameter val s: kotlin.String? defined in foo
// PARAM_DESCRIPTOR: value-parameter val x: X<kotlin.Any> defined in foo
@@ -1,4 +1,4 @@
// PARAM_TYPES: kotlin.String, Comparable<String>, CharSequence, java.io.Serializable, kotlin.Any
// PARAM_TYPES: kotlin.String, Comparable<String>, CharSequence, java.io.Serializable, Any
// PARAM_TYPES: X<kotlin.Any>
// PARAM_DESCRIPTOR: value-parameter val s: kotlin.String? defined in foo
// PARAM_DESCRIPTOR: value-parameter val x: X<kotlin.Any> defined in foo
@@ -1,4 +1,4 @@
// PARAM_TYPES: kotlin.String, Comparable<String>, CharSequence, java.io.Serializable, kotlin.Any
// PARAM_TYPES: kotlin.String, Comparable<String>, CharSequence, java.io.Serializable, Any
// PARAM_DESCRIPTOR: public fun kotlin.String.test(): kotlin.Unit defined in root package
fun String.foo(f: () -> Unit) {
f()
@@ -1,4 +1,4 @@
// PARAM_TYPES: kotlin.String, Comparable<String>, CharSequence, java.io.Serializable, kotlin.Any
// PARAM_TYPES: kotlin.String, Comparable<String>, CharSequence, java.io.Serializable, Any
// PARAM_DESCRIPTOR: public fun kotlin.String.test(): kotlin.Unit defined in root package
fun String.foo(f: () -> Unit) {
f()