From a06c8786df25aa1189cb932f521cc152905c3aa5 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Tue, 23 Jun 2020 00:13:15 +0300 Subject: [PATCH] Fix overload ambiguity after smartcast to nullable Nothing #KT-39544 Fixed --- ...irOldFrontendDiagnosticsTestGenerated.java | 5 ++++ .../calls/components/ArgumentsUtils.kt | 9 ++++++ .../tests/smartCasts/alwaysNullWithJava.kt | 2 +- ...rtcastToNothingAfterCheckingForNull.fir.kt | 29 +++++++++++++++++++ .../smartcastToNothingAfterCheckingForNull.kt | 29 +++++++++++++++++++ ...smartcastToNothingAfterCheckingForNull.txt | 22 ++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 5 ++++ .../DiagnosticsUsingJavacTestGenerated.java | 5 ++++ 8 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.fir.kt create mode 100644 compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.kt create mode 100644 compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.txt diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index 441ed8fde0f..1c57e074a8d 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -21422,6 +21422,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastOnSameFieldOfDifferentInstances.kt"); } + @TestMetadata("smartcastToNothingAfterCheckingForNull.kt") + public void testSmartcastToNothingAfterCheckingForNull() throws Exception { + runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.kt"); + } + @TestMetadata("thisWithLabel.kt") public void testThisWithLabel() throws Exception { runTest("compiler/testData/diagnostics/tests/smartCasts/thisWithLabel.kt"); diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt index 66f9dd43567..6671208b147 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ArgumentsUtils.kt @@ -32,6 +32,8 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastI import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.checker.intersectWrappedTypes import org.jetbrains.kotlin.types.checker.prepareArgumentTypeRegardingCaptureTypes +import org.jetbrains.kotlin.types.typeUtil.isNullableNothing +import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.addToStdlib.safeAs @@ -71,6 +73,13 @@ val ReceiverValueWithSmartCastInfo.stableType: UnwrappedType */ val intersectionType = intersectWrappedTypes(allOriginalTypes) + // Intersection type of Nothing with any flexible types will be Nothing!. + // This is a bit incorrect as cast to Nothing? or Nothing can result only in Nothing? or Nothing, + // otherwise it'll be possible to pass null to some non-nullable type + if (intersectionType.isNullableNothing() && !intersectionType.isMarkedNullable) { + return intersectionType.makeNullable().unwrap() + } + return prepareArgumentTypeRegardingCaptureTypes(intersectionType) ?: intersectionType } diff --git a/compiler/testData/diagnostics/tests/smartCasts/alwaysNullWithJava.kt b/compiler/testData/diagnostics/tests/smartCasts/alwaysNullWithJava.kt index 276bfdff302..bfa431a3c11 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/alwaysNullWithJava.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/alwaysNullWithJava.kt @@ -11,7 +11,7 @@ public class My { fun test() { val my = My.create() if (my == null) { - my.foo() + my.foo() } } diff --git a/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.fir.kt new file mode 100644 index 00000000000..3e5ac605323 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.fir.kt @@ -0,0 +1,29 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +// FILE: B.java + +public abstract class B implements A {} + +// FILE: test.kt + +interface A { + val content: T +} +fun f(x: Any?) {} +fun f(x: Byte) {} +fun f(x: Char) {} + +fun g(i: Int) {} + +fun g(x: B) { + val y = x.content + if (y == null) { + f(y) + g(y) + } + + if (y is Nothing?) { + f(y) + g(y) + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.kt b/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.kt new file mode 100644 index 00000000000..68d5e749f41 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.kt @@ -0,0 +1,29 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +// FILE: B.java + +public abstract class B implements A {} + +// FILE: test.kt + +interface A { + val content: T +} +fun f(x: Any?) {} +fun f(x: Byte) {} +fun f(x: Char) {} + +fun g(i: Int) {} + +fun g(x: B) { + val y = x.content + if (y == null) { + f(y) + g(y) + } + + if (y is Nothing?) { + f(y) + g(y) + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.txt b/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.txt new file mode 100644 index 00000000000..07b0340ef73 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.txt @@ -0,0 +1,22 @@ +package + +public fun f(/*0*/ x: kotlin.Any?): kotlin.Unit +public fun f(/*0*/ x: kotlin.Byte): kotlin.Unit +public fun f(/*0*/ x: kotlin.Char): kotlin.Unit +public fun g(/*0*/ x: B): kotlin.Unit +public fun g(/*0*/ i: kotlin.Int): kotlin.Unit + +public interface A { + public abstract val content: T + 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 abstract class B : A { + public constructor B() + public abstract override /*1*/ /*fake_override*/ val content: T! + 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/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 9fdf5fca1ef..ec0b4b9cd5e 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -21499,6 +21499,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastOnSameFieldOfDifferentInstances.kt"); } + @TestMetadata("smartcastToNothingAfterCheckingForNull.kt") + public void testSmartcastToNothingAfterCheckingForNull() throws Exception { + runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.kt"); + } + @TestMetadata("thisWithLabel.kt") public void testThisWithLabel() throws Exception { runTest("compiler/testData/diagnostics/tests/smartCasts/thisWithLabel.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index cf83369550e..2f1c9252215 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -21424,6 +21424,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastOnSameFieldOfDifferentInstances.kt"); } + @TestMetadata("smartcastToNothingAfterCheckingForNull.kt") + public void testSmartcastToNothingAfterCheckingForNull() throws Exception { + runTest("compiler/testData/diagnostics/tests/smartCasts/smartcastToNothingAfterCheckingForNull.kt"); + } + @TestMetadata("thisWithLabel.kt") public void testThisWithLabel() throws Exception { runTest("compiler/testData/diagnostics/tests/smartCasts/thisWithLabel.kt");