Humanize type mismatch diagnostic caused by type projections

#KT-10581 Fixed
This commit is contained in:
Denis Zharkov
2016-01-15 12:22:44 +03:00
parent 0c52960d7a
commit e9693e987f
60 changed files with 796 additions and 111 deletions
@@ -2,5 +2,5 @@
fun foo() {
val f : Function1<*, *> = { x -> x.toString() }
f(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
<!MEMBER_PROJECTED_OUT!>f<!>(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>).f(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).f(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).<!MEMBER_PROJECTED_OUT!>f<!>(1) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).<!MEMBER_PROJECTED_OUT!>f<!>(1) // !!
Inv<Int>().inf(1)
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<in Int>).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<!>) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<out Int>).<!MEMBER_PROJECTED_OUT!>inf<!>(1) // !!
(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<*>).<!MEMBER_PROJECTED_OUT!>inf<!>(1) // !!
Inv<Int>().outf()
checkSubtype<Int>(<!TYPE_MISMATCH!>(null <!CAST_NEVER_SUCCEEDS!>as<!> Inv<in Int>).outf()<!>) // Type mismatch
@@ -28,9 +28,9 @@ fun main() {
checkSubtype<Outer<out CharSequence>.Inner>(outer.bar())
checkSubtype<Outer<out CharSequence>.Inner>(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()<!>)
outer.<!MEMBER_PROJECTED_OUT!>set<!>(outer.bar())
outer.<!MEMBER_PROJECTED_OUT!>set<!>(outer.Inner())
val x: Outer<String>.Inner = factoryString()
outer.set(<!TYPE_MISMATCH(kotlin.Nothing; Outer<kotlin.String>.Inner)!>x<!>)
outer.<!MEMBER_PROJECTED_OUT!>set<!>(x)
}
@@ -4,6 +4,7 @@ interface C<out T>
interface MC<T> : C<T> {
fun addAll(x: C<T>): Boolean
fun addAllMC(x: MC<out T>): Boolean
fun addAllInv(x: MC<T>): Boolean
}
interface Open
@@ -13,15 +14,18 @@ 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_DUE_TO_TYPE_PROJECTIONS(C<kotlin.Nothing>; MC<out Open>; MC<out Open>; public abstract fun addAll\(x: C<T>\): kotlin.Boolean defined in MC)!>x<!>)
x.addAllMC(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS(MC<kotlin.Nothing>; MC<out Open>; MC<out Open>; public abstract fun addAllMC\(x: MC<out T>\): kotlin.Boolean defined in MC)!>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_DUE_TO_TYPE_PROJECTIONS(C<kotlin.Nothing>; MC<Open>; MC<out Open>; public abstract fun addAll\(x: C<T>\): kotlin.Boolean defined in MC)!>mc<Open>()<!>)
x.addAllMC(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS(MC<kotlin.Nothing>; MC<Open>; MC<out Open>; public abstract fun addAllMC\(x: MC<out T>\): kotlin.Boolean defined in MC)!>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(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS(C<kotlin.Nothing>; MC<Derived>; MC<out Open>; public abstract fun addAll\(x: C<T>\): kotlin.Boolean defined in MC)!>mc<Derived>()<!>)
x.addAllMC(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS(MC<kotlin.Nothing>; MC<Derived>; MC<out Open>; public abstract fun addAllMC\(x: MC<out T>\): kotlin.Boolean defined in MC)!>mc<Derived>()<!>)
x.addAll(c())
x.addAll(c<Nothing>())
x.<!MEMBER_PROJECTED_OUT!>addAllInv<!>(mc<Open>())
x.addAll(<!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!>)
}
@@ -19,6 +19,7 @@ public final class Derived : Open {
public interface MC</*0*/ T> : C<T> {
public abstract fun addAll(/*0*/ x: C<T>): kotlin.Boolean
public abstract fun addAllInv(/*0*/ x: MC<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
@@ -0,0 +1,19 @@
class A<T> {
fun T.foo() {}
fun Out<T>.bar() {}
}
class Out<out E>
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
fun test(x: A<out CharSequence>, y: Out<CharSequence>) {
with(x) {
// TODO: this diagnostic could be replaced with TYPE_MISMATCH_DUE_TO_TYPE_PROJECTION
"".<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>foo<!>()
<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>.bar()
with(y) {
<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>bar<!>()
}
}
}
@@ -0,0 +1,20 @@
package
public fun test(/*0*/ x: A<out kotlin.CharSequence>, /*1*/ y: Out<kotlin.CharSequence>): kotlin.Unit
public inline fun </*0*/ T, /*1*/ R> with(/*0*/ receiver: T, /*1*/ f: T.() -> R): R
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 open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final fun Out<T>.bar(): kotlin.Unit
public final fun T.foo(): kotlin.Unit
}
public final class Out</*0*/ out E> {
public constructor Out</*0*/ out E>()
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 A<T>
interface B<E> {
fun foo(x: A<in E>)
}
fun foo(x: B<in CharSequence>, y: A<CharSequence>) {
x.foo(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>)
}
@@ -0,0 +1,16 @@
package
public fun foo(/*0*/ x: B<in kotlin.CharSequence>, /*1*/ y: A<kotlin.CharSequence>): 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*/ E> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ x: A<in E>): 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,19 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class Out<out T>
class In<in T> {
fun invoke1(x: T) {}
fun invoke2(x: Out<T>) {}
}
interface A<E> {
fun foo(): In<E>
}
fun test(a: A<out CharSequence>, y: Out<CharSequence>) {
val i = a.foo()
// TODO: These diagnostic are wrong, type of 'i' --- 'In<Nothing>' is not projected itself,
// but it's approximation result caused by 'a' projection
i.invoke1(<!TYPE_MISMATCH!>""<!>)
i.invoke2(<!TYPE_MISMATCH!>y<!>)
}
@@ -0,0 +1,26 @@
package
public fun test(/*0*/ a: A<out kotlin.CharSequence>, /*1*/ y: Out<kotlin.CharSequence>): kotlin.Unit
public interface A</*0*/ E> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(): In<E>
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 T> {
public constructor In</*0*/ in 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 final fun invoke1(/*0*/ x: T): kotlin.Unit
public final fun invoke2(/*0*/ x: Out<T>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Out</*0*/ out T> {
public constructor Out</*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
}
@@ -0,0 +1,9 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A<T> {
fun foo(x: T, y: T) {}
}
fun test(a: A<out CharSequence>) {
a.<!MEMBER_PROJECTED_OUT!>foo<!>("", "")
}
@@ -0,0 +1,11 @@
package
public fun test(/*0*/ a: A<out 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 foo(/*0*/ x: T, /*1*/ y: T): 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,13 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A<T> {
operator fun plus(x: T): A<T> = this
operator fun set(x: Int, y: T) {}
operator fun get(x: T) = 1
}
fun test(a: A<out CharSequence>) {
a <!MEMBER_PROJECTED_OUT(public final operator fun plus\(x: T\): A<T> defined in A; A<out kotlin.CharSequence>)!>+<!> ""
<!MEMBER_PROJECTED_OUT(public final operator fun set\(x: kotlin.Int, y: T\): kotlin.Unit defined in A; A<out kotlin.CharSequence>)!>a[1]<!> = ""
<!MEMBER_PROJECTED_OUT(public final operator fun get\(x: T\): kotlin.Int defined in A; A<out kotlin.CharSequence>)!>a[""]<!>
}
@@ -0,0 +1,13 @@
package
public fun test(/*0*/ a: A<out 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 operator fun get(/*0*/ x: T): kotlin.Int
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final operator fun plus(/*0*/ x: T): A<T>
public final operator fun set(/*0*/ x: kotlin.Int, /*1*/ y: T): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,19 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A<T> {
operator fun plus(x: Out<T>): A<T> = this
operator fun set(x: Int, y: Out<T>) {}
operator fun get(x: Out<T>) = 1
}
class Out<out F>
fun test(a: A<out CharSequence>, y: Out<CharSequence>) {
a + <!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>
a[1] = <!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>
a[<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>]
a + Out<Nothing>()
a[1] = Out<Nothing>()
a[Out<Nothing>()]
}
@@ -0,0 +1,20 @@
package
public fun test(/*0*/ a: A<out kotlin.CharSequence>, /*1*/ y: Out<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 operator fun get(/*0*/ x: Out<T>): kotlin.Int
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final operator fun plus(/*0*/ x: Out<T>): A<T>
public final operator fun set(/*0*/ x: kotlin.Int, /*1*/ y: Out<T>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Out</*0*/ out F> {
public constructor Out</*0*/ out F>()
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,26 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
class Out<out T> {
fun id() = this
fun foobar(x: Any) {}
}
class A<E> {
inline fun foo(block: () -> E) {}
inline fun bar(block: () -> Out<E>) {}
}
fun test(a: A<out CharSequence>, z: Out<CharSequence>) {
a.foo {
val x: String = <!CONSTANT_EXPECTED_TYPE_MISMATCH!>1<!> // Should be no TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS
<!TYPE_MISMATCH!>""<!>
}
a.bar { <!TYPE_MISMATCH!>Out<CharSequence>()<!> }
a.bar { Out() }
a.bar { <!TYPE_MISMATCH!>z.id()<!> }
a.foo {
z.foobar(if (1 > 2) return@foo <!TYPE_MISMATCH!>""<!> else "")
<!TYPE_MISMATCH!>""<!>
}
}
@@ -0,0 +1,21 @@
package
public fun test(/*0*/ a: A<out kotlin.CharSequence>, /*1*/ z: Out<kotlin.CharSequence>): kotlin.Unit
public final class A</*0*/ E> {
public constructor A</*0*/ E>()
public final inline fun bar(/*0*/ block: () -> Out<E>): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final inline fun foo(/*0*/ block: () -> E): kotlin.Unit
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 T> {
public constructor Out</*0*/ out T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foobar(/*0*/ x: kotlin.Any): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun id(): Out<T>
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A<T> {
fun foo(vararg x: T) {}
}
fun test(a: A<out CharSequence>, y: Array<out CharSequence>) {
a.<!MEMBER_PROJECTED_OUT!>foo<!>("", "", "")
a.foo(*<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>)
// TODO: TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS probably redundant
a.<!MEMBER_PROJECTED_OUT!>foo<!>(*<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>y<!>, "")
}
@@ -0,0 +1,11 @@
package
public fun test(/*0*/ a: A<out kotlin.CharSequence>, /*1*/ y: kotlin.Array<out 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 foo(/*0*/ vararg x: T /*kotlin.Array<out T>*/): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -4,6 +4,6 @@ interface Tr<T> {
}
fun test(t: Tr<*>) {
t.v = <!TYPE_MISMATCH!>t<!>
<!SETTER_PROJECTED_OUT!>t.v<!> = t
t.v checkType { _<Tr<*>>() }
}
@@ -7,7 +7,7 @@ interface Tr<T> {
fun test(t: Tr<*>) {
t.v = null!!
t.v = <!TYPE_MISMATCH!>""<!>
t.v = <!NULL_FOR_NONNULL_TYPE!>null<!>
<!SETTER_PROJECTED_OUT!>t.v<!> = ""
<!SETTER_PROJECTED_OUT!>t.v<!> = null
t.v checkType { _<Any?>() }
}
@@ -6,5 +6,5 @@ interface Tr<T> {
fun test(t: Tr<out String>) {
// resolved as t.v = t.v + null!!, where type of right operand is String,
// so TYPE_MISMATCH: String is not <: of Captured(out String)
<!TYPE_MISMATCH!>t.v += null!!<!>
<!SETTER_PROJECTED_OUT!>t.v<!> += null!!
}
@@ -1,12 +1,12 @@
fun test(mc: MutableCollection<out CharSequence>) {
mc.addAll(<!TYPE_MISMATCH!>mc<!>)
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>mc<!>)
mc.addAll(<!TYPE_MISMATCH!>arrayListOf<CharSequence>()<!>)
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>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(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf("")<!>)
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf<String>("")<!>)
mc.addAll(<!TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS!>listOf<CharSequence>("")<!>)
mc.addAll(emptyList())
mc.addAll(emptyList<Nothing>())