Approximate definitely not-null types for type parameter's types if they are already not-null (has not-null upper bounds)

^KT-44440 Fixed
This commit is contained in:
Victor Petukhov
2021-01-21 14:57:28 +03:00
parent f2c1608c2b
commit f06a5321a6
12 changed files with 144 additions and 45 deletions
@@ -7,5 +7,5 @@ FILE: definetelyNotNullForTypeParameter.kt
public final fun <F : R|kotlin/Any|> foo(computable: R|Out<F?>|): R|kotlin/Unit| {
}
public final fun <T : R|kotlin/Any|> bar(computable: R|Out<T?>|): R|kotlin/Unit| {
R|/foo|<R|T?!!|>(R|/id|<R|T?|>(R|<local>/computable|))
R|/foo|<R|T|>(R|/id|<R|T?|>(R|<local>/computable|))
}
@@ -14002,6 +14002,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt");
}
@Test
@TestMetadata("kt44440.kt")
public void testKt44440() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt44440.kt");
}
@Test
@TestMetadata("kt702.kt")
public void testKt702() throws Exception {
@@ -360,6 +360,10 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
return this is ConeCapturedTypeConstructor
}
override fun TypeConstructorMarker.isTypeParameterTypeConstructor(): Boolean {
return this.getTypeParameterClassifier() != null
}
override fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker {
// TODO
return this
@@ -338,6 +338,12 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon
val originalType = type.original()
val approximatedOriginalType =
if (toSuper) approximateToSuperType(originalType, conf, depth) else approximateToSubType(originalType, conf, depth)
val typeWithErasedNullability = originalType.withNullability(false)
// Approximate T!! into T if T is already not-null (has not-null upper bounds)
if (originalType.typeConstructor().isTypeParameterTypeConstructor() && !typeWithErasedNullability.isNullableType()) {
return typeWithErasedNullability
}
return if (conf.definitelyNotNullType) {
approximatedOriginalType?.makeDefinitelyNotNullOrNotNull()
@@ -0,0 +1,21 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNUSED_EXPRESSION
interface I
fun consume(x: WrapperFactory<Wrapper<I>>) {}
fun test(x: I) {
val y = foo(x)
<!DEBUG_INFO_EXPRESSION_TYPE("WrapperFactory<Wrapper<I>>")!>y<!>
consume(y)
}
fun <CX: I> foo(
x: CX,
fn1: (CX) -> Unit = {},
fn2: (CX?) -> Unit = {}
) = WrapperFactory { Wrapper(fn1, fn2) }
class WrapperFactory<W>(val creator: () -> W)
class Wrapper<in CX2>(val fn1: (CX2) -> Unit, val fn2: (CX2?) -> Unit)
@@ -0,0 +1,21 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNUSED_EXPRESSION
interface I
fun consume(x: WrapperFactory<Wrapper<I>>) {}
fun test(x: I) {
val y = foo(x)
<!DEBUG_INFO_EXPRESSION_TYPE("WrapperFactory<Wrapper<I>>")!>y<!>
consume(y)
}
fun <CX: I> foo(
x: CX,
fn1: (CX) -> Unit = {},
fn2: (CX?) -> Unit = {}
) = WrapperFactory { Wrapper(fn1, fn2) }
class WrapperFactory<W>(val creator: () -> W)
class Wrapper<in CX2>(val fn1: (CX2) -> Unit, val fn2: (CX2?) -> Unit)
@@ -0,0 +1,28 @@
package
public fun consume(/*0*/ x: WrapperFactory<Wrapper<I>>): kotlin.Unit
public fun </*0*/ CX : I> foo(/*0*/ x: CX, /*1*/ fn1: (CX) -> kotlin.Unit = ..., /*2*/ fn2: (CX?) -> kotlin.Unit = ...): WrapperFactory<Wrapper<CX>>
public fun test(/*0*/ x: I): kotlin.Unit
public interface I {
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 Wrapper</*0*/ in CX2> {
public constructor Wrapper</*0*/ in CX2>(/*0*/ fn1: (CX2) -> kotlin.Unit, /*1*/ fn2: (CX2?) -> kotlin.Unit)
public final val fn1: (CX2) -> kotlin.Unit
public final val fn2: (CX2?) -> kotlin.Unit
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 WrapperFactory</*0*/ W> {
public constructor WrapperFactory</*0*/ W>(/*0*/ creator: () -> W)
public final val creator: () -> W
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
}
@@ -14008,6 +14008,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt");
}
@Test
@TestMetadata("kt44440.kt")
public void testKt44440() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt44440.kt");
}
@Test
@TestMetadata("kt702.kt")
public void testKt702() throws Exception {
@@ -464,7 +464,7 @@ fun <T : Number> T?.case_11() {
equals(this)
itest1()
apply {
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>
equals(null)
propT
propAny
@@ -475,29 +475,29 @@ fun <T : Number> T?.case_11() {
funNullableT()
funNullableAny()
itest1()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.itest1()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.itest1()
}
also {
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.itest1()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.itest1()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.funNullableAny()
}
}
}
@@ -564,7 +564,7 @@ fun <T : Number> case_11(x: T?) {
x.funNullableAny()
x.itest()
x.apply {
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>
equals(null)
propT
propAny
@@ -575,29 +575,29 @@ fun <T : Number> case_11(x: T?) {
funNullableT()
funNullableAny()
itest()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>this<!>.itest()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>this<!>.itest()
}
x.also {
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.itest()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T?!!")!>it<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.itest()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T")!>it<!>.funNullableAny()
}
}
}
@@ -137,6 +137,8 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui
fun TypeConstructorMarker.isCapturedTypeConstructor(): Boolean
fun TypeConstructorMarker.isTypeParameterTypeConstructor(): Boolean
fun Collection<KotlinTypeMarker>.singleBestRepresentative(): KotlinTypeMarker?
fun KotlinTypeMarker.isUnit(): Boolean
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.BuiltInAnnotationDescriptor
import org.jetbrains.kotlin.descriptors.impl.AbstractTypeParameterDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
@@ -573,6 +574,10 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
return this is NewCapturedTypeConstructor
}
override fun TypeConstructorMarker.isTypeParameterTypeConstructor(): Boolean {
return this is AbstractTypeConstructor && this.declarationDescriptor is AbstractTypeParameterDescriptor
}
override fun arrayType(componentType: KotlinTypeMarker): SimpleTypeMarker {
require(componentType is KotlinType, this::errorMessage)
return builtIns.getArrayType(Variance.INVARIANT, componentType)