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:
+1
-1
@@ -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
|
||||
|
||||
+3
-4
@@ -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
|
||||
}
|
||||
Vendored
+13
@@ -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()
|
||||
}
|
||||
Vendored
+18
@@ -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
|
||||
}
|
||||
+16
@@ -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?>() }
|
||||
}
|
||||
}
|
||||
+11
@@ -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
|
||||
}
|
||||
+10
@@ -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<*>>) { }
|
||||
+16
@@ -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
|
||||
}
|
||||
+16
@@ -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
|
||||
}
|
||||
+18
@@ -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
|
||||
}
|
||||
+8
@@ -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<*>?>() }
|
||||
}
|
||||
+10
@@ -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
|
||||
}
|
||||
+43
@@ -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())
|
||||
}
|
||||
+34
@@ -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
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
|
||||
interface A<out K> {
|
||||
fun foo(x: @UnsafeVariance K): Unit
|
||||
}
|
||||
|
||||
fun test(a: A<*>) {
|
||||
a.foo(null)
|
||||
a.foo(Any())
|
||||
}
|
||||
+10
@@ -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
|
||||
}
|
||||
+1
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
+17
-16
@@ -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()) {
|
||||
|
||||
+14
-1
@@ -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));
|
||||
|
||||
+31
@@ -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
-1
@@ -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
-1
@@ -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
|
||||
|
||||
Vendored
+1
-1
@@ -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
-1
@@ -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
-1
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user