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, token,
) )
} }
add(FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION) { firDiagnostic -> add(FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.errorFactory) { firDiagnostic ->
InferredTypeVariableIntoEmptyIntersectionImpl( 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.a,
firDiagnostic.b.map { coneKotlinType -> firDiagnostic.b.map { coneKotlinType ->
firSymbolBuilder.typeBuilder.buildKtType(coneKotlinType) firSymbolBuilder.typeBuilder.buildKtType(coneKotlinType)
@@ -1579,8 +1579,16 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val kotlinClass: FqName abstract val kotlinClass: FqName
} }
abstract class InferredTypeVariableIntoEmptyIntersection : KtFirDiagnostic<PsiElement>() { abstract class InferredTypeVariableIntoEmptyIntersectionError : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = InferredTypeVariableIntoEmptyIntersection::class 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 typeVariableDescription: String
abstract val incompatibleTypes: List<KtType> abstract val incompatibleTypes: List<KtType>
abstract val description: String abstract val description: String
@@ -1899,14 +1899,23 @@ internal class PlatformClassMappedToKotlinImpl(
override val token: KtLifetimeToken, override val token: KtLifetimeToken,
) : KtFirDiagnostic.PlatformClassMappedToKotlin(), KtAbstractFirDiagnostic<PsiElement> ) : KtFirDiagnostic.PlatformClassMappedToKotlin(), KtAbstractFirDiagnostic<PsiElement>
internal class InferredTypeVariableIntoEmptyIntersectionImpl( internal class InferredTypeVariableIntoEmptyIntersectionErrorImpl(
override val typeVariableDescription: String, override val typeVariableDescription: String,
override val incompatibleTypes: List<KtType>, override val incompatibleTypes: List<KtType>,
override val description: String, override val description: String,
override val causingTypes: String, override val causingTypes: String,
override val firDiagnostic: KtPsiDiagnostic, override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken, 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( internal class InferredTypeVariableIntoPossibleEmptyIntersectionImpl(
override val typeVariableDescription: String, override val typeVariableDescription: String,
@@ -737,7 +737,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<FqName>("kotlinClass") 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<String>("typeVariableDescription")
parameter<Collection<ConeKotlinType>>("incompatibleTypes") parameter<Collection<ConeKotlinType>>("incompatibleTypes")
parameter<String>("description") 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.ApiVersion
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageFeature.ForbidExposingTypesInPrimaryConstructorProperties 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.ForbidUsingExtensionPropertyTypeParameterInDelegate
import org.jetbrains.kotlin.config.LanguageFeature.ModifierNonBuiltinSuspendFunError import org.jetbrains.kotlin.config.LanguageFeature.ModifierNonBuiltinSuspendFunError
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitAssigningSingleElementsToVarargsInNamedForm import org.jetbrains.kotlin.config.LanguageFeature.ProhibitAssigningSingleElementsToVarargsInNamedForm
@@ -433,7 +434,7 @@ object FirErrors {
val SMARTCAST_IMPOSSIBLE by error4<KtExpression, ConeKotlinType, FirExpression, String, Boolean>() val SMARTCAST_IMPOSSIBLE by error4<KtExpression, ConeKotlinType, FirExpression, String, Boolean>()
val REDUNDANT_NULLABLE by warning0<KtTypeReference>(SourceElementPositioningStrategies.REDUNDANT_NULLABLE) 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 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 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_LEFT_COMPONENT_OF_INTERSECTION by error0<KtTypeReference>()
val INCORRECT_RIGHT_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( is InferredEmptyIntersectionDiagnostic -> reportInferredIntoEmptyIntersection(
source, rootCause.typeVariable, rootCause.incompatibleTypes, rootCause.causingTypes, rootCause.kind source,
rootCause.typeVariable,
rootCause.incompatibleTypes,
rootCause.causingTypes,
rootCause.kind,
isError = rootCause.isError
) )
else -> genericDiagnostic else -> genericDiagnostic
@@ -434,12 +439,13 @@ private fun ConstraintSystemError.toDiagnostic(
is InferredEmptyIntersection -> { is InferredEmptyIntersection -> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
reportInferredIntoEmptyIntersectionError( reportInferredIntoEmptyIntersection(
source, source,
typeVariable as ConeTypeVariable, typeVariable as ConeTypeVariable,
incompatibleTypes as Collection<ConeKotlinType>, incompatibleTypes as Collection<ConeKotlinType>,
causingTypes 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, source: KtSourceElement,
typeVariable: ConeTypeVariable, typeVariable: ConeTypeVariable,
incompatibleTypes: Collection<ConeKotlinType>, incompatibleTypes: Collection<ConeKotlinType>,
causingTypes: Collection<ConeKotlinType>, causingTypes: Collection<ConeKotlinType>,
kind: EmptyIntersectionTypeKind kind: EmptyIntersectionTypeKind,
isError: Boolean
): KtDiagnostic? { ): KtDiagnostic? {
val typeVariableText = val typeVariableText =
(typeVariable.typeConstructor.originalTypeParameter as? ConeTypeParameterLookupTag)?.name?.asString() (typeVariable.typeConstructor.originalTypeParameter as? ConeTypeParameterLookupTag)?.name?.asString()
?: typeVariable.toString() ?: typeVariable.toString()
val causingTypesText = if (incompatibleTypes == causingTypes) "" else ": ${causingTypes.joinToString()}" val causingTypesText = if (incompatibleTypes == causingTypes) "" else ": ${causingTypes.joinToString()}"
val factory = val factory =
if (kind.isDefinitelyEmpty) FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION when {
else FirErrors.INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION !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) return factory.createOn(source, typeVariableText, incompatibleTypes, kind.description, causingTypesText)
} }
@@ -597,7 +597,10 @@ internal object CheckIncompatibleTypeVariableUpperBounds : ResolutionStage() {
upperTypes as List<ConeKotlinType>, upperTypes as List<ConeKotlinType>,
emptyIntersectionTypeInfo.casingTypes.toList() as List<ConeKotlinType>, emptyIntersectionTypeInfo.casingTypes.toList() as List<ConeKotlinType>,
variableWithConstraints.typeVariable as ConeTypeVariable, 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 incompatibleTypes: Collection<ConeKotlinType>,
val causingTypes: Collection<ConeKotlinType>, val causingTypes: Collection<ConeKotlinType>,
val typeVariable: ConeTypeVariable, val typeVariable: ConeTypeVariable,
val kind: EmptyIntersectionTypeKind val kind: EmptyIntersectionTypeKind,
val isError: Boolean
) : ResolutionDiagnostic(INAPPLICABLE) ) : ResolutionDiagnostic(INAPPLICABLE)
class TooManyArguments( class TooManyArguments(
@@ -27,7 +27,7 @@ fun test3() = run {
incompatibleI() // ? either uninferred T or error (Unit </: I) 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 if (p) return@run
incompatibleC() // ? either uninferred T or error (Unit </: C) incompatibleC() // ? either uninferred T or error (Unit </: C)
} }
@@ -47,7 +47,7 @@ fun test(i: Inv<Nothing>, iUnit: Inv<Unit>) {
if (iUnit is String) { if (iUnit is String) {
launch { 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 // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
abstract class Foo<T> 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 // RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T> 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 // RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T> 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 // RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T> class Foo<T>
@@ -8,5 +8,5 @@ class Bar<T> {
fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Int<!>> main() { fun <K : L, L : N, N: <!FINAL_UPPER_BOUND!>Int<!>> main() {
val foo = Foo<K>() 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 // RENDER_DIAGNOSTICS_FULL_TEXT
class Foo<T> 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 // RENDER_DIAGNOSTICS_FULL_TEXT
open class A<T1, T2> {} open class A<T1, T2> {}
class B { 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 Base
open class DoesNotImplementBase 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 open class Base
class DoesNotImplementBase class DoesNotImplementBase
@@ -5,7 +5,7 @@ fun box(): String {
return try { return try {
val range1 = 0..1 val range1 = 0..1
range1 <!CAST_NEVER_SUCCEEDS!>as<!> List<Double> 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) { } catch (e: java.lang.ClassCastException) {
"OK" "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 // RENDER_DIAGNOSTICS_FULL_TEXT
open class Foo open class Foo
inline fun <reified T : Foo> g(): T? = null 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 <T : <!FINAL_UPPER_BOUND!>String<!>> g(): T? = null
fun <R> f(block: () -> R?): R? = block() 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 // RENDER_DIAGNOSTICS_FULL_TEXT
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
@@ -9,7 +9,7 @@ fun <T : Foo> foo(): T? {
} }
fun main() { 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 test10(): I = findViewById10()
fun <T: View2> findViewById11(): T = null as T 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 { object Obj {
fun <T: I> findViewById1(): T = null as T fun <T: I> findViewById1(): T = null as T
@@ -73,7 +73,7 @@ object Obj {
fun test10(): View1 = findViewById10() fun test10(): View1 = findViewById10()
fun <T: View2> findViewById11(): T = null as T 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 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 // !LANGUAGE: +ForbidInferringTypeVariablesIntoEmptyIntersection
// FILE: ObjectNode.java // 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 // !LANGUAGE: -ForbidInferringTypeVariablesIntoEmptyIntersection
// FILE: ObjectNode.java // 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 Expression<T>(val x: T)
class GreaterOp(val expr1: Expression<*>, val expr2: Expression<*>) class GreaterOp(val expr1: Expression<*>, val expr2: Expression<*>)
@@ -7,5 +7,5 @@ fun test1(l: List<Number>) {
val i: Int = l.firstTyped() 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<!>()
} }