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 d20edf07c93..4f277f7ced1 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 @@ -9179,12 +9179,24 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); } + @Test + @TestMetadata("approximation.kt") + public void testApproximation() throws Exception { + runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/approximation.kt"); + } + @Test @TestMetadata("disabledFeature.kt") public void testDisabledFeature() throws Exception { runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/disabledFeature.kt"); } + @Test + @TestMetadata("inference.kt") + public void testInference() throws Exception { + runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.kt"); + } + @Test @TestMetadata("notApplicable.kt") public void testNotApplicable() throws Exception { 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 ec765dd8fb5..452994785c4 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/types/AbstractTypeApproximator.kt @@ -365,7 +365,7 @@ abstract class AbstractTypeApproximator( return typeWithErasedNullability } - return if (conf.definitelyNotNullType) { + return if (conf.definitelyNotNullType || languageVersionSettings.supportsFeature(LanguageFeature.DefinitelyNotNullTypeParameters)) { approximatedOriginalType?.makeDefinitelyNotNullOrNotNull() } else { if (toSuper) diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/approximation.fir.kt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/approximation.fir.kt new file mode 100644 index 00000000000..36679f0c4c4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/approximation.fir.kt @@ -0,0 +1,14 @@ +// !LANGUAGE: +DefinitelyNotNullTypeParameters + +fun foo(x: T, y: T!!) = 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/explicitDefinitelyNotNull/approximation.kt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/approximation.kt new file mode 100644 index 00000000000..75b56913297 --- /dev/null +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/approximation.kt @@ -0,0 +1,14 @@ +// !LANGUAGE: +DefinitelyNotNullTypeParameters + +fun foo(x: T, y: T!!) = 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/explicitDefinitelyNotNull/approximation.txt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/approximation.txt new file mode 100644 index 00000000000..db1673f7a72 --- /dev/null +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/approximation.txt @@ -0,0 +1,4 @@ +package + +public fun foo(/*0*/ x: T, /*1*/ y: T!!): T!! +public fun main(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.fir.kt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.fir.kt new file mode 100644 index 00000000000..ef72c1e2395 --- /dev/null +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.fir.kt @@ -0,0 +1,33 @@ +// !LANGUAGE: +DefinitelyNotNullTypeParameters + +fun toDefNotNull(s: T): T!! = s!! + +fun removeQuestionMark(x: K?): K = x!! + +fun Any.foo() {} + +fun expectNN(e: E!!) {} + +fun main(x: F, y: F, z: F, w: F, m: F) { + val y1 = toDefNotNull(x) // K instead of K!! + val y2: F!! = toDefNotNull(x) // K instead of K!! + val x1 = removeQuestionMark(x) // T or T!! + val x2: F!! = removeQuestionMark(x) // T or T!! + + val z1 = x!! + val z2: F!! = y!! + val w1 = if (z != null) z else return + val w2: F!! = if (w != null) w else return + + y1.foo() + y2.foo() + x1.foo() + x2.foo() + z1.foo() + z2.foo() + w1.foo() + w2.foo() + + expectNN(m) + expectNN(m!!) +} diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.kt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.kt new file mode 100644 index 00000000000..5fa140d37e6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.kt @@ -0,0 +1,33 @@ +// !LANGUAGE: +DefinitelyNotNullTypeParameters + +fun toDefNotNull(s: T): T!! = s!! + +fun removeQuestionMark(x: K?): K = x!! + +fun Any.foo() {} + +fun expectNN(e: E!!) {} + +fun main(x: F, y: F, z: F, w: F, m: F) { + val y1 = toDefNotNull(x) // K instead of K!! + val y2: F!! = toDefNotNull(x) // K instead of K!! + val x1 = removeQuestionMark(x) // T or T!! + val x2: F!! = removeQuestionMark(x) // T or T!! + + val z1 = x!! + val z2: F!! = y!! + val w1 = if (z != null) z else return + val w2: F!! = if (w != null) w else return + + y1.foo() + y2.foo() + x1.foo() + x2.foo() + z1.foo() + z2.foo() + w1.foo() + w2.foo() + + expectNN(m) + expectNN(m!!) +} diff --git a/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.txt b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.txt new file mode 100644 index 00000000000..b41a53165e8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.txt @@ -0,0 +1,7 @@ +package + +public fun expectNN(/*0*/ e: E!!): kotlin.Unit +public fun main(/*0*/ x: F, /*1*/ y: F, /*2*/ z: F, /*3*/ w: F, /*4*/ m: F): kotlin.Unit +public fun removeQuestionMark(/*0*/ x: K?): K +public fun toDefNotNull(/*0*/ s: T): T!! +public fun kotlin.Any.foo(): kotlin.Unit 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 f61be2267b7..9143d6fc5ed 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 @@ -9185,12 +9185,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); } + @Test + @TestMetadata("approximation.kt") + public void testApproximation() throws Exception { + runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/approximation.kt"); + } + @Test @TestMetadata("disabledFeature.kt") public void testDisabledFeature() throws Exception { runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/disabledFeature.kt"); } + @Test + @TestMetadata("inference.kt") + public void testInference() throws Exception { + runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.kt"); + } + @Test @TestMetadata("notApplicable.kt") public void testNotApplicable() throws Exception {