From c75331bf2a685a8ddee0abff2a45ac10f307d5c4 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Wed, 7 Apr 2021 12:57:02 +0300 Subject: [PATCH] Implicit nothing type argument: handle nullable case properly #KT-41620 Fixed --- ...irOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ ...plicitNothingAsTypeParameterCallChecker.kt | 7 ++++++- .../backend/jvm/codegen/ExpressionCodegen.kt | 3 ++- .../nothingType/genericOverride.fir.kt | 12 ++++++++++++ .../inference/nothingType/genericOverride.kt | 12 ++++++++++++ .../inference/nothingType/genericOverride.txt | 19 +++++++++++++++++++ ...ughInformationFromNullabilityConstraint.kt | 4 ++-- .../test/runners/DiagnosticTestGenerated.java | 6 ++++++ .../diagnostics/notLinked/dfa/pos/52.kt | 2 +- 9 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.kt create mode 100644 compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.txt 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 cfb56f00b0c..5147d79bd10 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 @@ -13418,6 +13418,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/inference/nothingType/generateConstraintWithInnerNothingType.kt"); } + @Test + @TestMetadata("genericOverride.kt") + public void testGenericOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.kt"); + } + @Test @TestMetadata("implicitInferenceTToFlexibleNothing.kt") public void testImplicitInferenceTToFlexibleNothing() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ImplicitNothingAsTypeParameterCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ImplicitNothingAsTypeParameterCallChecker.kt index c1072a92f71..90cbba19020 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ImplicitNothingAsTypeParameterCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ImplicitNothingAsTypeParameterCallChecker.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isNothingOrNullableNothing +import org.jetbrains.kotlin.types.typeUtil.isNullableNothing import org.jetbrains.kotlin.types.typeUtil.isTypeParameter object ImplicitNothingAsTypeParameterCallChecker : CallChecker { @@ -61,10 +62,14 @@ object ImplicitNothingAsTypeParameterCallChecker : CallChecker { resolvedCall.candidateDescriptor.valueParameters.filter { it.type.isFunctionOrSuspendFunctionType } .map { it.returnType?.arguments?.last()?.type }.toSet() val unsubstitutedReturnType = resultingDescriptor.original.returnType - val hasImplicitNothing = inferredReturnType?.isNothing() == true && + val hasImplicitNothing = inferredReturnType?.isNothingOrNullableNothing() == true && unsubstitutedReturnType?.isTypeParameter() == true && (TypeUtils.noExpectedType(expectedType) || !expectedType.isNothing()) + if (inferredReturnType?.isNullableNothing() == true && unsubstitutedReturnType?.isMarkedNullable == false) { + return false + } + if (hasImplicitNothing && unsubstitutedReturnType !in lambdasFromArgumentsReturnTypes) { context.trace.reportDiagnosticOnceWrtDiagnosticFactoryList( Errors.IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION.on(reportOn), diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 359e0980657..0208d5af628 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -1079,7 +1079,8 @@ class ExpressionCodegen( nestedTryWithoutFinally: MutableList = arrayListOf(), stop: (LoopInfo) -> Boolean ): LoopInfo? { - return data.handleBlock { + @Suppress("RemoveExplicitTypeArguments") + return data.handleBlock { when { it is TryWithFinallyInfo -> { genFinallyBlock(it, null, endLabel, data, nestedTryWithoutFinally) diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.fir.kt b/compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.fir.kt new file mode 100644 index 00000000000..40b4d243c74 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.fir.kt @@ -0,0 +1,12 @@ +interface A { + fun a(): A +} + +fun error(s: String): Nothing = null!! + +class A1 : A { + override fun a() = test() ?: error("") + + @Suppress("UNCHECKED_CAST") + private fun test(): V? = this as? V +} diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.kt b/compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.kt new file mode 100644 index 00000000000..c53182e60ec --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.kt @@ -0,0 +1,12 @@ +interface A { + fun a(): A +} + +fun error(s: String): Nothing = null!! + +class A1 : A { + override fun a() = test() ?: error("") + + @Suppress("UNCHECKED_CAST") + private fun test(): V? = this as? V +} diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.txt b/compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.txt new file mode 100644 index 00000000000..3c256a31e59 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.txt @@ -0,0 +1,19 @@ +package + +public fun error(/*0*/ s: kotlin.String): kotlin.Nothing + +public interface A { + public abstract fun a(): A + 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 A1 : A { + public constructor A1() + public open override /*1*/ fun a(): kotlin.Nothing + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + @kotlin.Suppress(names = {"UNCHECKED_CAST"}) private final fun test(): V? + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationFromNullabilityConstraint.kt b/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationFromNullabilityConstraint.kt index 161b292d409..ceeccea1614 100644 --- a/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationFromNullabilityConstraint.kt +++ b/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationFromNullabilityConstraint.kt @@ -10,7 +10,7 @@ fun test() { make() ) - select(make(), null) + select(make(), null) - if (true) make() else TODO() + if (true) make() else TODO() } 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 6b0b2b28bb0..a3b52b148cb 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 @@ -13424,6 +13424,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/nothingType/generateConstraintWithInnerNothingType.kt"); } + @Test + @TestMetadata("genericOverride.kt") + public void testGenericOverride() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/genericOverride.kt"); + } + @Test @TestMetadata("implicitInferenceTToFlexibleNothing.kt") public void testImplicitInferenceTToFlexibleNothing() throws Exception { diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/52.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/52.kt index b3dfae0c222..c9cda6797a3 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/52.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/pos/52.kt @@ -119,5 +119,5 @@ fun String> T?.case_11() = this fun case_11() { var x: Int? = 10 x = null - x.case_11() + x.case_11() }