K2: support ForbidInferringTypeVariablesIntoEmptyIntersection on/off
This commit is contained in:
committed by
Space Team
parent
f7544aff62
commit
b64cb67370
+14
-2
@@ -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)
|
||||
|
||||
+10
-2
@@ -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
|
||||
|
||||
+11
-2
@@ -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,
|
||||
|
||||
+3
-1
@@ -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")
|
||||
|
||||
+2
-1
@@ -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>()
|
||||
|
||||
+18
-8
@@ -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
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
+2
-1
@@ -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(
|
||||
|
||||
+1
-1
@@ -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)
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-37
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
|
||||
|
||||
abstract class Foo<T>
|
||||
|
||||
-11
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
class Foo<T>
|
||||
|
||||
|
||||
-13
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
class Foo<T>
|
||||
|
||||
|
||||
-11
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
class Foo<T>
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
|
||||
-11
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
class Foo<T>
|
||||
|
||||
|
||||
-17
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
open class A<T1, T2> {}
|
||||
class B {
|
||||
|
||||
-11
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
open class Base
|
||||
open class DoesNotImplementBase
|
||||
|
||||
|
||||
-11
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
open class Base
|
||||
class DoesNotImplementBase
|
||||
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
|
||||
-11
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
open class Foo
|
||||
inline fun <reified T : Foo> g(): T? = null
|
||||
|
||||
-7
@@ -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}? */ }
|
||||
}
|
||||
Vendored
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
fun <T : <!FINAL_UPPER_BOUND!>String<!>> g(): T? = null
|
||||
|
||||
fun <R> f(block: () -> R?): R? = block()
|
||||
|
||||
-20
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// RENDER_DIAGNOSTICS_FULL_TEXT
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -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<*>)
|
||||
|
||||
compiler/testData/diagnostics/testsWithStdLib/inference/annotationsForResolve/exactAnnotation.fir.kt
Vendored
+1
-1
@@ -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<!>()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user