K2: support ForbidInferringTypeVariablesIntoEmptyIntersection on/off

This commit is contained in:
Mikhail Glukhikh
2023-02-28 09:40:19 +01:00
committed by Space Team
parent f7544aff62
commit b64cb67370
43 changed files with 86 additions and 248 deletions
@@ -2224,8 +2224,20 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION) { firDiagnostic ->
InferredTypeVariableIntoEmptyIntersectionImpl(
add(FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.errorFactory) { firDiagnostic ->
InferredTypeVariableIntoEmptyIntersectionErrorImpl(
firDiagnostic.a,
firDiagnostic.b.map { coneKotlinType ->
firSymbolBuilder.typeBuilder.buildKtType(coneKotlinType)
},
firDiagnostic.c,
firDiagnostic.d,
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.warningFactory) { firDiagnostic ->
InferredTypeVariableIntoEmptyIntersectionWarningImpl(
firDiagnostic.a,
firDiagnostic.b.map { coneKotlinType ->
firSymbolBuilder.typeBuilder.buildKtType(coneKotlinType)
@@ -1579,8 +1579,16 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val kotlinClass: FqName
}
abstract class InferredTypeVariableIntoEmptyIntersection : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = InferredTypeVariableIntoEmptyIntersection::class
abstract class InferredTypeVariableIntoEmptyIntersectionError : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = InferredTypeVariableIntoEmptyIntersectionError::class
abstract val typeVariableDescription: String
abstract val incompatibleTypes: List<KtType>
abstract val description: String
abstract val causingTypes: String
}
abstract class InferredTypeVariableIntoEmptyIntersectionWarning : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = InferredTypeVariableIntoEmptyIntersectionWarning::class
abstract val typeVariableDescription: String
abstract val incompatibleTypes: List<KtType>
abstract val description: String
@@ -1899,14 +1899,23 @@ internal class PlatformClassMappedToKotlinImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.PlatformClassMappedToKotlin(), KtAbstractFirDiagnostic<PsiElement>
internal class InferredTypeVariableIntoEmptyIntersectionImpl(
internal class InferredTypeVariableIntoEmptyIntersectionErrorImpl(
override val typeVariableDescription: String,
override val incompatibleTypes: List<KtType>,
override val description: String,
override val causingTypes: String,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.InferredTypeVariableIntoEmptyIntersection(), KtAbstractFirDiagnostic<PsiElement>
) : KtFirDiagnostic.InferredTypeVariableIntoEmptyIntersectionError(), KtAbstractFirDiagnostic<PsiElement>
internal class InferredTypeVariableIntoEmptyIntersectionWarningImpl(
override val typeVariableDescription: String,
override val incompatibleTypes: List<KtType>,
override val description: String,
override val causingTypes: String,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.InferredTypeVariableIntoEmptyIntersectionWarning(), KtAbstractFirDiagnostic<PsiElement>
internal class InferredTypeVariableIntoPossibleEmptyIntersectionImpl(
override val typeVariableDescription: String,
@@ -737,7 +737,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<FqName>("kotlinClass")
}
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error<PsiElement> {
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by deprecationError<PsiElement>(
LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection
) {
parameter<String>("typeVariableDescription")
parameter<Collection<ConeKotlinType>>("incompatibleTypes")
parameter<String>("description")
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.builtins.functions.FunctionTypeKind
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageFeature.ForbidExposingTypesInPrimaryConstructorProperties
import org.jetbrains.kotlin.config.LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection
import org.jetbrains.kotlin.config.LanguageFeature.ForbidUsingExtensionPropertyTypeParameterInDelegate
import org.jetbrains.kotlin.config.LanguageFeature.ModifierNonBuiltinSuspendFunError
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitAssigningSingleElementsToVarargsInNamedForm
@@ -433,7 +434,7 @@ object FirErrors {
val SMARTCAST_IMPOSSIBLE by error4<KtExpression, ConeKotlinType, FirExpression, String, Boolean>()
val REDUNDANT_NULLABLE by warning0<KtTypeReference>(SourceElementPositioningStrategies.REDUNDANT_NULLABLE)
val PLATFORM_CLASS_MAPPED_TO_KOTLIN by warning1<PsiElement, FqName>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error4<PsiElement, String, Collection<ConeKotlinType>, String, String>()
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by deprecationError4<PsiElement, String, Collection<ConeKotlinType>, String, String>(ForbidInferringTypeVariablesIntoEmptyIntersection)
val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning4<PsiElement, String, Collection<ConeKotlinType>, String, String>()
val INCORRECT_LEFT_COMPONENT_OF_INTERSECTION by error0<KtTypeReference>()
val INCORRECT_RIGHT_COMPONENT_OF_INTERSECTION by error0<KtTypeReference>()
@@ -292,8 +292,13 @@ private fun mapInapplicableCandidateError(
)
}
is InferredEmptyIntersectionDiagnostic -> reportInferredIntoEmptyIntersectionError(
source, rootCause.typeVariable, rootCause.incompatibleTypes, rootCause.causingTypes, rootCause.kind
is InferredEmptyIntersectionDiagnostic -> reportInferredIntoEmptyIntersection(
source,
rootCause.typeVariable,
rootCause.incompatibleTypes,
rootCause.causingTypes,
rootCause.kind,
isError = rootCause.isError
)
else -> genericDiagnostic
@@ -434,12 +439,13 @@ private fun ConstraintSystemError.toDiagnostic(
is InferredEmptyIntersection -> {
@Suppress("UNCHECKED_CAST")
reportInferredIntoEmptyIntersectionError(
reportInferredIntoEmptyIntersection(
source,
typeVariable as ConeTypeVariable,
incompatibleTypes as Collection<ConeKotlinType>,
causingTypes as Collection<ConeKotlinType>,
kind
kind,
this is InferredEmptyIntersectionError,
)
}
@@ -454,20 +460,24 @@ private fun ConstraintSystemError.toDiagnostic(
}
}
private fun reportInferredIntoEmptyIntersectionError(
private fun reportInferredIntoEmptyIntersection(
source: KtSourceElement,
typeVariable: ConeTypeVariable,
incompatibleTypes: Collection<ConeKotlinType>,
causingTypes: Collection<ConeKotlinType>,
kind: EmptyIntersectionTypeKind
kind: EmptyIntersectionTypeKind,
isError: Boolean
): KtDiagnostic? {
val typeVariableText =
(typeVariable.typeConstructor.originalTypeParameter as? ConeTypeParameterLookupTag)?.name?.asString()
?: typeVariable.toString()
val causingTypesText = if (incompatibleTypes == causingTypes) "" else ": ${causingTypes.joinToString()}"
val factory =
if (kind.isDefinitelyEmpty) FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION
else FirErrors.INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION
when {
!kind.isDefinitelyEmpty -> FirErrors.INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION
isError -> FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.errorFactory
else -> FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.warningFactory
}
return factory.createOn(source, typeVariableText, incompatibleTypes, kind.description, causingTypesText)
}
@@ -597,7 +597,10 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionStage() {
upperTypes as List<ConeKotlinType>,
emptyIntersectionTypeInfo.casingTypes.toList() as List<ConeKotlinType>,
variableWithConstraints.typeVariable as ConeTypeVariable,
emptyIntersectionTypeInfo.kind
emptyIntersectionTypeInfo.kind,
isError = context.session.languageVersionSettings.supportsFeature(
LanguageFeature.ForbidInferringTypeVariablesIntoEmptyIntersection
)
)
)
}
@@ -33,7 +33,8 @@ class InferredEmptyIntersectionDiagnostic(
val incompatibleTypes: Collection<ConeKotlinType>,
val causingTypes: Collection<ConeKotlinType>,
val typeVariable: ConeTypeVariable,
val kind: EmptyIntersectionTypeKind
val kind: EmptyIntersectionTypeKind,
val isError: Boolean
) : ResolutionDiagnostic(INAPPLICABLE)
class TooManyArguments(
@@ -27,7 +27,7 @@ fun test3() = run {
incompatibleI() // ? either uninferred T or error (Unit </: I)
}
fun test4() = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>run<!> {
fun test4() = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>run<!> {
if (p) return@run
incompatibleC() // ? either uninferred T or error (Unit </: C)
}
@@ -47,7 +47,7 @@ fun test(i: Inv<Nothing>, iUnit: Inv<Unit>) {
if (iUnit is String) {
launch {
run(A.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>flexible<!>(iUnit)) { 42 }
run(A.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>flexible<!>(iUnit)) { 42 }
}
}
}
@@ -1,37 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
abstract class Foo<T>
abstract class Bar<T> : Foo<T>(), Comparable<Bar<T>>
object Scope {
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>) {}
object Nested {
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {}
fun test(b: Bar<Long>) {
<!DEBUG_INFO_CALL("fqName: Scope.greater; typeCall: function")!>greater(b, b)<!>
}
}
}
object OnlyOne {
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {}
fun test(b: Bar<Long>) {
<!DEBUG_INFO_CALL("fqName: OnlyOne.greater; typeCall: function")!><!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>greater<!>(b, b)<!>
}
}
object GoodOldCandidate {
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, t: T) {}
object Nested {
fun <T : Comparable<T>, S : T> greater(x: Bar<in S>, other: Foo<T>) {}
fun test(b: Bar<Long>) {
<!DEBUG_INFO_CALL("fqName: GoodOldCandidate.Nested.greater; typeCall: function")!>greater(b, b)<!>
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
abstract class Foo<T>
@@ -1,11 +0,0 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T>
class Bar<T> {
fun <S : T> takeFoo(foo: Foo<in S>) {}
}
fun main() {
val foo = Foo<Int>()
Bar<String>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T>
@@ -1,13 +0,0 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T>
class Bar<T> {
fun <S : T> takeFoo(foo: Foo<in S>) {}
}
interface A
fun <K : L, L : N, N> main() where N: A, N: Number {
val foo = Foo<K>()
Bar<String>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T>
@@ -1,11 +0,0 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T>
class Bar<T> {
fun <S : T> takeFoo(foo: Foo<in S>) {}
}
fun <K : <!FINAL_UPPER_BOUND!>Int<!>> main() {
val foo = Foo<K>()
Bar<String>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T>
@@ -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("S; kotlin/String, K; multiple incompatible classes; : kotlin/String, kotlin/Int")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
val x: Float = Bar<String>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_ERROR("S; kotlin/String, K; multiple incompatible classes; : kotlin/String, kotlin/Int")!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
}
@@ -1,11 +0,0 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T>
class Bar<T> {
fun <S : T> takeFoo(foo: Foo<in S>) {}
}
fun <K : L, L : N, N: Number> main() {
val foo = Foo<K>()
Bar<String>().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>takeFoo<!>(foo) // error in 1.3.72, no error in 1.4.31
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T>
@@ -1,17 +0,0 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
open class A<T1, T2> {}
class B {
fun <T1: Number, T2: A<Float, T1>> foo(x1: T2, x2: T1) {}
}
class C<T: D, T2>(val x: T, val y: T2) {
fun test() {
B().<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>foo<!>(x, foo())
}
}
open class D: A<Float, Number>()
fun <T: <!FINAL_UPPER_BOUND!>String<!>> foo(): T {
return "" <!UNCHECKED_CAST!>as T<!> // this cast is safe because String is final.
}
fun main() {
C(D(), 10.5).test()
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// RENDER_DIAGNOSTICS_FULL_TEXT
open class A<T1, T2> {}
class B {
@@ -1,11 +0,0 @@
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
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
open class Base
open class DoesNotImplementBase
@@ -1,11 +0,0 @@
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!>exampleGenericFunction<!>(func) // expected this to be a compilation error as the T: Base constraint should not be satisfied
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
open class Base
class DoesNotImplementBase
@@ -5,7 +5,7 @@ fun box(): String {
return try {
val range1 = 0..1
range1 <!CAST_NEVER_SUCCEEDS!>as<!> List<Double>
range1.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>joinToString<!> { "" }
range1.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>joinToString<!> { "" }
} catch (e: java.lang.ClassCastException) {
"OK"
}
@@ -1,11 +0,0 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
open class Foo
inline fun <reified T : Foo> g(): T? = null
inline fun <R> f(block: ()->R?): R? {
return block()
}
fun main() {
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>f<!><Int> { g() }
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// RENDER_DIAGNOSTICS_FULL_TEXT
open class Foo
inline fun <reified T : Foo> g(): T? = null
@@ -1,7 +0,0 @@
fun <T : <!FINAL_UPPER_BOUND!>String<!>> g(): T? = null
fun <R> f(block: () -> R?): R? = block()
fun main() {
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>f<!><Int> { g() /* OK, g() is inferred into {Int & String}? */ }
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
fun <T : <!FINAL_UPPER_BOUND!>String<!>> g(): T? = null
fun <R> f(block: () -> R?): R? = block()
@@ -1,20 +0,0 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
// !DIAGNOSTICS: -UNUSED_PARAMETER
class In<in T>
class Out<out T>
class A
class B
fun <K> select(x: K, y: K): K = x
fun <V> genericIn(x: In<V>) {}
fun <V> genericOut(x: Out<V>) {}
fun test1(a: In<A>, b: In<B>) {
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>genericIn<!>(select(a, b))
}
fun test2(a: Out<A>, b: Out<B>) {
genericOut(select(a, b))
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// RENDER_DIAGNOSTICS_FULL_TEXT
// !DIAGNOSTICS: -UNUSED_PARAMETER
@@ -9,7 +9,7 @@ fun <T : Foo> foo(): T? {
}
fun main() {
val a: Bar? = <!DEBUG_INFO_EXPRESSION_TYPE("Foo? & Bar?")!><!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>foo<!>()<!>
val a: Bar? = <!DEBUG_INFO_EXPRESSION_TYPE("Foo? & Bar?")!><!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>foo<!>()<!>
}
@@ -39,7 +39,7 @@ 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 = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>findViewById11<!>()
fun test11(): View4 = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>findViewById11<!>()
object Obj {
fun <T: I> findViewById1(): T = null as T
@@ -73,7 +73,7 @@ object Obj {
fun test10(): View1 = findViewById10()
fun <T: View2> findViewById11(): T = null as T
fun test11(): View4 = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>findViewById11<!>()
fun test11(): View4 = <!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>findViewById11<!>()
}
interface A
@@ -1,25 +0,0 @@
// !LANGUAGE: +ForbidInferringTypeVariablesIntoEmptyIntersection
// FILE: ObjectNode.java
public interface ObjectNode {
<T extends JsonNode> T set(String fieldName, JsonNode value);
}
// FILE: JsonNode.java
public class JsonNode
// FILE: test.kt
interface JsonObject
class SomeJsonObject() : JsonObject
fun String.put(value: JsonObject?, node: ObjectNode) {
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>when (value) {
null -> node.set(this, null)
is SomeJsonObject -> Unit
else -> TODO()
}<!>
}
fun TODO(): Nothing = null!!
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +ForbidInferringTypeVariablesIntoEmptyIntersection
// FILE: ObjectNode.java
@@ -1,25 +0,0 @@
// !LANGUAGE: -ForbidInferringTypeVariablesIntoEmptyIntersection
// FILE: ObjectNode.java
public interface ObjectNode {
<T extends JsonNode> T set(String fieldName, JsonNode value);
}
// FILE: JsonNode.java
public class JsonNode
// FILE: test.kt
interface JsonObject
class SomeJsonObject() : JsonObject
fun String.put(value: JsonObject?, node: ObjectNode) {
<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>when (value) {
null -> node.set(this, null)
is SomeJsonObject -> Unit
else -> TODO()
}<!>
}
fun TODO(): Nothing = null!!
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: -ForbidInferringTypeVariablesIntoEmptyIntersection
// FILE: ObjectNode.java
@@ -1,12 +0,0 @@
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.greater<String, Nothing>("0")
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
class Expression<T>(val x: T)
class GreaterOp(val expr1: Expression<*>, val expr2: Expression<*>)
@@ -7,5 +7,5 @@ fun test1(l: List<Number>) {
val i: Int = l.firstTyped()
val s: String = l.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION!>firstTyped<!>()
val s: String = l.<!INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION_WARNING!>firstTyped<!>()
}