EmptyIntersectionTypeChecker: drop questionable check of arguments
The situations with conflicting type arguments normally don't provoke any runtime problems. Also, conflicts like A<T> VS A<SomeType> aren't valid at all. Here we decided to remove them to avoid strange and non-actionable warnings in user code. #KT-54411 Fixed
This commit is contained in:
committed by
Space Team
parent
832baf81e5
commit
2a1a5c6936
+1
-1
@@ -18,7 +18,7 @@ fun test() {
|
||||
callFun<String, Wrapper<String>>(::createWrapper)
|
||||
callFun<Int, Wrapper<Number>>(::createWrapper)
|
||||
callFun<String, Wrapper<*>>(::createWrapper)
|
||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>callFun<!><String, Wrapper<Int>>(::createWrapper)
|
||||
callFun<String, Wrapper<Int>>(::createWrapper)
|
||||
|
||||
callFun<Int, Wrapper<Int>>(::createWrapper).baz(::foo)
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ fun test() {
|
||||
callFun<String, Wrapper<String>>(::createWrapper)
|
||||
callFun<Int, Wrapper<Number>>(::createWrapper)
|
||||
callFun<String, Wrapper<*>>(::createWrapper)
|
||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>callFun<!><String, Wrapper<Int>>(::createWrapper)
|
||||
callFun<String, Wrapper<Int>>(::createWrapper)
|
||||
|
||||
callFun<Int, Wrapper<Int>>(::createWrapper).baz(::foo)
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -70,7 +70,7 @@ fun main() {
|
||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2 { x: Int -> x }))
|
||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2(::takeInt)))
|
||||
select(id1 { x: Inv<out Number> -> TODO() }, id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int>")!>it<!>.x.inv() }, id1 { x: Inv<Int> -> TODO() })
|
||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>select<!>(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Number> & Inv<kotlin.Int>")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
|
||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Number> & Inv<kotlin.Int>")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
|
||||
select(id(id2 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id(id { x: Int -> x }))
|
||||
|
||||
// Disambiguating callable references by other callable references without overloads
|
||||
|
||||
Vendored
+1
-1
@@ -70,7 +70,7 @@ fun main() {
|
||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2 { x: Int -> x }))
|
||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }, id1 { x: Number -> TODO() }, id1(id2(::takeInt)))
|
||||
select(id1 { x: Inv<out Number> -> TODO() }, id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int>")!>it<!>.x.inv() }, id1 { x: Inv<Int> -> TODO() })
|
||||
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>select<!>(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("{Inv<Int> & Inv<Number>}")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
|
||||
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("{Inv<Int> & Inv<Number>}")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
|
||||
select(id(id2 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id(id { x: Int -> x }))
|
||||
|
||||
// Disambiguating callable references by other callable references without overloads
|
||||
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
/kt45461_10.kt:7:25: warning: parameter 'foo' is never used
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
^
|
||||
/kt45461_10.kt:16:21: warning: type argument for a type parameter S has possible incompatible upper bounds: Out<Int>, K (final class and interface: Int, A)
|
||||
Bar<Out<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
^
|
||||
|
||||
+1
-2
@@ -1,5 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
|
||||
class Foo<T>
|
||||
|
||||
@@ -13,5 +12,5 @@ interface A
|
||||
|
||||
fun <K : Out<L>, L : N, N: A> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<Int>>().<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Out<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
/kt45461_13.kt:7:25: warning: parameter 'foo' is never used
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
^
|
||||
/kt45461_13.kt:16:24: warning: type argument for a type parameter S has possible incompatible upper bounds: Out<String>, K (final class and interface: String, A)
|
||||
Bar<Out<String>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
^
|
||||
|
||||
+1
-2
@@ -1,5 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
|
||||
class Foo<T>
|
||||
|
||||
@@ -13,5 +12,5 @@ class Out<out K>
|
||||
|
||||
fun <K : L, L : N, N> main() where N: Out<A> {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<String>>().<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Out<String>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
/kt45461_15.kt:5:25: warning: parameter 'foo' is never used
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
^
|
||||
/kt45461_15.kt:14:21: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv<Int>, K (incompatible type arguments: Int, {A & Number}). This will become an error in Kotlin 1.9
|
||||
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
^
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Inv<P>
|
||||
|
||||
interface A
|
||||
|
||||
fun <K : Inv<T>, T> main() where T: A, T: Number {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<Int>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -11,5 +11,5 @@ interface A
|
||||
|
||||
fun <K : Inv<T>, T> main() where T: A, T: Number {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<Int>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Inv<P>
|
||||
|
||||
interface A
|
||||
|
||||
fun <K : Inv<T>, T> main() where T: A, T: Number {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<out Int>>().<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+1
-1
@@ -11,5 +11,5 @@ interface A
|
||||
|
||||
fun <K : Inv<T>, T> main() where T: A, T: Number {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<out Int>>().<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Inv<out Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
/kt45461_19.kt:5:25: warning: parameter 'foo' is never used
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
^
|
||||
/kt45461_19.kt:13:26: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Out<Inv<Int>>, K (incompatible type arguments: Int, Number). This will become an error in Kotlin 1.9
|
||||
Bar<Out<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
^
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Out<out P>
|
||||
class Inv<O>
|
||||
|
||||
fun <K : Out<L>, L : N, N: Inv<Number>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<Inv<Int>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -10,5 +10,5 @@ class Inv<O>
|
||||
|
||||
fun <K : Out<L>, L : N, N: Inv<Number>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<Inv<Int>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Out<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
/kt45461_21.kt:5:25: warning: parameter 'foo' is never used
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
^
|
||||
/kt45461_21.kt:13:25: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: In<Inv<Int>>, K (incompatible type arguments: Int, Number). This will become an error in Kotlin 1.9
|
||||
Bar<In<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
^
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class In<in P>
|
||||
class Inv<O>
|
||||
|
||||
fun <K : In<Inv<Number>>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<In<Inv<Int>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -10,5 +10,5 @@ class Inv<O>
|
||||
|
||||
fun <K : In<Inv<Number>>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<In<Inv<Int>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<In<Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
/kt45461_24.kt:5:25: warning: parameter 'foo' is never used
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
^
|
||||
/kt45461_24.kt:10:10: warning: 'Inv<out Inv<out Int>>' is a final type, and thus a value of the type parameter is predetermined
|
||||
fun <K : Inv<out Inv<out Int>>> main() {
|
||||
^
|
||||
/kt45461_24.kt:12:35: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv<in Inv<in Number>>, K (incompatible type arguments: Number, Int). This will become an error in Kotlin 1.9
|
||||
Bar<Inv<in Inv<in Number>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
^
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Inv<O>
|
||||
|
||||
fun <K : <!FINAL_UPPER_BOUND!>Inv<out Inv<out Int>><!>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<in Inv<in Number>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -9,5 +9,5 @@ class Inv<O>
|
||||
|
||||
fun <K : <!FINAL_UPPER_BOUND!>Inv<out Inv<out Int>><!>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<in Inv<in Number>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Inv<in Inv<in Number>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-4
@@ -1,10 +1,6 @@
|
||||
/kt45461_26.kt:13:25: error: type mismatch: inferred type is {K & Out<String>} but Out<Float> was expected
|
||||
val x: Out<Float> = Bar<Out<String>>().takeFoo(foo)
|
||||
^
|
||||
/kt45461_26.kt:13:44: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Out<String>, K (multiple incompatible classes: String, Int)
|
||||
val x: Out<Float> = Bar<Out<String>>().takeFoo(foo)
|
||||
^
|
||||
/kt45461_26.kt:13:44: error: type mismatch: inferred type is {K & Out<String>} but Out<Float> was expected
|
||||
val x: Out<Float> = Bar<Out<String>>().takeFoo(foo)
|
||||
^
|
||||
|
||||
|
||||
+1
-1
@@ -10,5 +10,5 @@ class Out<out K>
|
||||
|
||||
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Out<Int><!>> main() {
|
||||
val foo = Foo<K>()
|
||||
val x: Out<Float> = Bar<Out<String>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION("S; Out<kotlin/String>, K; multiple incompatible classes; : kotlin/String, kotlin/Int")!>takeFoo<!>(foo)
|
||||
val x: Out<Float> = Bar<Out<String>>().takeFoo(foo)
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,5 +10,5 @@ class Out<out K>
|
||||
|
||||
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Out<Int><!>> main() {
|
||||
val foo = Foo<K>()
|
||||
val x: Out<Float> = <!TYPE_MISMATCH!>Bar<Out<String>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_ERROR("S; Out<String>, K; multiple incompatible classes; : String, Int"), TYPE_MISMATCH!>takeFoo<!>(foo)<!>
|
||||
val x: Out<Float> = <!TYPE_MISMATCH!>Bar<Out<String>>().<!TYPE_MISMATCH!>takeFoo<!>(foo)<!>
|
||||
}
|
||||
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Inv<O>
|
||||
|
||||
fun <K : Inv<Inv<Number>>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<in Inv<Int>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -8,5 +9,5 @@ class Inv<O>
|
||||
|
||||
fun <K : Inv<Inv<Number>>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<in Inv<Int>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Inv<in Inv<Int>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Inv<P>
|
||||
|
||||
interface A
|
||||
interface B
|
||||
|
||||
fun <K : Inv<A>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -11,5 +12,5 @@ interface B
|
||||
|
||||
fun <K : Inv<A>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Inv<B>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Out<out P>
|
||||
|
||||
interface A<K>
|
||||
interface B<K> : A<Int>
|
||||
|
||||
fun <K : Out<A<String>>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<B<String>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -11,5 +12,5 @@ interface B<K> : A<Int>
|
||||
|
||||
fun <K : Out<A<String>>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<B<String>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Out<B<String>>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Out<out P>
|
||||
|
||||
interface A<K>
|
||||
interface B : A<Int>
|
||||
|
||||
fun <K : Out<A<String>>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -11,5 +12,5 @@ interface B : A<Int>
|
||||
|
||||
fun <K : Out<A<String>>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING("S; Out<B>, K; incompatible supertypes; : A<Int>, A<String>")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Out<B>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Out<out P>
|
||||
|
||||
interface A<K>
|
||||
interface B : A<Int>
|
||||
interface C : A<String>
|
||||
|
||||
fun <K : Out<C>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -12,5 +13,5 @@ interface C : A<String>
|
||||
|
||||
fun <K : Out<C>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Out<B>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Out<out P>
|
||||
|
||||
interface A<K>
|
||||
class B : A<Int>
|
||||
class C : A<String>
|
||||
|
||||
fun <K : <!FINAL_UPPER_BOUND!>Out<C><!>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -12,5 +13,5 @@ class C : A<String>
|
||||
|
||||
fun <K : <!FINAL_UPPER_BOUND!>Out<C><!>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Out<B>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Out<out P>
|
||||
|
||||
interface A<K>
|
||||
class B : A<Int>
|
||||
|
||||
fun <K : Out<A<String>>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -11,5 +12,5 @@ class B : A<Int>
|
||||
|
||||
fun <K : Out<A<String>>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Out<B>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING("S; Out<B>, K; incompatible supertypes; : A<Int>, A<String>")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Out<B>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
// WITH_STDLIB
|
||||
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T>
|
||||
|
||||
fun <T> Bar<T>.takeFoo(foo: Foo<out Any?>): Int = 1
|
||||
|
||||
class Inv<O>
|
||||
|
||||
fun <K : <!FINAL_UPPER_BOUND!>Inv<out Inv<out Int>><!>> main() {
|
||||
fun <T, S : T> Bar<T>.takeFoo(foo: Foo<in S>): String = ""
|
||||
|
||||
val foo = Foo<K>()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>Bar<Inv<in Inv<in Number>>>().takeFoo(foo)<!>
|
||||
}
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// WITH_STDLIB
|
||||
|
||||
class Foo<T>
|
||||
@@ -12,5 +13,5 @@ fun <K : <!FINAL_UPPER_BOUND!>Inv<out Inv<out Int>><!>> main() {
|
||||
fun <T, S : T> Bar<T>.takeFoo(foo: Foo<in S>): String = ""
|
||||
|
||||
val foo = Foo<K>()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>Bar<Inv<in Inv<in Number>>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo)<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>Bar<Inv<in Inv<in Number>>>().takeFoo(foo)<!>
|
||||
}
|
||||
|
||||
+1
-1
@@ -14,5 +14,5 @@ fun <K : <!FINAL_UPPER_BOUND!>Inv<out Inv<out Int>><!>> main() {
|
||||
fun <T, S : T> Bar<T>.takeFoo(foo: Foo<in S>): String = ""
|
||||
|
||||
val foo = Foo<K>()
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>Bar<Inv<in Inv<in Number>>>().takeFoo(foo)<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>Bar<Inv<in Inv<in Number>>>().takeFoo(foo)<!>
|
||||
}
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
/kt45461_8.kt:5:25: warning: parameter 'foo' is never used
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
^
|
||||
/kt45461_8.kt:10:28: warning: 'Int' is a final type, and thus a value of the type parameter is predetermined
|
||||
fun <K : Inv<L>, L : N, N: Int> main() {
|
||||
^
|
||||
/kt45461_8.kt:12:24: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv<Number>, K (incompatible type arguments: Number, Int). This will become an error in Kotlin 1.9
|
||||
Bar<Inv<Number>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
^
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Inv<P>
|
||||
|
||||
fun <K : Inv<L>, L : N, N: <!FINAL_UPPER_BOUND!>Int<!>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<Number>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -9,5 +9,5 @@ class Inv<P>
|
||||
|
||||
fun <K : Inv<L>, L : N, N: <!FINAL_UPPER_BOUND!>Int<!>> main() {
|
||||
val foo = Foo<K>()
|
||||
Bar<Inv<Number>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Inv<Number>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
/kt45461_9.kt:5:25: warning: parameter 'foo' is never used
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
^
|
||||
/kt45461_9.kt:12:21: warning: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: Inv<Int>, Inv<Number> (incompatible type arguments: Int, Number). This will become an error in Kotlin 1.9
|
||||
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
^
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
fun <S : T> takeFoo(foo: Foo<in S>) {}
|
||||
}
|
||||
|
||||
class Inv<P>
|
||||
|
||||
fun <K : Inv<L>, L : N, N: Number> main() {
|
||||
val foo = Foo<Inv<Number>>()
|
||||
Bar<Inv<Int>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
// FIR_IDENTICAL
|
||||
class Foo<T>
|
||||
|
||||
class Bar<T> {
|
||||
@@ -9,5 +9,5 @@ class Inv<P>
|
||||
|
||||
fun <K : Inv<L>, L : N, N: Number> main() {
|
||||
val foo = Foo<Inv<Number>>()
|
||||
Bar<Inv<Int>>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
|
||||
Bar<Inv<Int>>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
|
||||
}
|
||||
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
/kt54411.kt:5:68: warning: parameter 'createNewSegment' is never used
|
||||
inline fun <F : Segment<F>> AtomicRef<F>.findSegmentAndMoveForward(createNewSegment: (prev: F?) -> F) = null
|
||||
^
|
||||
/kt54411.kt:14:14: warning: type argument for a type parameter F has possible incompatible upper bounds: Segment<OneElementSegment<Q>>, OneElementSegment<Q>? (final class and non-final class: Segment<OneElementSegment<out Any?>>, OneElementSegment<out Any?>)
|
||||
tail.findSegmentAndMoveForward(::createSegment)
|
||||
^
|
||||
/kt54411.kt:18:31: warning: parameter 'prev' is never used
|
||||
private fun <C> createSegment(prev: OneElementSegment<C>?) = OneElementSegment<C>()
|
||||
^
|
||||
+1
-2
@@ -1,5 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
class AtomicRef<T>(val value: T)
|
||||
|
||||
inline fun <F : Segment<F>> AtomicRef<F>.findSegmentAndMoveForward(createNewSegment: (prev: F?) -> F) = null
|
||||
@@ -11,7 +10,7 @@ interface Queue<Q> {
|
||||
// F <: Segment<F> from upper bound
|
||||
// F <: OneElementSegment<Segment<F>>? from ::createSegment argument. ? is questionable here
|
||||
// (F?) -> F <: (OneElementSegment<C>?) -> OneElementSegment<C>
|
||||
tail.<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION!>findSegmentAndMoveForward<!>(::createSegment)
|
||||
tail.findSegmentAndMoveForward(::createSegment)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-99
@@ -107,18 +107,10 @@ internal object EmptyIntersectionTypeChecker {
|
||||
).singleOrNull()
|
||||
|
||||
when {
|
||||
firstSuperTypeWithSecondConstructor != null && secondSuperTypeByFirstConstructor != null -> {
|
||||
val argumentsIntersectionKind = computeByCheckingTypeArguments(
|
||||
firstSuperTypeWithSecondConstructor, secondSuperTypeByFirstConstructor
|
||||
) ?: continue
|
||||
|
||||
if (argumentsIntersectionKind.kind.isDefinitelyEmpty())
|
||||
return argumentsIntersectionKind
|
||||
|
||||
if (possibleEmptyIntersectionKind == null && argumentsIntersectionKind.kind.isPossiblyEmpty())
|
||||
possibleEmptyIntersectionKind = argumentsIntersectionKind
|
||||
firstSuperTypeWithSecondConstructor != null || secondSuperTypeByFirstConstructor != null -> {
|
||||
continue
|
||||
}
|
||||
firstSuperTypeWithSecondConstructor == null && secondSuperTypeByFirstConstructor == null && !atLeastOneInterface -> {
|
||||
!atLeastOneInterface -> {
|
||||
// Two classes can't have a common subtype if neither is a subtype of another
|
||||
return EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.MULTIPLE_CLASSES, firstType, secondType)
|
||||
}
|
||||
@@ -140,70 +132,6 @@ internal object EmptyIntersectionTypeChecker {
|
||||
return possibleEmptyIntersectionKind
|
||||
}
|
||||
|
||||
private fun TypeSystemInferenceExtensionContext.computeByCheckingTypeArguments(
|
||||
firstType: KotlinTypeMarker,
|
||||
secondType: KotlinTypeMarker,
|
||||
): EmptyIntersectionTypeInfo? {
|
||||
require(firstType.typeConstructor() == secondType.typeConstructor()) {
|
||||
"Type constructors of the passed types should be the same to compare their arguments"
|
||||
}
|
||||
|
||||
fun isSubtypeOf(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker) =
|
||||
AbstractTypeChecker.isSubtypeOf(this, firstType, secondType)
|
||||
|
||||
fun areEqualTypes(firstType: KotlinTypeMarker, secondType: KotlinTypeMarker) =
|
||||
AbstractTypeChecker.equalTypes(this, firstType, secondType)
|
||||
|
||||
fun Boolean.toEmptyIntersectionKind(vararg types: KotlinTypeMarker) =
|
||||
if (this) null else EmptyIntersectionTypeInfo(EmptyIntersectionTypeKind.INCOMPATIBLE_TYPE_ARGUMENTS, *types)
|
||||
|
||||
var possibleEmptyIntersectionTypeInfo: EmptyIntersectionTypeInfo? = null
|
||||
|
||||
for ((i, argumentOfFirst) in firstType.getArguments().withIndex()) {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val argumentOfFirst = uncaptureIfNeeded(argumentOfFirst)
|
||||
val argumentOfSecond = uncaptureIfNeeded(secondType.getArgument(i))
|
||||
|
||||
if (argumentOfFirst == argumentOfSecond || argumentOfFirst.isStarProjection() || argumentOfSecond.isStarProjection())
|
||||
continue
|
||||
|
||||
val argumentTypeOfFirst = argumentOfFirst.getType()
|
||||
val argumentTypeOfSecond = argumentOfSecond.getType()
|
||||
val intersectionKindOfArguments = when {
|
||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.INV) ->
|
||||
areEqualTypes(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||
.toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.OUT) ->
|
||||
isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||
.toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.INV, TypeVariance.IN) ->
|
||||
isSubtypeOf(argumentTypeOfSecond, argumentTypeOfFirst)
|
||||
.toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.OUT) -> {
|
||||
if (argumentTypeOfFirst.argumentsCount() == 0 && argumentTypeOfSecond.argumentsCount() == 0) {
|
||||
isSubtypeOf(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||
.toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||
} else {
|
||||
computeByHavingCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||
}
|
||||
}
|
||||
areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.OUT, TypeVariance.OUT)
|
||||
|| areArgumentsOfSpecifiedVariances(firstType, secondType, i, TypeVariance.IN, TypeVariance.IN) -> {
|
||||
computeByHavingCommonSubtype(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||
}
|
||||
else -> true.toEmptyIntersectionKind(argumentTypeOfFirst, argumentTypeOfSecond)
|
||||
} ?: continue
|
||||
|
||||
if (intersectionKindOfArguments.kind.isDefinitelyEmpty())
|
||||
return intersectionKindOfArguments
|
||||
|
||||
if (possibleEmptyIntersectionTypeInfo == null && intersectionKindOfArguments.kind.isPossiblyEmpty())
|
||||
possibleEmptyIntersectionTypeInfo = intersectionKindOfArguments
|
||||
}
|
||||
|
||||
return possibleEmptyIntersectionTypeInfo
|
||||
}
|
||||
|
||||
private fun TypeSystemInferenceExtensionContext.getIncompatibleSuperTypes(
|
||||
firstType: KotlinTypeMarker, secondType: KotlinTypeMarker
|
||||
): Array<KotlinTypeMarker>? {
|
||||
@@ -268,30 +196,6 @@ internal object EmptyIntersectionTypeChecker {
|
||||
return !typeConstructor.isAnyConstructor() && !typeConstructor.isNothingConstructor()
|
||||
}
|
||||
|
||||
private fun TypeSystemInferenceExtensionContext.areArgumentsOfSpecifiedVariances(
|
||||
firstType: KotlinTypeMarker,
|
||||
secondType: KotlinTypeMarker,
|
||||
argumentIndex: Int,
|
||||
variance1: TypeVariance,
|
||||
variance2: TypeVariance,
|
||||
): Boolean {
|
||||
fun getEffectiveVariance(type: KotlinTypeMarker): TypeVariance? {
|
||||
val argument = uncaptureIfNeeded(type.getArgument(argumentIndex))
|
||||
val parameter = type.typeConstructor().getParameter(argumentIndex)
|
||||
return AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
|
||||
}
|
||||
|
||||
val effectiveVariance1 = getEffectiveVariance(firstType)
|
||||
val effectiveVariance2 = getEffectiveVariance(secondType)
|
||||
|
||||
return (effectiveVariance1 == variance1 && effectiveVariance2 == variance2)
|
||||
|| (effectiveVariance1 == variance2 && effectiveVariance2 == variance1)
|
||||
}
|
||||
|
||||
private fun TypeSystemInferenceExtensionContext.uncaptureIfNeeded(argument: TypeArgumentMarker): TypeArgumentMarker {
|
||||
val type = argument.getType()
|
||||
return if (type is CapturedTypeMarker) type.typeConstructorProjection() else argument
|
||||
}
|
||||
}
|
||||
|
||||
class EmptyIntersectionTypeInfo(val kind: EmptyIntersectionTypeKind, vararg val casingTypes: KotlinTypeMarker)
|
||||
Reference in New Issue
Block a user