[FE] Implement discussed rules to report empty intersection errors

This commit is contained in:
Victor Petukhov
2022-03-28 16:11:18 +03:00
committed by teamcity
parent b96708c3e2
commit 5bfe6cd20a
29 changed files with 241 additions and 62 deletions
@@ -8,12 +8,12 @@ package org.jetbrains.kotlin.resolve.calls.inference.components
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
import org.jetbrains.kotlin.resolve.calls.inference.model.*
import org.jetbrains.kotlin.resolve.calls.model.PostponedAtomWithRevisableExpectedType
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
import org.jetbrains.kotlin.types.model.TypeVariableMarker
import org.jetbrains.kotlin.types.AbstractTypeChecker.isRelatedBySubtypingTo
import org.jetbrains.kotlin.types.model.*
abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Context, ResultTypeResolver.Context {
abstract val allTypeVariables: Map<TypeConstructorMarker, TypeVariableMarker>
@@ -37,6 +37,50 @@ abstract class ConstraintSystemCompletionContext : VariableFixationFinder.Contex
abstract fun couldBeResolvedWithUnrestrictedBuilderInference(): Boolean
abstract fun processForkConstraints()
private fun TypeConstructorMarker.isDefinitelyClass() = isClassTypeConstructor() && !isInterface()
private fun KotlinTypeMarker.containsTypeParameter() = contains { it.typeConstructor().isTypeParameterTypeConstructor() }
fun Collection<KotlinTypeMarker>.isEmptyIntersection(constraintSystem: NewConstraintSystem?): Boolean {
val indexedComponents = withIndex()
return indexedComponents.any firstTypes@{ (i, first) ->
val firstTypeConstructor = first.typeConstructor()
indexedComponents.any secondTypes@{ (j, second) ->
if (i >= j) return@secondTypes false
val secondTypeConstructor = second.typeConstructor()
if (!firstTypeConstructor.isDefinitelyClass() && !firstTypeConstructor.isTypeParameterTypeConstructor())
return@secondTypes false
if (!secondTypeConstructor.isDefinitelyClass() && !secondTypeConstructor.isTypeParameterTypeConstructor())
return@secondTypes false
if (!first.containsTypeParameter() && !second.containsTypeParameter()) {
return@secondTypes !isRelatedBySubtypingTo(this@ConstraintSystemCompletionContext, first, second)
}
if (constraintSystem == null) return false
val completerContext = constraintSystem.asConstraintSystemCompleterContext()
val substitutionMap = completerContext.allTypeVariables.entries.associate { (key, value) ->
val typeParameter = (key as TypeVariableTypeConstructorMarker).typeParameter
require(typeParameter != null) {
"Constraint system for checking type parameters for intersection emptiness" +
"should be build with type variables which refer to those type parameters"
}
typeParameter.getTypeConstructor() to value.defaultType()
}
val substitutor = typeSubstitutorByTypeConstructor(substitutionMap)
completerContext.getBuilder().addSubtypeConstraint(
substitutor.safeSubstitute(first), substitutor.safeSubstitute(second), TypeParametersIntersectionEmptyCheckingPosition
)
constraintSystem.hasContradiction
}
}
}
fun <A : PostponedResolvedAtomMarker> analyzeArgumentWithFixedParameterTypes(
languageVersionSettings: LanguageVersionSettings,
postponedArguments: List<A>,
@@ -18,7 +18,7 @@ fun test() {
callFun<String, Wrapper<String>>(::createWrapper)
callFun<Int, Wrapper<Number>>(::createWrapper)
callFun<String, Wrapper<*>>(::createWrapper)
callFun<String, Wrapper<Int>>(::createWrapper)
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>callFun<!><String, Wrapper<Int>>(::createWrapper)
callFun<Int, Wrapper<Int>>(::createWrapper).baz(::foo)
}
@@ -18,7 +18,7 @@ fun test() {
callFun<String, Wrapper<String>>(::createWrapper)
callFun<Int, Wrapper<Number>>(::createWrapper)
callFun<String, Wrapper<*>>(::createWrapper)
callFun<String, Wrapper<Int>>(::createWrapper)
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>callFun<!><String, Wrapper<Int>>(::createWrapper)
callFun<Int, Wrapper<Int>>(::createWrapper).baz(::foo)
}
@@ -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() })
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Number> & Inv<kotlin.Int>")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, id1 { x: Inv<Int> -> TODO() })
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION, 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(id(id2 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id(id { x: Int -> x }))
// Disambiguating callable references by other callable references without overloads
@@ -164,10 +164,10 @@ fun main() {
select({ x, y -> x.inv() + y.toByte() }, id { x: Int, y -> y.toByte() }, id { x, y: Number -> x.inv() })
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { x: Int -> }, { x: Nothing -> x })
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { x: Nothing -> x })
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Nothing) -> Unit, { x: Int -> x })
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { } as (Nothing) -> Unit)
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { x: Int -> }, { x: Nothing -> x })
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { x: Nothing -> x })
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Nothing) -> Unit, { x: Int -> x })
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { } as (Nothing) -> Unit)
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types; dependent type parameters
takeLambdasWithDirectlyDependentTypeParameters({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Int -> x })
@@ -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() })
select(id1 { <!DEBUG_INFO_EXPRESSION_TYPE("{Inv<Int> & Inv<Number>}")!>it<!> }, id1 { x: Inv<Number> -> TODO() }, 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(id(id2 { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!>.inv() }), id(id { x: Int -> x }))
// Disambiguating callable references by other callable references without overloads
@@ -164,10 +164,10 @@ fun main() {
select({ x, y -> x.inv() + y.toByte() }, id { x: Int, y -> y.toByte() }, id { x, y: Number -> x.inv() })
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { x: Int -> }, { x: Nothing -> x })
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { x: Nothing -> x })
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Nothing) -> Unit, { x: Int -> x })
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>takeLambdas<!>({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { } as (Nothing) -> Unit)
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { x: Int -> }, { x: Nothing -> x })
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { x: Nothing -> x })
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Nothing) -> Unit, { x: Int -> x })
takeLambdas({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!> }, { } as (Int) -> Unit, { } as (Nothing) -> Unit)
// Inferring lambda parameter types by other specified lambda parameters; expected type is a functional type with type variables in parameter types; dependent type parameters
takeLambdasWithDirectlyDependentTypeParameters({ <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int")!>it<!> }, { x: Int -> x })
+2 -1
View File
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// RENDER_DIAGNOSTICS_FULL_TEXT
interface Base
@@ -9,5 +10,5 @@ fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
fun main() {
val func: (DoesNotImplementBase) -> Unit = { }
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>exampleGenericFunction<!>(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
exampleGenericFunction(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
}
@@ -0,0 +1,13 @@
// FIR_IDENTICAL
interface Base
interface DoesNotImplementBase
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
}
fun main() {
val func: (DoesNotImplementBase) -> Unit = { }
exampleGenericFunction(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
}
@@ -0,0 +1,16 @@
package
public fun </*0*/ T : Base, /*1*/ V : (T) -> kotlin.Unit> exampleGenericFunction(/*0*/ func: V): kotlin.Unit
public fun main(): kotlin.Unit
public interface Base {
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 DoesNotImplementBase {
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,11 @@
open class Base
open class DoesNotImplementBase
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
}
fun main() {
val func: (DoesNotImplementBase) -> Unit = { }
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>exampleGenericFunction<!>(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
}
@@ -0,0 +1,11 @@
open class Base
open class DoesNotImplementBase
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
}
fun main() {
val func: (DoesNotImplementBase) -> Unit = { }
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>exampleGenericFunction<!>(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
}
@@ -0,0 +1,18 @@
package
public fun </*0*/ T : Base, /*1*/ V : (T) -> kotlin.Unit> exampleGenericFunction(/*0*/ func: V): kotlin.Unit
public fun main(): kotlin.Unit
public open class Base {
public constructor Base()
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 DoesNotImplementBase {
public constructor DoesNotImplementBase()
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
}
@@ -1,6 +1,4 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
interface Base
open class Base
class DoesNotImplementBase
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
@@ -0,0 +1,11 @@
open class Base
class DoesNotImplementBase
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
}
fun main() {
val func: (DoesNotImplementBase) -> Unit = { }
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>exampleGenericFunction<!>(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
}
@@ -0,0 +1,18 @@
package
public fun </*0*/ T : Base, /*1*/ V : (T) -> kotlin.Unit> exampleGenericFunction(/*0*/ func: V): kotlin.Unit
public fun main(): kotlin.Unit
public open class Base {
public constructor Base()
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 DoesNotImplementBase {
public constructor DoesNotImplementBase()
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,13 @@
// FIR_IDENTICAL
interface Base
class DoesNotImplementBase
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
}
fun main() {
val func: (DoesNotImplementBase) -> Unit = { }
exampleGenericFunction(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
}
@@ -0,0 +1,17 @@
package
public fun </*0*/ T : Base, /*1*/ V : (T) -> kotlin.Unit> exampleGenericFunction(/*0*/ func: V): kotlin.Unit
public fun main(): kotlin.Unit
public interface Base {
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 DoesNotImplementBase {
public constructor DoesNotImplementBase()
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,13 @@
// FIR_IDENTICAL
interface Base
open class DoesNotImplementBase
fun <T, V> exampleGenericFunction(func: V) where T: Base, V: (T) -> Unit {
}
fun main() {
val func: (DoesNotImplementBase) -> Unit = { }
exampleGenericFunction(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
}
@@ -0,0 +1,17 @@
package
public fun </*0*/ T : Base, /*1*/ V : (T) -> kotlin.Unit> exampleGenericFunction(/*0*/ func: V): kotlin.Unit
public fun main(): kotlin.Unit
public interface Base {
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 DoesNotImplementBase {
public constructor DoesNotImplementBase()
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
}
@@ -14,7 +14,7 @@ val a1: A = select(
{ a: Int -> myPrint(a + this.length + 2) }
)
val a2 = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>select<!>(
val a2 = select(
{ a: Int -> myPrint(a + this.length + 1) },
fun CharSequence.(a: Int) { myPrint(a + this.length + 2) },
{ a: Int -> myPrint(a + this.length + 3) }
@@ -14,7 +14,7 @@ val a1: A = select(
{ a: Int -> myPrint(a + this.length + 2) }
)
val a2 = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>select<!>(
val a2 = select(
{ a: Int -> myPrint(a + this.<!UNRESOLVED_REFERENCE!>length<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 1) },
fun CharSequence.(a: Int) { myPrint(a + this.length + 2) },
{ a: Int -> myPrint(a + this.<!UNRESOLVED_REFERENCE!>length<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>+<!> 3) }
@@ -1,14 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
abstract class Bar<T>
class Foo<T> : Bar<T>(), Comparable<Foo<*>> {
override fun compareTo(other: Foo<*>): Int = TODO()
}
infix fun <T : Comparable<T>, S : T?> Bar<in S>.test(t: T) { }
infix fun <T : Comparable<T>, S : T?> Bar<in S>.test(other: Bar<in S>) {}
fun checkFunctions(exp1: Foo<Int?>, exp2: Foo<Int>) {
exp1.<!OVERLOAD_RESOLUTION_AMBIGUITY!>test<!>(exp2)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
abstract class Bar<T>
@@ -13,7 +13,7 @@ fun testElvis(a: Int?, b: Int?) {
if (a != null) {
doInt(b ?: a)
}
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>doList<!>(getList() ?: emptyListOfA()) //should be an error
doList(getList() ?: emptyListOfA()) //should be an error
doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed
}
@@ -13,7 +13,7 @@ fun testElvis(a: Int?, b: Int?) {
if (a != null) {
doInt(b ?: <!DEBUG_INFO_SMARTCAST!>a<!>)
}
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>doList<!>(getList() ?: emptyListOfA()) //should be an error
doList(getList() ?: emptyListOfA()) //should be an error
doList(getList() ?: strangeList { doInt(it) }) //lambda was not analyzed
}
@@ -12,7 +12,7 @@ fun <T: A> emptyNullableListOfA(): List<T>? = null
//-------------------------------
fun testExclExcl() {
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>doList<!>(emptyNullableListOfA()!!) //should be an error here
doList(emptyNullableListOfA()!!) //should be an error here
val l: List<Int> = <!INITIALIZER_TYPE_MISMATCH, NEW_INFERENCE_ERROR!>id(emptyNullableListOfA()!!)<!>
doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase)
@@ -12,7 +12,7 @@ fun <T: A> emptyNullableListOfA(): List<T>? = null
//-------------------------------
fun testExclExcl() {
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>doList<!>(emptyNullableListOfA()!!) //should be an error here
doList(emptyNullableListOfA()!!) //should be an error here
val l: List<Int> = <!TYPE_MISMATCH!><!TYPE_MISMATCH!>id<!>(<!TYPE_MISMATCH!>emptyNullableListOfA<!>()<!TYPE_MISMATCH!>!!<!>)<!>
doList(strangeNullableList { doInt(it) }!!) //lambda should be analyzed (at completion phase)
@@ -0,0 +1,12 @@
class Expression<T>(val x: T)
class GreaterOp(val expr1: Expression<*>, val expr2: Expression<*>)
fun <T : Comparable<T>, S : T?> Expression<in S>.greater(other: T): GreaterOp =
GreaterOp(this, Expression(other))
fun foo(countExpr: Expression<Long>) {
countExpr.greater(0)
countExpr.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>greater<!>("0")
countExpr.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>greater<!><String, Nothing>("0")
}
+2 -3
View File
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
class Expression<T>(val x: T)
class GreaterOp(val expr1: Expression<*>, val expr2: Expression<*>)
@@ -8,6 +7,6 @@ fun <T : Comparable<T>, S : T?> Expression<in S>.greater(other: T): GreaterOp =
fun foo(countExpr: Expression<Long>) {
countExpr.greater(0)
countExpr.greater("0")
countExpr.greater<String, Nothing>("0")
countExpr.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>greater<!>("0")
countExpr.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>greater<!><String, Nothing>("0")
}
@@ -178,26 +178,6 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
fun KotlinTypeMarker.isFinal(): Boolean
fun Collection<KotlinTypeMarker>.isEmptyIntersection(): Boolean {
val expandedTypes = buildSet {
for (type in this@isEmptyIntersection) {
val typeConstructor = type.typeConstructor()
when {
typeConstructor.isClassTypeConstructor() -> add(type)
typeConstructor.isTypeParameterTypeConstructor() -> addAll(typeConstructor.supertypes())
}
}
}.takeIf { it.isNotEmpty() } ?: return false
return expandedTypes.any { first ->
expandedTypes.any { second ->
first !== second &&
first.isFinal() &&
!AbstractTypeChecker.isSubtypeOf(this@TypeSystemInferenceExtensionContext, first, second)
}
}
}
fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker
fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker