[FE] Always infer upper types to intersection types in K2...

...and always use old algorithm for K1

^KT-51221
This commit is contained in:
Dmitriy Novozhilov
2022-11-28 17:54:55 +02:00
committed by Space Team
parent d50c072af0
commit ac7fddaad5
15 changed files with 42 additions and 25 deletions
@@ -577,4 +577,7 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
override fun createSubstitutorForSuperTypes(baseType: KotlinTypeMarker): TypeSubstitutorMarker? =
if (baseType is ConeLookupTagBasedType) createSubstitutionForSupertype(baseType, session) else null
override val isK2: Boolean
get() = true
}
@@ -241,12 +241,8 @@ class ResultTypeResolver(
}
private fun Context.computeUpperType(upperConstraints: List<Constraint>): KotlinTypeMarker {
val isInferringIntoEmptyIntersectionEnabled =
languageVersionSettings.supportsFeature(LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection)
// TODO: Remove this after stopping support of disabling `ForbidInferringTypeVariablesIntoEmptyIntersection`
// If `ForbidInferringTypeVariablesIntoEmptyIntersection` is enabled, we do the corresponding checks during resolution and completion
return if (!isInferringIntoEmptyIntersectionEnabled) {
// TODO: Remove this after stopping support of K1
return if (!isK2) {
val intersectionUpperType = intersectTypes(upperConstraints.map { it.type })
val resultIsActuallyIntersection = intersectionUpperType.typeConstructor().isIntersection()
@@ -2,7 +2,7 @@ package c
import java.util.ArrayList
fun Array<Int>.toIntArray(): IntArray = <!RETURN_TYPE_MISMATCH!>this.mapTo(<!ARGUMENT_TYPE_MISMATCH!>IntArray(size)<!>, {it})<!>
fun Array<Int>.toIntArray(): IntArray = this.mapTo(<!ARGUMENT_TYPE_MISMATCH!>IntArray(size)<!>, {it})
fun Array<Int>.toArrayList(): ArrayList<Int> = this.mapTo(ArrayList<Int>(size), {it})
@@ -1,3 +1,10 @@
/kt45461_25.kt:11:34: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K, Float (multiple incompatible classes: String, Int)
/kt45461_25.kt:11:20: error: type mismatch: inferred type is {K & String} but Float was expected
val x: Float = Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
^
/kt45461_25.kt:11:34: error: type argument for a type parameter S can't be inferred because it has incompatible upper bounds: String, K (multiple incompatible classes: String, Int)
val x: Float = Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
^
/kt45461_25.kt:11:34: error: type mismatch: inferred type is {K & String} but Float was expected
val x: Float = Bar<String>().takeFoo(foo) // error in 1.3.72, no error in 1.4.31
^
@@ -8,5 +8,5 @@ class Bar<T> {
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Int<!>> main() {
val foo = Foo<K>()
val x: Float = Bar<String>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_ERROR("S; String, K, Float; multiple incompatible classes; : String, Int")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
val x: Float = <!TYPE_MISMATCH!>Bar<String>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_ERROR("S; String, K; multiple incompatible classes; : String, Int"), TYPE_MISMATCH!>takeFoo<!>(foo)<!> // error in 1.3.72, no error in 1.4.31
}
@@ -1,4 +1,10 @@
/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, Out<Float> (multiple incompatible classes: String, Int)
/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)
^
@@ -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_ERROR("S; Out<String>, K, Out<Float>; multiple incompatible classes; : String, Int")!>takeFoo<!>(foo)
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)<!>
}
@@ -11,7 +11,7 @@ fun test(x: X<Number>) {
fun <S, D: S> g() {
fun <T : S> foo(): T = TODO()
val y = <!NEW_INFERENCE_ERROR!>foo()<!> as Int
val y = <!DEBUG_INFO_EXPRESSION_TYPE("S!! & kotlin.Int")!>foo()<!> as Int
val y2 = foo() as D
}
@@ -13,7 +13,7 @@ fun <T: A> emptyNullableListOfA(): List<T>? = null
fun testExclExcl() {
<!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION("T; a/A, kotlin/Int; final class and interface")!>doList<!>(emptyNullableListOfA()!!) //should be an error here
val l: List<Int> = <!INITIALIZER_TYPE_MISMATCH, NEW_INFERENCE_ERROR!>id(emptyNullableListOfA()!!)<!>
val l: List<Int> = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.collections.List<a.A & kotlin.Int>")!>id(emptyNullableListOfA()!!)<!>
doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase)
}
@@ -9,9 +9,9 @@ fun <T : Foo> foo(): T? {
}
fun main() {
val a: Bar? = <!DEBUG_INFO_EXPRESSION_TYPE("Foo?"), INITIALIZER_TYPE_MISMATCH, NEW_INFERENCE_ERROR!>foo()<!>
val a: Bar? = <!DEBUG_INFO_EXPRESSION_TYPE("Foo? & Bar?")!><!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>foo<!>()<!>
}
fun <T : Appendable> wtf(): T = TODO()
val bar: Int = <!INITIALIZER_TYPE_MISMATCH, NEW_INFERENCE_ERROR!>wtf()<!> // happily compiles
val bar: Int = wtf() // happily compiles
@@ -7,6 +7,6 @@ fun interface ReadOnlyProperty<in T, out V> {
}
class Problem {
val variable: Int by <!DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, NEW_INFERENCE_ERROR!><!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>delegate<!>()<!> // delegate returns `ReadOnlyProperty<Problem, {CharSequence & Int}>`
val variable: Int by delegate() // delegate returns `ReadOnlyProperty<Problem, {CharSequence & Int}>`
fun <T : CharSequence> delegate() = null <!CAST_NEVER_SUCCEEDS!>as<!> ReadOnlyProperty<Problem, T>
}
@@ -9,13 +9,13 @@ abstract class View4
interface View5
fun <T: View1> findViewById1(): T = null as T
fun test1(): I = <!NEW_INFERENCE_ERROR, RETURN_TYPE_MISMATCH!>findViewById1()<!>
fun test1(): I = findViewById1()
fun <T: View2> findViewById2(): T = null as T
fun test2(): I = findViewById2()
inline fun <reified T: View1> findViewById3(): T = null as T
fun test3(): I = <!NEW_INFERENCE_ERROR, RETURN_TYPE_MISMATCH!>findViewById3()<!>
fun test3(): I = findViewById3()
inline fun <reified T: View2> findViewById4(): T = null as T
fun test4(): I = findViewById4()
@@ -39,17 +39,17 @@ inline fun <reified T> findViewById10(): T where T: View3, T: View5 = null as T
fun test10(): I = findViewById10()
fun <T: View2> findViewById11(): T = null as T
fun test11(): View4 = <!NEW_INFERENCE_ERROR, RETURN_TYPE_MISMATCH!>findViewById11()<!>
fun test11(): View4 = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>findViewById11<!>()
object Obj {
fun <T: I> findViewById1(): T = null as T
fun test1(): View1 = <!NEW_INFERENCE_ERROR, RETURN_TYPE_MISMATCH!>findViewById1()<!>
fun test1(): View1 = findViewById1()
fun <T: I> findViewById2(): T = null as T
fun test2(): View2 = findViewById2()
inline fun <reified T: I> findViewById3(): T = null as T
fun test3(): View1 = <!NEW_INFERENCE_ERROR, RETURN_TYPE_MISMATCH!>findViewById3()<!>
fun test3(): View1 = findViewById3()
inline fun <reified T: I> findViewById4(): T = null as T
fun test4(): View2 = findViewById4()
@@ -67,13 +67,13 @@ object Obj {
fun test8(): View4 = findViewById8()
fun <T> findViewById9(): T where T: View3, T: View5 = null as T
fun test9(): View1 = <!NEW_INFERENCE_ERROR, RETURN_TYPE_MISMATCH!>findViewById9()<!>
fun test9(): View1 = findViewById9()
inline fun <reified T> findViewById10(): T where T: View3, T: View5 = null as T
fun test10(): View1 = <!NEW_INFERENCE_ERROR, RETURN_TYPE_MISMATCH!>findViewById10()<!>
fun test10(): View1 = findViewById10()
fun <T: View2> findViewById11(): T = null as T
fun test11(): View4 = <!NEW_INFERENCE_ERROR, RETURN_TYPE_MISMATCH!>findViewById11()<!>
fun test11(): View4 = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>findViewById11<!>()
}
interface A
@@ -7,5 +7,5 @@ fun test1(l: List<Number>) {
val i: Int = l.firstTyped()
val s: String = <!INITIALIZER_TYPE_MISMATCH, NEW_INFERENCE_ERROR!>l.firstTyped()<!>
val s: String = l.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>firstTyped<!>()
}
@@ -332,6 +332,8 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
private fun computeEffectiveVariance(parameter: TypeParameterMarker, argument: TypeArgumentMarker): TypeVariance? =
AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance())
val isK2: Boolean
}
@@ -902,6 +902,9 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
return this is UnwrappedType && constructor is NewTypeVariableConstructor
}
override val isK2: Boolean
get() = false
class WA // Workaround for KT-52313
}