FIR: improve inference of implicit type arguments in casts

Type parameters do not necessarily match one-to-one, or preserve order.
This commit is contained in:
pyos
2021-01-06 14:39:22 +01:00
committed by Dmitriy Novozhilov
parent acdc1f532b
commit 29f95c7df2
32 changed files with 134 additions and 149 deletions
@@ -4,7 +4,7 @@ interface Tr
interface G<T>
fun test(tr: Tr) {
val v = tr as G?
val v = tr as <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>G?<!>
// If v is not nullable, there will be a warning on this line:
checkSubtype<G<*>>(v!!)
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><G<*>>(v!!)
}
@@ -1,18 +0,0 @@
// !CHECK_TYPE
interface Either<out A, out B>
interface Left<out A>: Either<A, Nothing>
interface Right<out B>: Either<Nothing, B>
class C1(val v1: Int)
class C2(val v2: Int)
fun _as_left(e: Either<C1, C2>): Any {
val v = e as Left
return checkSubtype<Left<C1>>(v)
}
fun _as_right(e: Either<C1, C2>): Any {
val v = e as Right
return <!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Right<C2>>(v)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !CHECK_TYPE
interface Either<out A, out B>
@@ -1,25 +0,0 @@
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
interface Either<out A, out B>
interface Left<out A>: Either<A, Nothing> {
val value: A
}
interface Right<out B>: Either<Nothing, B> {
val value: B
}
class C1(val v1: Int)
class C2(val v2: Int)
fun _is_l(e: Either<C1, C2>): Any {
if (e is Left) {
return e.value.v1
}
return e
}
fun _is_r(e: Either<C1, C2>): Any {
if (e is Right) {
return e.value.<!UNRESOLVED_REFERENCE!>v2<!>
}
return e
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
interface Either<out A, out B>
interface Left<out A>: Either<A, Nothing> {
@@ -1,25 +0,0 @@
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
interface Either<out A, out B>
interface Left<out A>: Either<A, Nothing> {
val value: A
}
interface Right<out B>: Either<Nothing, B> {
val value: B
}
class C1(val v1: Int)
class C2(val v2: Int)
fun _is_l(e: Either<C1, C2>): Any {
if (e !is Left) {
return e
}
return e.value.v1
}
fun _is_r(e: Either<C1, C2>): Any {
if (e !is Right) {
return e
}
return e.value.<!UNRESOLVED_REFERENCE!>v2<!>
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
interface Either<out A, out B>
interface Left<out A>: Either<A, Nothing> {
@@ -1,18 +0,0 @@
// !CHECK_TYPE
interface Either<out A, out B>
interface Left<out A>: Either<A, Nothing>
interface Right<out B>: Either<Nothing, B>
class C1(val v1: Int)
class C2(val v2: Int)
fun _as_left(e: Either<C1, C2>): Any? {
val v = e as? Left
return checkSubtype<Left<C1>?>(v)
}
fun _as_right(e: Either<C1, C2>): Any? {
val v = e as? Right
return <!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Right<C2>?>(v)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !CHECK_TYPE
interface Either<out A, out B>
@@ -1,19 +0,0 @@
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
interface Either<out A, out B>
interface Left<out A>: Either<A, Nothing> {
val value: A
}
interface Right<out B>: Either<Nothing, B> {
val value: B
}
class C1(val v1: Int)
class C2(val v2: Int)
fun _when(e: Either<C1, C2>): Any {
return when (e) {
is Left -> e.value.v1
is Right -> e.value.<!UNRESOLVED_REFERENCE!>v2<!>
else -> e
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -DEBUG_INFO_SMARTCAST
interface Either<out A, out B>
interface Left<out A>: Either<A, Nothing> {
@@ -4,6 +4,6 @@ interface Tr
interface G<T>
fun test(tr: Tr?) {
val v = tr as G
checkSubtype<G<*>>(v)
val v = tr as <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>G<!>
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><G<*>>(v)
}
@@ -4,6 +4,6 @@ interface Tr
interface G<T>
fun test(tr: Tr?) {
val v = tr as G?
checkSubtype<G<*>>(v!!)
val v = tr as <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>G?<!>
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><G<*>>(v!!)
}
@@ -4,6 +4,6 @@ interface Tr
interface G<T>
fun test(tr: Tr) {
val v = tr as G
checkSubtype<G<*>>(v)
val v = tr as <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>G<!>
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><G<*>>(v)
}
@@ -1,4 +1,4 @@
interface Tr
interface G<T>
fun test(tr: Tr) = tr is G
fun test(tr: Tr) = tr is <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>G<!>