diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 958657ee28b..c3292a06f27 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -15156,6 +15156,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt"); } + @Test + @TestMetadata("nullableArgumentForDnn.kt") + public void testNullableArgumentForDnn() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nullableArgumentForDnn.kt"); + } + @Test @TestMetadata("nullableTypeArgumentWithNotNullUpperBound.kt") public void testNullableTypeArgumentWithNotNullUpperBound() throws Exception { @@ -19934,6 +19940,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/j+k/mutableIterator.kt"); } + @Test + @TestMetadata("nullForOptionalOf.kt") + public void testNullForOptionalOf() throws Exception { + runTest("compiler/testData/diagnostics/tests/j+k/nullForOptionalOf.kt"); + } + @Test @TestMetadata("nullForOptionalOrElse.kt") public void testNullForOptionalOrElse() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index db2943df7ac..47d6deb8fe1 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -15156,6 +15156,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt"); } + @Test + @TestMetadata("nullableArgumentForDnn.kt") + public void testNullableArgumentForDnn() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nullableArgumentForDnn.kt"); + } + @Test @TestMetadata("nullableTypeArgumentWithNotNullUpperBound.kt") public void testNullableTypeArgumentWithNotNullUpperBound() throws Exception { @@ -19934,6 +19940,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/j+k/mutableIterator.kt"); } + @Test + @TestMetadata("nullForOptionalOf.kt") + public void testNullForOptionalOf() throws Exception { + runTest("compiler/testData/diagnostics/tests/j+k/nullForOptionalOf.kt"); + } + @Test @TestMetadata("nullForOptionalOrElse.kt") public void testNullForOptionalOrElse() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 937406051ef..d8225972809 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -15156,6 +15156,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt"); } + @Test + @TestMetadata("nullableArgumentForDnn.kt") + public void testNullableArgumentForDnn() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nullableArgumentForDnn.kt"); + } + @Test @TestMetadata("nullableTypeArgumentWithNotNullUpperBound.kt") public void testNullableTypeArgumentWithNotNullUpperBound() throws Exception { @@ -19934,6 +19940,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/j+k/mutableIterator.kt"); } + @Test + @TestMetadata("nullForOptionalOf.kt") + public void testNullForOptionalOf() throws Exception { + runTest("compiler/testData/diagnostics/tests/j+k/nullForOptionalOf.kt"); + } + @Test @TestMetadata("nullForOptionalOrElse.kt") public void testNullForOptionalOrElse() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index 9894dc66248..a51ebd33dd5 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -15162,6 +15162,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt"); } + @Test + @TestMetadata("nullableArgumentForDnn.kt") + public void testNullableArgumentForDnn() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nullableArgumentForDnn.kt"); + } + @Test @TestMetadata("nullableTypeArgumentWithNotNullUpperBound.kt") public void testNullableTypeArgumentWithNotNullUpperBound() throws Exception { @@ -19940,6 +19946,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/j+k/mutableIterator.kt"); } + @Test + @TestMetadata("nullForOptionalOf.kt") + public void testNullForOptionalOf() throws Exception { + runTest("compiler/testData/diagnostics/tests/j+k/nullForOptionalOf.kt"); + } + @Test @TestMetadata("nullForOptionalOrElse.kt") public void testNullForOptionalOrElse() throws Exception { diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerStateForConstraintSystem.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerStateForConstraintSystem.kt index a21ea36594d..3052ed48e67 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerStateForConstraintSystem.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/inference/components/TypeCheckerStateForConstraintSystem.kt @@ -205,6 +205,13 @@ abstract class TypeCheckerStateForConstraintSystem( * (Foo & Any .. Bar) <: T -- (Foo!! .. Bar) <: T * * => (Foo..Bar) <: T! -- (Foo!! .. Bar) <: T + * + * T & Any + * + * Foo? <: T & Any => ERROR (for K2 only) + * + * Foo..Bar? <: T & Any => Foo..Bar? <: T + * Foo <: T & Any => Foo <: T */ private fun simplifyLowerConstraint( typeVariable: KotlinTypeMarker, @@ -213,35 +220,41 @@ abstract class TypeCheckerStateForConstraintSystem( ): Boolean = with(extensionTypeContext) { val lowerConstraint = when (typeVariable) { is SimpleTypeMarker -> - /* - * Foo <: T -- Foo <: T - * Foo <: T? (T is contained in invariant or contravariant positions of a return type) -- Foo <: T - * Example: - * fun foo(x: T?): Inv {} - * fun main(z: K) { val x = foo(z) } - * Foo <: T? (T isn't contained there) -- Foo!! <: T - * Example: - * fun foo(x: T?) {} - * fun main(z: K) { foo(z) } - */ - if (typeVariable.isMarkedNullable()) { - val typeVariableTypeConstructor = typeVariable.typeConstructor() - val subTypeConstructor = subType.typeConstructor() - val needToMakeDefNotNull = subTypeConstructor.isTypeVariable() || - typeVariableTypeConstructor !is TypeVariableTypeConstructorMarker || - !typeVariableTypeConstructor.isContainedInInvariantOrContravariantPositions() + when { + // Foo? (any type which cannot be used as dispatch receiver because of nullability) <: T & Any => ERROR (for K2 only) + isK2 && typeVariable.isDefinitelyNotNullType() + && !AbstractNullabilityChecker.isSubtypeOfAny(extensionTypeContext, subType) -> return false + /* + * Foo <: T? (T is contained in invariant or contravariant positions of a return type) -- Foo <: T + * Example: + * fun foo(x: T?): Inv {} + * fun main(z: K) { val x = foo(z) } + * Foo <: T? (T isn't contained there) -- Foo!! <: T + * Example: + * fun foo(x: T?) {} + * fun main(z: K) { foo(z) } + */ + typeVariable.isMarkedNullable() -> { + val typeVariableTypeConstructor = typeVariable.typeConstructor() + val subTypeConstructor = subType.typeConstructor() + val needToMakeDefNotNull = subTypeConstructor.isTypeVariable() || + typeVariableTypeConstructor !is TypeVariableTypeConstructorMarker || + !typeVariableTypeConstructor.isContainedInInvariantOrContravariantPositions() - val resultType = if (needToMakeDefNotNull) { - subType.makeDefinitelyNotNullOrNotNull() - } else { - if (!isInferenceCompatibilityEnabled && subType is CapturedTypeMarker) { - subType.withNotNullProjection() + val resultType = if (needToMakeDefNotNull) { + subType.makeDefinitelyNotNullOrNotNull() } else { - subType.withNullability(false) + if (!isInferenceCompatibilityEnabled && subType is CapturedTypeMarker) { + subType.withNotNullProjection() + } else { + subType.withNullability(false) + } } + if (isInferenceCompatibilityEnabled && resultType is CapturedTypeMarker) resultType.withNotNullProjection() else resultType } - if (isInferenceCompatibilityEnabled && resultType is CapturedTypeMarker) resultType.withNotNullProjection() else resultType - } else subType + // Foo <: T => Foo <: T + else -> subType + } is FlexibleTypeMarker -> { assertFlexibleTypeVariable(typeVariable) @@ -298,6 +311,7 @@ abstract class TypeCheckerStateForConstraintSystem( * T! <: Foo <=> T <: Foo & Any..Foo? * T? <: Foo <=> T <: Foo && Nothing? <: Foo * T <: Foo -- leave as is + * T & Any <: Foo <=> T <: Foo? */ private fun simplifyUpperConstraint(typeVariable: KotlinTypeMarker, superType: KotlinTypeMarker): Boolean = with(extensionTypeContext) { val typeVariableLowerBound = typeVariable.lowerBoundIfFlexible() diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/approximation.fir.kt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/approximation.fir.kt deleted file mode 100644 index 4731d4970e5..00000000000 --- a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/approximation.fir.kt +++ /dev/null @@ -1,14 +0,0 @@ -// !LANGUAGE: +DefinitelyNonNullableTypes - -fun foo(x: T, y: T & Any) = x!! - -fun main() { - foo("", "").length - foo("", null).length - foo(null, "").length - foo(null, null).length - - foo("", "").length - foo("", null).length - foo(null, "").length -} diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/approximation.kt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/approximation.kt index e8aa31d09ff..e14ad498507 100644 --- a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/approximation.kt +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/approximation.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +DefinitelyNonNullableTypes fun foo(x: T, y: T & Any) = x!! diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/inference.fir.kt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/inference.fir.kt index 33e47c35c47..71dc21387f3 100644 --- a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/inference.fir.kt +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/inference.fir.kt @@ -28,6 +28,6 @@ fun main(x: F, y: F, z: F, w: F, m: F) { w1.foo() w2.foo() - expectNN(m) + expectNN(m) expectNN(m!!) } diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/simple.fir.kt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/simple.fir.kt deleted file mode 100644 index 748219cb353..00000000000 --- a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/simple.fir.kt +++ /dev/null @@ -1,14 +0,0 @@ -// !LANGUAGE: +DefinitelyNonNullableTypes - -fun foo(x: T, y: T & Any): T & Any = x ?: y - -fun main() { - foo("", "").length - foo("", null).length - foo(null, "").length - foo(null, null).length - - foo("", "").length - foo("", null).length - foo(null, "").length -} diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/simple.kt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/simple.kt index 034e857c50e..e006e8e5cde 100644 --- a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/simple.kt +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNullableViaIntersection/simple.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +DefinitelyNonNullableTypes fun foo(x: T, y: T & Any): T & Any = x ?: y diff --git a/compiler/testData/diagnostics/tests/inference/nullableArgumentForDnn.fir.kt b/compiler/testData/diagnostics/tests/inference/nullableArgumentForDnn.fir.kt new file mode 100644 index 00000000000..3cc0e9819b5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nullableArgumentForDnn.fir.kt @@ -0,0 +1,9 @@ +// ISSUE: KT-58665 + +fun use(x: String?, r: R, t: T) { + foo(x) + foo(r) + foo(t) +} + +fun foo(x: W & Any) {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/nullableArgumentForDnn.kt b/compiler/testData/diagnostics/tests/inference/nullableArgumentForDnn.kt new file mode 100644 index 00000000000..0a0d2809fe3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nullableArgumentForDnn.kt @@ -0,0 +1,9 @@ +// ISSUE: KT-58665 + +fun use(x: String?, r: R, t: T) { + foo(x) + foo(r) + foo(t) +} + +fun foo(x: W & Any) {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/nullForOptionalOf.fir.kt b/compiler/testData/diagnostics/tests/j+k/nullForOptionalOf.fir.kt new file mode 100644 index 00000000000..e770060d25f --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/nullForOptionalOf.fir.kt @@ -0,0 +1,8 @@ +// ISSUE: KT-58665 +// FULL_JDK + +import java.util.* + +fun use(x: String?) { + Optional.of(x) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/nullForOptionalOf.kt b/compiler/testData/diagnostics/tests/j+k/nullForOptionalOf.kt new file mode 100644 index 00000000000..2cfa339a3c0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/j+k/nullForOptionalOf.kt @@ -0,0 +1,8 @@ +// ISSUE: KT-58665 +// FULL_JDK + +import java.util.* + +fun use(x: String?) { + Optional.of(x) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/j+k/types/notNullTypeParameterWithKotlinNullable.fir.kt b/compiler/testData/diagnostics/tests/j+k/types/notNullTypeParameterWithKotlinNullable.fir.kt index deed3dd92a9..4fe57a3269a 100644 --- a/compiler/testData/diagnostics/tests/j+k/types/notNullTypeParameterWithKotlinNullable.fir.kt +++ b/compiler/testData/diagnostics/tests/j+k/types/notNullTypeParameterWithKotlinNullable.fir.kt @@ -21,8 +21,8 @@ fun SLRUMap.getOrPut(value: V, l: List) { takeV(value) takeVList(l) - takeE(value) - takeEList(l) + takeE(value) + takeEList(l) takeE(id(value)) if (value != null) { diff --git a/compiler/testData/diagnostics/tests/j+k/types/notNullTypeParameterWithKotlinNullableWarnings.fir.kt b/compiler/testData/diagnostics/tests/j+k/types/notNullTypeParameterWithKotlinNullableWarnings.fir.kt index c9da3698aa1..09e064e0e2a 100644 --- a/compiler/testData/diagnostics/tests/j+k/types/notNullTypeParameterWithKotlinNullableWarnings.fir.kt +++ b/compiler/testData/diagnostics/tests/j+k/types/notNullTypeParameterWithKotlinNullableWarnings.fir.kt @@ -22,8 +22,8 @@ fun SLRUMap.getOrPut(value: V, l: List) { takeV(value) takeVList(l) - takeE(value) - takeEList(l) + takeE(value) + takeEList(l) takeE(id(value)) if (value != null) { diff --git a/compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/methodTypeParameter.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/methodTypeParameter.fir.kt deleted file mode 100644 index 8fd4acd73b7..00000000000 --- a/compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/methodTypeParameter.fir.kt +++ /dev/null @@ -1,18 +0,0 @@ -// FILE: A.java - -import org.jetbrains.annotations.NotNull; - -public class A { - public static void bar(@NotNull T x, T y) { } - public static String platformString() { return null; } -} - -// FILE: k.kt - -fun test() { - A.bar(null, "") - - A.bar(null, "") - A.bar(null, "") - A.bar(null, A.platformString()) -} diff --git a/compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/methodTypeParameter.kt b/compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/methodTypeParameter.kt index cec0554560c..841da97e652 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/methodTypeParameter.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/notNullTypeParameter/methodTypeParameter.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // FILE: A.java import org.jetbrains.annotations.NotNull; 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 b2f769b5c84..c9ad8b5f603 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 @@ -15162,6 +15162,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/nothingVsParameterBound.kt"); } + @Test + @TestMetadata("nullableArgumentForDnn.kt") + public void testNullableArgumentForDnn() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nullableArgumentForDnn.kt"); + } + @Test @TestMetadata("nullableTypeArgumentWithNotNullUpperBound.kt") public void testNullableTypeArgumentWithNotNullUpperBound() throws Exception { @@ -19940,6 +19946,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/j+k/mutableIterator.kt"); } + @Test + @TestMetadata("nullForOptionalOf.kt") + public void testNullForOptionalOf() throws Exception { + runTest("compiler/testData/diagnostics/tests/j+k/nullForOptionalOf.kt"); + } + @Test @TestMetadata("nullForOptionalOrElse.kt") public void testNullForOptionalOrElse() throws Exception {