diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.fir.txt b/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.fir.txt index 465f220857f..4dfaae98256 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.fir.txt @@ -7,5 +7,5 @@ FILE: definetelyNotNullForTypeParameter.kt public final fun foo(computable: R|Out|): R|kotlin/Unit| { } public final fun bar(computable: R|Out|): R|kotlin/Unit| { - R|/foo|(R|/id|(R|/computable|)) + R|/foo|(R|/id|(R|/computable|)) } diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index acf3ec4799e..1fb24221dd3 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -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 { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt index 8b24fb9e583..0b16784e182 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/ConeInferenceContext.kt @@ -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 diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt index 1dff6729d95..d4c8f0e3d50 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt @@ -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() diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt44440.fir.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt44440.fir.kt new file mode 100644 index 00000000000..5bfbe210324 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt44440.fir.kt @@ -0,0 +1,21 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNUSED_EXPRESSION + +interface I + +fun consume(x: WrapperFactory>) {} + +fun test(x: I) { + val y = foo(x) + >")!>y + consume(y) +} + +fun foo( + x: CX, + fn1: (CX) -> Unit = {}, + fn2: (CX?) -> Unit = {} +) = WrapperFactory { Wrapper(fn1, fn2) } + +class WrapperFactory(val creator: () -> W) + +class Wrapper(val fn1: (CX2) -> Unit, val fn2: (CX2?) -> Unit) diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt44440.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt44440.kt new file mode 100644 index 00000000000..5bfbe210324 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt44440.kt @@ -0,0 +1,21 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNUSED_EXPRESSION + +interface I + +fun consume(x: WrapperFactory>) {} + +fun test(x: I) { + val y = foo(x) + >")!>y + consume(y) +} + +fun foo( + x: CX, + fn1: (CX) -> Unit = {}, + fn2: (CX?) -> Unit = {} +) = WrapperFactory { Wrapper(fn1, fn2) } + +class WrapperFactory(val creator: () -> W) + +class Wrapper(val fn1: (CX2) -> Unit, val fn2: (CX2?) -> Unit) diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt44440.txt b/compiler/testData/diagnostics/tests/inference/regressions/kt44440.txt new file mode 100644 index 00000000000..807941ea2d3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt44440.txt @@ -0,0 +1,28 @@ +package + +public fun consume(/*0*/ x: WrapperFactory>): kotlin.Unit +public fun foo(/*0*/ x: CX, /*1*/ fn1: (CX) -> kotlin.Unit = ..., /*2*/ fn2: (CX?) -> kotlin.Unit = ...): WrapperFactory> +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 { + public constructor Wrapper(/*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 { + public constructor WrapperFactory(/*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 +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 74f5057f586..24216caa2a4 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -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 { diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/12.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/12.fir.kt index d4e97b770a2..12f5812c047 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/12.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/12.fir.kt @@ -464,7 +464,7 @@ fun T?.case_11() { equals(this) itest1() apply { - this + this equals(null) propT propAny @@ -475,29 +475,29 @@ fun T?.case_11() { funNullableT() funNullableAny() itest1() - this.equals(null) - this.propT - this.propAny - this.propNullableT - this.propNullableAny - this.funT() - this.funAny() - this.funNullableT() - this.funNullableAny() - this.itest1() + this.equals(null) + this.propT + this.propAny + this.propNullableT + this.propNullableAny + this.funT() + this.funAny() + this.funNullableT() + this.funNullableAny() + this.itest1() } also { - it - it.itest1() - it.equals(null) - it.propT - it.propAny - it.propNullableT - it.propNullableAny - it.funT() - it.funAny() - it.funNullableT() - it.funNullableAny() + it + it.itest1() + it.equals(null) + it.propT + it.propAny + it.propNullableT + it.propNullableAny + it.funT() + it.funAny() + it.funNullableT() + it.funNullableAny() } } } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/13.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/13.fir.kt index 520b79e3e46..c8701c8a687 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/13.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/13.fir.kt @@ -564,7 +564,7 @@ fun case_11(x: T?) { x.funNullableAny() x.itest() x.apply { - this + this equals(null) propT propAny @@ -575,29 +575,29 @@ fun case_11(x: T?) { funNullableT() funNullableAny() itest() - this.equals(null) - this.propT - this.propAny - this.propNullableT - this.propNullableAny - this.funT() - this.funAny() - this.funNullableT() - this.funNullableAny() - this.itest() + this.equals(null) + this.propT + this.propAny + this.propNullableT + this.propNullableAny + this.funT() + this.funAny() + this.funNullableT() + this.funNullableAny() + this.itest() } x.also { - it - it.itest() - it.equals(null) - it.propT - it.propAny - it.propNullableT - it.propNullableAny - it.funT() - it.funAny() - it.funNullableT() - it.funNullableAny() + it + it.itest() + it.equals(null) + it.propT + it.propAny + it.propNullableT + it.propNullableAny + it.funT() + it.funAny() + it.funNullableT() + it.funNullableAny() } } } diff --git a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt index 9bb9a8020a7..6c7f40d41b6 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/types/model/TypeSystemContext.kt @@ -137,6 +137,8 @@ interface TypeSystemInferenceExtensionContext : TypeSystemContext, TypeSystemBui fun TypeConstructorMarker.isCapturedTypeConstructor(): Boolean + fun TypeConstructorMarker.isTypeParameterTypeConstructor(): Boolean + fun Collection.singleBestRepresentative(): KotlinTypeMarker? fun KotlinTypeMarker.isUnit(): Boolean diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt index d424fe9d778..fa3f585b72e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt @@ -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)