From cb0b44273db18bc341c237d45e72cda364d63c64 Mon Sep 17 00:00:00 2001 From: Pavel Kirpichenkov Date: Fri, 17 Jan 2020 11:43:50 +0300 Subject: [PATCH] [NI] Check stub types in result type An uninferred parameter stub may leak through calculation of CST(Inv, Nothing) into a result type. A stub type in the result type means a type error. So we can afford recalculating CST with stub-containing types filtered out, since its an error anyway. This prevents stub types leakages and helps with reporting type error diagnostics. KT-35914 Fixed KT-35943 Fixed --- ...irOldFrontendDiagnosticsTestGenerated.java | 10 +++++ .../components/ResultTypeResolver.kt | 20 ++++++++-- .../codegen/box/regressions/kt35914.kt | 15 ++++++++ .../notEnoughInformationAndNothing.fir.kt | 38 +++++++++++++++++++ .../notEnoughInformationAndNothing.kt | 38 +++++++++++++++++++ .../notEnoughInformationAndNothing.txt | 14 +++++++ .../inference/regressions/kt35943.fir.kt | 9 +++++ .../tests/inference/regressions/kt35943.kt | 9 +++++ .../tests/inference/regressions/kt35943.txt | 11 ++++++ .../checkers/DiagnosticsTestGenerated.java | 10 +++++ .../DiagnosticsUsingJavacTestGenerated.java | 10 +++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ .../IrJsCodegenBoxTestGenerated.java | 5 +++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++ 17 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/codegen/box/regressions/kt35914.kt create mode 100644 compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.kt create mode 100644 compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.txt create mode 100644 compiler/testData/diagnostics/tests/inference/regressions/kt35943.fir.kt create mode 100644 compiler/testData/diagnostics/tests/inference/regressions/kt35943.kt create mode 100644 compiler/testData/diagnostics/tests/inference/regressions/kt35943.txt diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index 6a803acd133..14fc16f1f00 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -10861,6 +10861,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/nothingType/nestedLambdaInferenceWithIncorporationOfVariables.kt"); } + @TestMetadata("notEnoughInformationAndNothing.kt") + public void testNotEnoughInformationAndNothing() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.kt"); + } + @TestMetadata("notEnoughInformationFromNullabilityConstraint.kt") public void testNotEnoughInformationFromNullabilityConstraint() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationFromNullabilityConstraint.kt"); @@ -11185,6 +11190,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/inference/regressions/kt35844.kt"); } + @TestMetadata("kt35943.kt") + public void testKt35943() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/regressions/kt35943.kt"); + } + @TestMetadata("kt4420.kt") public void testKt4420() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt"); diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt index 3d6c04093a7..d65374540c6 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ResultTypeResolver.kt @@ -17,13 +17,11 @@ package org.jetbrains.kotlin.resolve.calls.inference.components import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator -import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionStatelessCallbacks import org.jetbrains.kotlin.resolve.calls.inference.components.TypeVariableDirectionCalculator.ResolveDirection import org.jetbrains.kotlin.resolve.calls.inference.model.* import org.jetbrains.kotlin.types.AbstractTypeApproximator import org.jetbrains.kotlin.types.TypeApproximatorConfiguration import org.jetbrains.kotlin.types.model.* -import org.jetbrains.kotlin.utils.addToStdlib.safeAs class ResultTypeResolver( val typeApproximator: AbstractTypeApproximator, @@ -98,9 +96,20 @@ class ResultTypeResolver( if (lowerConstraintTypes.isNotEmpty()) { val types = sinkIntegerLiteralTypes(lowerConstraintTypes) - val commonSuperType = with(NewCommonSuperTypeCalculator) { - this@findSubType.commonSuperType(types) + var commonSuperType = computeCommonSuperType(types) + + if (commonSuperType.contains { it is StubTypeMarker }) { + val typesWithoutStubs = types.filter { lowerType -> + !lowerType.contains { it is StubTypeMarker } + } + + if (typesWithoutStubs.isNotEmpty()) { + commonSuperType = computeCommonSuperType(typesWithoutStubs) + } else { + return null + } } + /** * * fun Array.intersect(other: Iterable) { @@ -128,6 +137,9 @@ class ResultTypeResolver( return null } + private fun Context.computeCommonSuperType(types: List): KotlinTypeMarker = + with(NewCommonSuperTypeCalculator) { commonSuperType(types) } + private fun Context.prepareLowerConstraints(constraints: List): List { var atLeastOneProper = false var atLeastOneNonProper = false diff --git a/compiler/testData/codegen/box/regressions/kt35914.kt b/compiler/testData/codegen/box/regressions/kt35914.kt new file mode 100644 index 00000000000..92483152851 --- /dev/null +++ b/compiler/testData/codegen/box/regressions/kt35914.kt @@ -0,0 +1,15 @@ +// !LANGUAGE: +NewInference +// WITH_RUNTIME +// KJS_WITH_FULL_RUNTIME +// IGNORE_BACKEND_FIR: JVM_IR + +class Inv +fun bar(x: Inv.() -> Unit) = x + +fun box(): String { + listOf( + bar { }, + bar { } // the problem is here + ) + return "OK" +} diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.fir.kt b/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.fir.kt new file mode 100644 index 00000000000..3e58c6b661b --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.fir.kt @@ -0,0 +1,38 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// !CHECK_TYPE + +class Inv +fun materialize(): Inv = TODO() +fun id(arg: K) = arg +fun select(vararg args: S): S = TODO() + +fun test1(b: Boolean?) { + val v = when(b) { + true -> materialize() + false -> null + null -> materialize() + } + v checkType { _?>() } +} + +fun test2() { + select( + materialize() + ) + select(materialize(), materialize()) + select(materialize(), null, Inv()) + select( + materialize(), + null + ) + select( + materialize(), + materialize() + ) + select( + materialize(), + materialize(), + null + ) +} diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.kt b/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.kt new file mode 100644 index 00000000000..33edd7a1e1f --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.kt @@ -0,0 +1,38 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER +// !CHECK_TYPE + +class Inv +fun materialize(): Inv = TODO() +fun id(arg: K) = arg +fun select(vararg args: S): S = TODO() + +fun test1(b: Boolean?) { + val v = when(b) { + true -> materialize() + false -> null + null -> materialize() + } + v checkType { _?>() } +} + +fun test2() { + select( + materialize() + ) + select(materialize(), materialize()) + select(materialize(), null, Inv()) + select( + materialize(), + null + ) + select( + materialize(), + materialize() + ) + select( + materialize(), + materialize(), + null + ) +} diff --git a/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.txt b/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.txt new file mode 100644 index 00000000000..6ad30ff0a2f --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.txt @@ -0,0 +1,14 @@ +package + +public fun id(/*0*/ arg: K): K +public fun materialize(): Inv +public fun select(/*0*/ vararg args: S /*kotlin.Array*/): S +public fun test1(/*0*/ b: kotlin.Boolean?): kotlin.Unit +public fun test2(): kotlin.Unit + +public final class Inv { + public constructor Inv() + 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/testData/diagnostics/tests/inference/regressions/kt35943.fir.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt35943.fir.kt new file mode 100644 index 00000000000..7eb269e5eff --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt35943.fir.kt @@ -0,0 +1,9 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_EXPRESSION + +class Inv +fun create(): Inv = TODO() + +fun main() { + if (true) create() else null +} diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt35943.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt35943.kt new file mode 100644 index 00000000000..1df6a7ca31e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt35943.kt @@ -0,0 +1,9 @@ +// !LANGUAGE: +NewInference +// !DIAGNOSTICS: -UNUSED_EXPRESSION + +class Inv +fun create(): Inv = TODO() + +fun main() { + if (true) create() else null +} diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt35943.txt b/compiler/testData/diagnostics/tests/inference/regressions/kt35943.txt new file mode 100644 index 00000000000..0cb502edcf4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt35943.txt @@ -0,0 +1,11 @@ +package + +public fun create(): Inv +public fun main(): kotlin.Unit + +public final class Inv { + public constructor Inv() + 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 814a1a7b7e1..e3658565592 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10868,6 +10868,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inference/nothingType/nestedLambdaInferenceWithIncorporationOfVariables.kt"); } + @TestMetadata("notEnoughInformationAndNothing.kt") + public void testNotEnoughInformationAndNothing() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.kt"); + } + @TestMetadata("notEnoughInformationFromNullabilityConstraint.kt") public void testNotEnoughInformationFromNullabilityConstraint() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationFromNullabilityConstraint.kt"); @@ -11192,6 +11197,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inference/regressions/kt35844.kt"); } + @TestMetadata("kt35943.kt") + public void testKt35943() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/regressions/kt35943.kt"); + } + @TestMetadata("kt4420.kt") public void testKt4420() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index c38667bd0c4..bef9df310db 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10863,6 +10863,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/nothingType/nestedLambdaInferenceWithIncorporationOfVariables.kt"); } + @TestMetadata("notEnoughInformationAndNothing.kt") + public void testNotEnoughInformationAndNothing() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationAndNothing.kt"); + } + @TestMetadata("notEnoughInformationFromNullabilityConstraint.kt") public void testNotEnoughInformationFromNullabilityConstraint() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/nothingType/notEnoughInformationFromNullabilityConstraint.kt"); @@ -11187,6 +11192,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/regressions/kt35844.kt"); } + @TestMetadata("kt35943.kt") + public void testKt35943() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/regressions/kt35943.kt"); + } + @TestMetadata("kt4420.kt") public void testKt4420() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/regressions/kt4420.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 8152c910ca2..055ce43c896 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -25926,6 +25926,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/regressions/kt3587.kt"); } + @TestMetadata("kt35914.kt") + public void testKt35914() throws Exception { + runTest("compiler/testData/codegen/box/regressions/kt35914.kt"); + } + @TestMetadata("kt3850.kt") public void testKt3850() throws Exception { runTest("compiler/testData/codegen/box/regressions/kt3850.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index d5ebb9aef6c..c42c2ea64f1 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -24743,6 +24743,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/regressions/kt3587.kt"); } + @TestMetadata("kt35914.kt") + public void testKt35914() throws Exception { + runTest("compiler/testData/codegen/box/regressions/kt35914.kt"); + } + @TestMetadata("kt3850.kt") public void testKt3850() throws Exception { runTest("compiler/testData/codegen/box/regressions/kt3850.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 1febe0893c6..d17ff45e633 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -24425,6 +24425,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/regressions/kt3587.kt"); } + @TestMetadata("kt35914.kt") + public void testKt35914() throws Exception { + runTest("compiler/testData/codegen/box/regressions/kt35914.kt"); + } + @TestMetadata("kt3850.kt") public void testKt3850() throws Exception { runTest("compiler/testData/codegen/box/regressions/kt3850.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 0b16ca184b9..892ce812f9c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -24425,6 +24425,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/regressions/kt3587.kt"); } + @TestMetadata("kt35914.kt") + public void testKt35914() throws Exception { + runTest("compiler/testData/codegen/box/regressions/kt35914.kt"); + } + @TestMetadata("kt3850.kt") public void testKt3850() throws Exception { runTest("compiler/testData/codegen/box/regressions/kt3850.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 9a128feae94..f5f345eaa6a 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -20076,6 +20076,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/regressions/kt3587.kt"); } + @TestMetadata("kt35914.kt") + public void testKt35914() throws Exception { + runTest("compiler/testData/codegen/box/regressions/kt35914.kt"); + } + @TestMetadata("kt3850.kt") public void testKt3850() throws Exception { runTest("compiler/testData/codegen/box/regressions/kt3850.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 8ac83ce191f..17ecf3239d9 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -21211,6 +21211,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/regressions/kt3587.kt"); } + @TestMetadata("kt35914.kt") + public void testKt35914() throws Exception { + runTest("compiler/testData/codegen/box/regressions/kt35914.kt"); + } + @TestMetadata("kt3850.kt") public void testKt3850() throws Exception { runTest("compiler/testData/codegen/box/regressions/kt3850.kt");