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
@@ -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
}