[NI] Fix issues with star projection uncapturing

Prevent stack overflow during uncapturing of star projection
for parameter with recursive upper bound.
Uncapture star projections for flexible type parameters with
respect to flexible upper bound.

^KT-35210 Fixed
This commit is contained in:
Pavel Kirpichenkov
2019-12-16 20:51:29 +03:00
parent 86dc0925b1
commit ebb9f09656
15 changed files with 317 additions and 9 deletions
@@ -0,0 +1,12 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
annotation class Anno
fun test(a: List<Class<Anno>>) {
strictSelect(a, emptyList<Anno>().map { it.annotationClass.java })
}
fun <@kotlin.internal.OnlyInputTypes S> strictSelect(arg1: S, arg2: S): S = TODO()
@@ -0,0 +1,18 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: TestBase.java
public class TestBase<T> { }
// FILE: Test.java
public class Test<K> extends TestBase<K> { }
// FILE: main.kt
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <@kotlin.internal.OnlyInputTypes K> TestBase<out K>.foo(key: K) = null
fun foo(result: Test<*>) {
result.foo("sd") // Type inference failed (NI), OK in OI
}
@@ -0,0 +1,18 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER
// FILE: TestBase.java
public class TestBase<T> { }
// FILE: Test.java
public class Test<K> extends TestBase<K> { }
// FILE: main.kt
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun <@kotlin.internal.OnlyInputTypes K> TestBase<out K>.foo(key: K) = null
fun foo(result: Test<*>) {
result.foo("sd") // Type inference failed (NI), OK in OI
}
@@ -0,0 +1,18 @@
package
public fun foo(/*0*/ result: Test<*>): kotlin.Unit
@kotlin.Suppress(names = {"INVISIBLE_MEMBER", "INVISIBLE_REFERENCE"}) public fun </*0*/ @kotlin.internal.OnlyInputTypes K> TestBase<out K>.foo(/*0*/ key: K): kotlin.Nothing?
public open class Test</*0*/ K : kotlin.Any!> : TestBase<K!> {
public constructor Test</*0*/ K : kotlin.Any!>()
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 open class TestBase</*0*/ T : kotlin.Any!> {
public constructor TestBase</*0*/ T : kotlin.Any!>()
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,24 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
interface IFace<K, out V>
fun <@kotlin.internal.OnlyInputTypes K, V> IFace<out K, V>.get(key: K): V? = TODO()
fun <@kotlin.internal.OnlyInputTypes I> id(arg: I): I = arg
interface InvBase<B>
class DerivedInv : InvBase<DerivedInv>
class InvRecursive<E : InvBase<E>>
fun test1(argument: InvRecursive<*>, receiver: IFace<InvRecursive<DerivedInv>, Any>) {
receiver.get(argument)
}
fun test2(arg: InvRecursive<out DerivedInv>) {
id(arg)
}
fun test3(arg: InvRecursive<in DerivedInv>) {
id(arg)
}
@@ -0,0 +1,24 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
interface IFace<K, out V>
fun <@kotlin.internal.OnlyInputTypes K, V> IFace<out K, V>.get(key: K): V? = TODO()
fun <@kotlin.internal.OnlyInputTypes I> id(arg: I): I = arg
interface InvBase<B>
class DerivedInv : InvBase<DerivedInv>
class InvRecursive<E : InvBase<E>>
fun test1(argument: InvRecursive<*>, receiver: IFace<InvRecursive<DerivedInv>, Any>) {
receiver.get(argument)
}
fun test2(arg: InvRecursive<out DerivedInv>) {
id(arg)
}
fun test3(arg: InvRecursive<in DerivedInv>) {
id(arg)
}
@@ -0,0 +1,33 @@
package
public fun </*0*/ @kotlin.internal.OnlyInputTypes I> id(/*0*/ arg: I): I
public fun test1(/*0*/ argument: InvRecursive<*>, /*1*/ receiver: IFace<InvRecursive<DerivedInv>, kotlin.Any>): kotlin.Unit
public fun test2(/*0*/ arg: InvRecursive<out DerivedInv>): kotlin.Unit
public fun test3(/*0*/ arg: InvRecursive<in DerivedInv>): kotlin.Unit
public fun </*0*/ @kotlin.internal.OnlyInputTypes K, /*1*/ V> IFace<out K, V>.get(/*0*/ key: K): V?
public final class DerivedInv : InvBase<DerivedInv> {
public constructor DerivedInv()
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 IFace</*0*/ K, /*1*/ out V> {
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 InvBase</*0*/ 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
}
public final class InvRecursive</*0*/ E : InvBase<E>> {
public constructor InvRecursive</*0*/ E : InvBase<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,54 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
// !WITH_NEW_INFERENCE
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
import kotlin.internal.OnlyInputTypes
interface Bound
class First : Bound
class Second : Bound
class Inv<I >(val v: I)
class InvB<I : Bound>(val v: I)
class In<in C>(v: C)
class InB<in C : Bound>(v: C)
class Out<out O>(val v: O)
class OutB<out O : Bound>(val v: O)
fun <@OnlyInputTypes M> strictId(arg: M): M = arg
fun <@OnlyInputTypes S> strictSelect(arg1: S, arg2: S): S = arg1
fun testOK(first: First, bound: Bound, second: Second) {
strictId(Inv(15))
strictId(Inv("foo"))
strictId(Inv(first))
strictId(InvB(first))
strictId(In(first))
strictId(InB(first))
strictId(Out(first))
strictId(OutB(first))
strictId(Inv(Inv(Inv(first))))
strictSelect(Inv(first), Inv(first))
strictSelect(InvB(first), InvB(first))
strictSelect(Out(first), Out(bound))
strictSelect(OutB(first), OutB(bound))
strictSelect(In(first), In(bound))
strictSelect(InB(first), InB(bound))
strictSelect(InB(first), InB(second)) // different behaviour in contravariant position
val out: Out<Bound> = strictSelect(Out(first), Out(second))
val outb: OutB<Bound> = strictSelect(OutB(first), OutB(second))
strictSelect<Out<Bound>>(Out(first), Out(second))
strictSelect<OutB<Bound>>(OutB(first), OutB(second))
}
fun testFail(first: First, bound: Bound, second: Second) {
strictSelect(InvB(first), InvB(bound))
strictSelect(Inv(first), Inv(bound))
strictSelect(Out(first), Out(second))
strictSelect(In(first), In(second))
strictSelect(Out(Inv(first)), Out(Inv(second)))
strictSelect(In(Inv(first)), In(Inv(second)))
}
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
// !WITH_NEW_INFERENCE
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
class Inv<T>
class Out<out T>
fun <T> foo(i: Inv<in T>, o: Out<T>) {
bar(i, o)
}
fun <@kotlin.internal.OnlyInputTypes K> bar(r: Inv<out K>, o: Out<K>): K = TODO()
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
// !WITH_NEW_INFERENCE
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
class Inv<T>
class Out<out T>
fun <T> foo(i: Inv<in T>, o: Out<T>) {
<!NI;TYPE_INFERENCE_ONLY_INPUT_TYPES!>bar<!>(i, o)
}
fun <@kotlin.internal.OnlyInputTypes K> bar(r: Inv<out K>, o: Out<K>): K = TODO()
@@ -0,0 +1,18 @@
package
public fun </*0*/ @kotlin.internal.OnlyInputTypes K> bar(/*0*/ r: Inv<out K>, /*1*/ o: Out<K>): K
public fun </*0*/ T> foo(/*0*/ i: Inv<in T>, /*1*/ o: Out<T>): kotlin.Unit
public final class Inv</*0*/ T> {
public constructor Inv</*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 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
}