From c3b871652ff553899eeba126449f41e052531996 Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Mon, 16 Jan 2023 17:24:22 +0000 Subject: [PATCH] [FIR] KT-55181: Ensure throw argument is Throwable `TYPE_MISMATCH` in `throwJLException.fir.kt` appeared, because in `throw Exn` the type of `Exn` is implicit Unit. This is red code anyway. ^KT-55181 Fixed Merge-request: KT-MR-8292 Merged-by: Nikolay Lunyak --- ...CompilerTestFE10TestdataTestGenerated.java | 6 ++++ ...irOldFrontendDiagnosticsTestGenerated.java | 6 ++++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 ++++ .../kotlin/fir/checkers/generator/Main.kt | 1 + .../expression/ComposedExpressionCheckers.kt | 4 +++ .../checkers/expression/ExpressionCheckers.kt | 2 ++ .../expression/FirExpressionCheckerAliases.kt | 2 ++ .../checkers/CommonExpressionCheckers.kt | 5 +++ .../FirThrowExpressionTypeChecker.kt | 34 +++++++++++++++++++ .../ExpressionCheckersDiagnosticComponent.kt | 4 +++ .../tests/FunctionReturnTypes.fir.kt | 2 +- .../testData/diagnostics/tests/kt55181.kt | 5 +++ .../testData/diagnostics/tests/kt55181.txt | 3 ++ .../nullabilityWarnings/throw.fir.kt | 25 -------------- .../nullabilityWarnings/throw.kt | 1 + .../tests/typealias/throwJLException.fir.kt | 7 ++++ .../tests/typealias/throwJLException.kt | 1 - .../test/runners/DiagnosticTestGenerated.java | 6 ++++ 18 files changed, 93 insertions(+), 27 deletions(-) create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirThrowExpressionTypeChecker.kt create mode 100644 compiler/testData/diagnostics/tests/kt55181.kt create mode 100644 compiler/testData/diagnostics/tests/kt55181.txt delete mode 100644 compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.fir.kt create mode 100644 compiler/testData/diagnostics/tests/typealias/throwJLException.fir.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 96752eca667..35ea39e7be8 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -501,6 +501,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/kt54587_2.kt"); } + @Test + @TestMetadata("kt55181.kt") + public void testKt55181() throws Exception { + runTest("compiler/testData/diagnostics/tests/kt55181.kt"); + } + @Test @TestMetadata("kt55733.kt") public void testKt55733() throws Exception { 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 51a910de912..7458207fc13 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 @@ -501,6 +501,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/kt54587_2.kt"); } + @Test + @TestMetadata("kt55181.kt") + public void testKt55181() throws Exception { + runTest("compiler/testData/diagnostics/tests/kt55181.kt"); + } + @Test @TestMetadata("kt55733.kt") public void testKt55733() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index fb27ddeaff1..df337400f9d 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -501,6 +501,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/kt54587_2.kt"); } + @Test + @TestMetadata("kt55181.kt") + public void testKt55181() throws Exception { + runTest("compiler/testData/diagnostics/tests/kt55181.kt"); + } + @Test @TestMetadata("kt55733.kt") public void testKt55733() throws Exception { diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt index 4d4e236226d..85dbbfce28b 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt @@ -59,6 +59,7 @@ fun main(args: Array) { alias("CallableReferenceAccessChecker") alias("ThisReceiverExpressionChecker") alias("WhileLoopChecker") + alias("ThrowExpressionChecker") alias("DoWhileLoopChecker") alias("ArrayOfCallChecker") alias("ClassReferenceExpressionChecker") diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt index f97c7eacbc7..91f5c06d32f 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt @@ -71,6 +71,8 @@ class ComposedExpressionCheckers : ExpressionCheckers() { get() = _thisReceiverExpressionCheckers override val whileLoopCheckers: Set get() = _whileLoopCheckers + override val throwExpressionCheckers: Set + get() = _throwExpressionCheckers override val doWhileLoopCheckers: Set get() = _doWhileLoopCheckers override val arrayOfCallCheckers: Set @@ -107,6 +109,7 @@ class ComposedExpressionCheckers : ExpressionCheckers() { private val _callableReferenceAccessCheckers: MutableSet = mutableSetOf() private val _thisReceiverExpressionCheckers: MutableSet = mutableSetOf() private val _whileLoopCheckers: MutableSet = mutableSetOf() + private val _throwExpressionCheckers: MutableSet = mutableSetOf() private val _doWhileLoopCheckers: MutableSet = mutableSetOf() private val _arrayOfCallCheckers: MutableSet = mutableSetOf() private val _classReferenceExpressionCheckers: MutableSet = mutableSetOf() @@ -142,6 +145,7 @@ class ComposedExpressionCheckers : ExpressionCheckers() { _callableReferenceAccessCheckers += checkers.callableReferenceAccessCheckers _thisReceiverExpressionCheckers += checkers.thisReceiverExpressionCheckers _whileLoopCheckers += checkers.whileLoopCheckers + _throwExpressionCheckers += checkers.throwExpressionCheckers _doWhileLoopCheckers += checkers.doWhileLoopCheckers _arrayOfCallCheckers += checkers.arrayOfCallCheckers _classReferenceExpressionCheckers += checkers.classReferenceExpressionCheckers diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt index 8e85015522f..0b3c28c6605 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt @@ -46,6 +46,7 @@ abstract class ExpressionCheckers { open val callableReferenceAccessCheckers: Set = emptySet() open val thisReceiverExpressionCheckers: Set = emptySet() open val whileLoopCheckers: Set = emptySet() + open val throwExpressionCheckers: Set = emptySet() open val doWhileLoopCheckers: Set = emptySet() open val arrayOfCallCheckers: Set = emptySet() open val classReferenceExpressionCheckers: Set = emptySet() @@ -79,6 +80,7 @@ abstract class ExpressionCheckers { @CheckersComponentInternal internal val allCallableReferenceAccessCheckers: Set by lazy { callableReferenceAccessCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers } @CheckersComponentInternal internal val allThisReceiverExpressionCheckers: Set by lazy { thisReceiverExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers } @CheckersComponentInternal internal val allWhileLoopCheckers: Set by lazy { whileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers } + @CheckersComponentInternal internal val allThrowExpressionCheckers: Set by lazy { throwExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allDoWhileLoopCheckers: Set by lazy { doWhileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers } @CheckersComponentInternal internal val allArrayOfCallCheckers: Set by lazy { arrayOfCallCheckers + basicExpressionCheckers + callCheckers } @CheckersComponentInternal internal val allClassReferenceExpressionCheckers: Set by lazy { classReferenceExpressionCheckers + basicExpressionCheckers } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt index 681b2216727..131337b03e3 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.FirStringConcatenationCall import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression +import org.jetbrains.kotlin.fir.expressions.FirThrowExpression import org.jetbrains.kotlin.fir.expressions.FirTryExpression import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment @@ -72,6 +73,7 @@ typealias FirConstExpressionChecker = FirExpressionChecker typealias FirCallableReferenceAccessChecker = FirExpressionChecker typealias FirThisReceiverExpressionChecker = FirExpressionChecker typealias FirWhileLoopChecker = FirExpressionChecker +typealias FirThrowExpressionChecker = FirExpressionChecker typealias FirDoWhileLoopChecker = FirExpressionChecker typealias FirArrayOfCallChecker = FirExpressionChecker typealias FirClassReferenceExpressionChecker = FirExpressionChecker diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt index 597ef84b4ef..ecea7c99c43 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt @@ -25,6 +25,11 @@ object CommonExpressionCheckers : ExpressionCheckers() { FirRecursiveProblemChecker ) + override val throwExpressionCheckers: Set + get() = setOf( + FirThrowExpressionTypeChecker, + ) + override val qualifiedAccessCheckers: Set get() = setOf( FirOptInUsageAccessChecker, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirThrowExpressionTypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirThrowExpressionTypeChecker.kt new file mode 100644 index 00000000000..92af00ed207 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirThrowExpressionTypeChecker.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.checkers.expression + +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.expressions.FirThrowExpression +import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.fir.types.isSubtypeOf +import org.jetbrains.kotlin.fir.types.isTypeMismatchDueToNullability +import org.jetbrains.kotlin.fir.types.typeContext + +object FirThrowExpressionTypeChecker : FirThrowExpressionChecker() { + override fun check(expression: FirThrowExpression, context: CheckerContext, reporter: DiagnosticReporter) { + val expectedType = context.session.builtinTypes.throwableType.coneType + val actualType = expression.exception.typeRef.coneType + + if (!actualType.isSubtypeOf(expectedType, context.session)) { + reporter.reportOn( + expression.exception.source, + FirErrors.TYPE_MISMATCH, + expectedType, + actualType, + context.session.typeContext.isTypeMismatchDueToNullability(expectedType, actualType), + context, + ) + } + } +} \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt index 9e815a298db..c89d100e7c3 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt @@ -148,6 +148,10 @@ class ExpressionCheckersDiagnosticComponent( checkers.allCallCheckers.check(delegatedConstructorCall, data) } + override fun visitThrowExpression(throwExpression: FirThrowExpression, data: CheckerContext) { + checkers.allThrowExpressionCheckers.check(throwExpression, data) + } + private fun Collection>.check( expression: E, context: CheckerContext diff --git a/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt b/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt index 5bd00c8707f..675c1c8a286 100644 --- a/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt +++ b/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt @@ -156,7 +156,7 @@ fun illegalReturnIf(): Char { } fun returnNothing(): Nothing { - throw 1 + throw 1 } fun f(): Int { if (1 < 2) { return 1 } else returnNothing() diff --git a/compiler/testData/diagnostics/tests/kt55181.kt b/compiler/testData/diagnostics/tests/kt55181.kt new file mode 100644 index 00000000000..afed57652b3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/kt55181.kt @@ -0,0 +1,5 @@ +// FIR_IDENTICAL + +fun main() { + throw "str" +} diff --git a/compiler/testData/diagnostics/tests/kt55181.txt b/compiler/testData/diagnostics/tests/kt55181.txt new file mode 100644 index 00000000000..a9fef69810f --- /dev/null +++ b/compiler/testData/diagnostics/tests/kt55181.txt @@ -0,0 +1,3 @@ +package + +public fun main(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.fir.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.fir.kt deleted file mode 100644 index 40cffe7a8ca..00000000000 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.fir.kt +++ /dev/null @@ -1,25 +0,0 @@ -// FILE: J.java - -import org.jetbrains.annotations.*; - -public class J { - @NotNull - public static Exception staticNN; - @Nullable - public static Exception staticN; - public static Exception staticJ; -} - -// FILE: k.kt - -fun test() { - throw J.staticNN -} - -fun test1() { - throw J.staticN -} - -fun test2() { - throw J.staticJ -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.kt b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.kt index df4f6c14145..14947dee273 100644 --- a/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.kt +++ b/compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/throw.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // FILE: J.java import org.jetbrains.annotations.*; diff --git a/compiler/testData/diagnostics/tests/typealias/throwJLException.fir.kt b/compiler/testData/diagnostics/tests/typealias/throwJLException.fir.kt new file mode 100644 index 00000000000..1fa84236d7c --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/throwJLException.fir.kt @@ -0,0 +1,7 @@ +// +JDK + +typealias Exn = java.lang.Exception + +fun test() { + throw Exn +} diff --git a/compiler/testData/diagnostics/tests/typealias/throwJLException.kt b/compiler/testData/diagnostics/tests/typealias/throwJLException.kt index 4e5e71ba4f2..8448c0ad67b 100644 --- a/compiler/testData/diagnostics/tests/typealias/throwJLException.kt +++ b/compiler/testData/diagnostics/tests/typealias/throwJLException.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // +JDK typealias Exn = java.lang.Exception 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 79a3995e76a..3d65b5ad072 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 @@ -501,6 +501,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/kt54587_2.kt"); } + @Test + @TestMetadata("kt55181.kt") + public void testKt55181() throws Exception { + runTest("compiler/testData/diagnostics/tests/kt55181.kt"); + } + @Test @TestMetadata("kt55733.kt") public void testKt55733() throws Exception {