[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:
committed by
Space Team
parent
842ad56266
commit
c3b871652f
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+1
@@ -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")
|
||||
|
||||
+4
@@ -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
|
||||
|
||||
+2
@@ -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 }
|
||||
|
||||
+2
@@ -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>
|
||||
|
||||
+5
@@ -25,6 +25,11 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
FirRecursiveProblemChecker
|
||||
)
|
||||
|
||||
override val throwExpressionCheckers: Set<FirThrowExpressionChecker>
|
||||
get() = setOf(
|
||||
FirThrowExpressionTypeChecker,
|
||||
)
|
||||
|
||||
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
|
||||
get() = setOf(
|
||||
FirOptInUsageAccessChecker,
|
||||
|
||||
+34
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
@@ -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()
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// FIR_IDENTICAL
|
||||
|
||||
fun main() {
|
||||
throw <!TYPE_MISMATCH!>"str"<!>
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun main(): kotlin.Unit
|
||||
-25
@@ -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
@@ -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
|
||||
|
||||
Generated
+6
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user