[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 <Nikolay.Lunyak@jetbrains.com>
This commit is contained in:
Nikolay Lunyak
2023-01-16 17:24:22 +00:00
committed by Space Team
parent 842ad56266
commit c3b871652f
18 changed files with 93 additions and 27 deletions
@@ -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 {
@@ -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 {
@@ -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 {
@@ -59,6 +59,7 @@ fun main(args: Array<String>) {
alias<FirCallableReferenceAccess>("CallableReferenceAccessChecker")
alias<FirThisReceiverExpression>("ThisReceiverExpressionChecker")
alias<FirWhileLoop>("WhileLoopChecker")
alias<FirThrowExpression>("ThrowExpressionChecker")
alias<FirDoWhileLoop>("DoWhileLoopChecker")
alias<FirArrayOfCall>("ArrayOfCallChecker")
alias<FirClassReferenceExpression>("ClassReferenceExpressionChecker")
@@ -71,6 +71,8 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
get() = _thisReceiverExpressionCheckers
override val whileLoopCheckers: Set<FirWhileLoopChecker>
get() = _whileLoopCheckers
override val throwExpressionCheckers: Set<FirThrowExpressionChecker>
get() = _throwExpressionCheckers
override val doWhileLoopCheckers: Set<FirDoWhileLoopChecker>
get() = _doWhileLoopCheckers
override val arrayOfCallCheckers: Set<FirArrayOfCallChecker>
@@ -107,6 +109,7 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
private val _callableReferenceAccessCheckers: MutableSet<FirCallableReferenceAccessChecker> = mutableSetOf()
private val _thisReceiverExpressionCheckers: MutableSet<FirThisReceiverExpressionChecker> = mutableSetOf()
private val _whileLoopCheckers: MutableSet<FirWhileLoopChecker> = mutableSetOf()
private val _throwExpressionCheckers: MutableSet<FirThrowExpressionChecker> = mutableSetOf()
private val _doWhileLoopCheckers: MutableSet<FirDoWhileLoopChecker> = mutableSetOf()
private val _arrayOfCallCheckers: MutableSet<FirArrayOfCallChecker> = mutableSetOf()
private val _classReferenceExpressionCheckers: MutableSet<FirClassReferenceExpressionChecker> = 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
@@ -46,6 +46,7 @@ abstract class ExpressionCheckers {
open val callableReferenceAccessCheckers: Set<FirCallableReferenceAccessChecker> = emptySet()
open val thisReceiverExpressionCheckers: Set<FirThisReceiverExpressionChecker> = emptySet()
open val whileLoopCheckers: Set<FirWhileLoopChecker> = emptySet()
open val throwExpressionCheckers: Set<FirThrowExpressionChecker> = emptySet()
open val doWhileLoopCheckers: Set<FirDoWhileLoopChecker> = emptySet()
open val arrayOfCallCheckers: Set<FirArrayOfCallChecker> = emptySet()
open val classReferenceExpressionCheckers: Set<FirClassReferenceExpressionChecker> = emptySet()
@@ -79,6 +80,7 @@ abstract class ExpressionCheckers {
@CheckersComponentInternal internal val allCallableReferenceAccessCheckers: Set<FirCallableReferenceAccessChecker> by lazy { callableReferenceAccessCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers }
@CheckersComponentInternal internal val allThisReceiverExpressionCheckers: Set<FirThisReceiverExpressionChecker> by lazy { thisReceiverExpressionCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers }
@CheckersComponentInternal internal val allWhileLoopCheckers: Set<FirWhileLoopChecker> by lazy { whileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allThrowExpressionCheckers: Set<FirThrowExpressionChecker> by lazy { throwExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allDoWhileLoopCheckers: Set<FirDoWhileLoopChecker> by lazy { doWhileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers }
@CheckersComponentInternal internal val allArrayOfCallCheckers: Set<FirArrayOfCallChecker> by lazy { arrayOfCallCheckers + basicExpressionCheckers + callCheckers }
@CheckersComponentInternal internal val allClassReferenceExpressionCheckers: Set<FirClassReferenceExpressionChecker> by lazy { classReferenceExpressionCheckers + basicExpressionCheckers }
@@ -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<FirConstExpression<*>
typealias FirCallableReferenceAccessChecker = FirExpressionChecker<FirCallableReferenceAccess>
typealias FirThisReceiverExpressionChecker = FirExpressionChecker<FirThisReceiverExpression>
typealias FirWhileLoopChecker = FirExpressionChecker<FirWhileLoop>
typealias FirThrowExpressionChecker = FirExpressionChecker<FirThrowExpression>
typealias FirDoWhileLoopChecker = FirExpressionChecker<FirDoWhileLoop>
typealias FirArrayOfCallChecker = FirExpressionChecker<FirArrayOfCall>
typealias FirClassReferenceExpressionChecker = FirExpressionChecker<FirClassReferenceExpression>
@@ -25,6 +25,11 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirRecursiveProblemChecker
)
override val throwExpressionCheckers: Set<FirThrowExpressionChecker>
get() = setOf(
FirThrowExpressionTypeChecker,
)
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
get() = setOf(
FirOptInUsageAccessChecker,
@@ -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,
)
}
}
}
@@ -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 <E : FirStatement> Collection<FirExpressionChecker<E>>.check(
expression: E,
context: CheckerContext
@@ -156,7 +156,7 @@ fun illegalReturnIf(): Char {
}
fun returnNothing(): Nothing {
throw 1
throw <!TYPE_MISMATCH!>1<!>
}
fun f(): Int {
if (1 < 2) { return 1 } else returnNothing()
+5
View File
@@ -0,0 +1,5 @@
// FIR_IDENTICAL
fun main() {
throw <!TYPE_MISMATCH!>"str"<!>
}
+3
View File
@@ -0,0 +1,3 @@
package
public fun main(): kotlin.Unit
@@ -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
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: J.java
import org.jetbrains.annotations.*;
@@ -0,0 +1,7 @@
// +JDK
typealias Exn = java.lang.Exception
fun test() {
throw <!NO_COMPANION_OBJECT, TYPE_MISMATCH!>Exn<!>
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// +JDK
typealias Exn = java.lang.Exception
@@ -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 {