[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");
|
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
|
@Test
|
||||||
@TestMetadata("kt55733.kt")
|
@TestMetadata("kt55733.kt")
|
||||||
public void testKt55733() throws Exception {
|
public void testKt55733() throws Exception {
|
||||||
|
|||||||
+6
@@ -501,6 +501,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/kt54587_2.kt");
|
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
|
@Test
|
||||||
@TestMetadata("kt55733.kt")
|
@TestMetadata("kt55733.kt")
|
||||||
public void testKt55733() throws Exception {
|
public void testKt55733() throws Exception {
|
||||||
|
|||||||
+6
@@ -501,6 +501,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/kt54587_2.kt");
|
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
|
@Test
|
||||||
@TestMetadata("kt55733.kt")
|
@TestMetadata("kt55733.kt")
|
||||||
public void testKt55733() throws Exception {
|
public void testKt55733() throws Exception {
|
||||||
|
|||||||
+1
@@ -59,6 +59,7 @@ fun main(args: Array<String>) {
|
|||||||
alias<FirCallableReferenceAccess>("CallableReferenceAccessChecker")
|
alias<FirCallableReferenceAccess>("CallableReferenceAccessChecker")
|
||||||
alias<FirThisReceiverExpression>("ThisReceiverExpressionChecker")
|
alias<FirThisReceiverExpression>("ThisReceiverExpressionChecker")
|
||||||
alias<FirWhileLoop>("WhileLoopChecker")
|
alias<FirWhileLoop>("WhileLoopChecker")
|
||||||
|
alias<FirThrowExpression>("ThrowExpressionChecker")
|
||||||
alias<FirDoWhileLoop>("DoWhileLoopChecker")
|
alias<FirDoWhileLoop>("DoWhileLoopChecker")
|
||||||
alias<FirArrayOfCall>("ArrayOfCallChecker")
|
alias<FirArrayOfCall>("ArrayOfCallChecker")
|
||||||
alias<FirClassReferenceExpression>("ClassReferenceExpressionChecker")
|
alias<FirClassReferenceExpression>("ClassReferenceExpressionChecker")
|
||||||
|
|||||||
+4
@@ -71,6 +71,8 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
|
|||||||
get() = _thisReceiverExpressionCheckers
|
get() = _thisReceiverExpressionCheckers
|
||||||
override val whileLoopCheckers: Set<FirWhileLoopChecker>
|
override val whileLoopCheckers: Set<FirWhileLoopChecker>
|
||||||
get() = _whileLoopCheckers
|
get() = _whileLoopCheckers
|
||||||
|
override val throwExpressionCheckers: Set<FirThrowExpressionChecker>
|
||||||
|
get() = _throwExpressionCheckers
|
||||||
override val doWhileLoopCheckers: Set<FirDoWhileLoopChecker>
|
override val doWhileLoopCheckers: Set<FirDoWhileLoopChecker>
|
||||||
get() = _doWhileLoopCheckers
|
get() = _doWhileLoopCheckers
|
||||||
override val arrayOfCallCheckers: Set<FirArrayOfCallChecker>
|
override val arrayOfCallCheckers: Set<FirArrayOfCallChecker>
|
||||||
@@ -107,6 +109,7 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
|
|||||||
private val _callableReferenceAccessCheckers: MutableSet<FirCallableReferenceAccessChecker> = mutableSetOf()
|
private val _callableReferenceAccessCheckers: MutableSet<FirCallableReferenceAccessChecker> = mutableSetOf()
|
||||||
private val _thisReceiverExpressionCheckers: MutableSet<FirThisReceiverExpressionChecker> = mutableSetOf()
|
private val _thisReceiverExpressionCheckers: MutableSet<FirThisReceiverExpressionChecker> = mutableSetOf()
|
||||||
private val _whileLoopCheckers: MutableSet<FirWhileLoopChecker> = mutableSetOf()
|
private val _whileLoopCheckers: MutableSet<FirWhileLoopChecker> = mutableSetOf()
|
||||||
|
private val _throwExpressionCheckers: MutableSet<FirThrowExpressionChecker> = mutableSetOf()
|
||||||
private val _doWhileLoopCheckers: MutableSet<FirDoWhileLoopChecker> = mutableSetOf()
|
private val _doWhileLoopCheckers: MutableSet<FirDoWhileLoopChecker> = mutableSetOf()
|
||||||
private val _arrayOfCallCheckers: MutableSet<FirArrayOfCallChecker> = mutableSetOf()
|
private val _arrayOfCallCheckers: MutableSet<FirArrayOfCallChecker> = mutableSetOf()
|
||||||
private val _classReferenceExpressionCheckers: MutableSet<FirClassReferenceExpressionChecker> = mutableSetOf()
|
private val _classReferenceExpressionCheckers: MutableSet<FirClassReferenceExpressionChecker> = mutableSetOf()
|
||||||
@@ -142,6 +145,7 @@ class ComposedExpressionCheckers : ExpressionCheckers() {
|
|||||||
_callableReferenceAccessCheckers += checkers.callableReferenceAccessCheckers
|
_callableReferenceAccessCheckers += checkers.callableReferenceAccessCheckers
|
||||||
_thisReceiverExpressionCheckers += checkers.thisReceiverExpressionCheckers
|
_thisReceiverExpressionCheckers += checkers.thisReceiverExpressionCheckers
|
||||||
_whileLoopCheckers += checkers.whileLoopCheckers
|
_whileLoopCheckers += checkers.whileLoopCheckers
|
||||||
|
_throwExpressionCheckers += checkers.throwExpressionCheckers
|
||||||
_doWhileLoopCheckers += checkers.doWhileLoopCheckers
|
_doWhileLoopCheckers += checkers.doWhileLoopCheckers
|
||||||
_arrayOfCallCheckers += checkers.arrayOfCallCheckers
|
_arrayOfCallCheckers += checkers.arrayOfCallCheckers
|
||||||
_classReferenceExpressionCheckers += checkers.classReferenceExpressionCheckers
|
_classReferenceExpressionCheckers += checkers.classReferenceExpressionCheckers
|
||||||
|
|||||||
+2
@@ -46,6 +46,7 @@ abstract class ExpressionCheckers {
|
|||||||
open val callableReferenceAccessCheckers: Set<FirCallableReferenceAccessChecker> = emptySet()
|
open val callableReferenceAccessCheckers: Set<FirCallableReferenceAccessChecker> = emptySet()
|
||||||
open val thisReceiverExpressionCheckers: Set<FirThisReceiverExpressionChecker> = emptySet()
|
open val thisReceiverExpressionCheckers: Set<FirThisReceiverExpressionChecker> = emptySet()
|
||||||
open val whileLoopCheckers: Set<FirWhileLoopChecker> = emptySet()
|
open val whileLoopCheckers: Set<FirWhileLoopChecker> = emptySet()
|
||||||
|
open val throwExpressionCheckers: Set<FirThrowExpressionChecker> = emptySet()
|
||||||
open val doWhileLoopCheckers: Set<FirDoWhileLoopChecker> = emptySet()
|
open val doWhileLoopCheckers: Set<FirDoWhileLoopChecker> = emptySet()
|
||||||
open val arrayOfCallCheckers: Set<FirArrayOfCallChecker> = emptySet()
|
open val arrayOfCallCheckers: Set<FirArrayOfCallChecker> = emptySet()
|
||||||
open val classReferenceExpressionCheckers: Set<FirClassReferenceExpressionChecker> = 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 allCallableReferenceAccessCheckers: Set<FirCallableReferenceAccessChecker> by lazy { callableReferenceAccessCheckers + qualifiedAccessExpressionCheckers + basicExpressionCheckers + qualifiedAccessCheckers }
|
||||||
@CheckersComponentInternal internal val allThisReceiverExpressionCheckers: Set<FirThisReceiverExpressionChecker> by lazy { thisReceiverExpressionCheckers + 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 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 allDoWhileLoopCheckers: Set<FirDoWhileLoopChecker> by lazy { doWhileLoopCheckers + loopExpressionCheckers + basicExpressionCheckers }
|
||||||
@CheckersComponentInternal internal val allArrayOfCallCheckers: Set<FirArrayOfCallChecker> by lazy { arrayOfCallCheckers + basicExpressionCheckers + callCheckers }
|
@CheckersComponentInternal internal val allArrayOfCallCheckers: Set<FirArrayOfCallChecker> by lazy { arrayOfCallCheckers + basicExpressionCheckers + callCheckers }
|
||||||
@CheckersComponentInternal internal val allClassReferenceExpressionCheckers: Set<FirClassReferenceExpressionChecker> by lazy { classReferenceExpressionCheckers + basicExpressionCheckers }
|
@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.FirStatement
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStringConcatenationCall
|
import org.jetbrains.kotlin.fir.expressions.FirStringConcatenationCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
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.FirTryExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
|
import org.jetbrains.kotlin.fir.expressions.FirTypeOperatorCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||||
@@ -72,6 +73,7 @@ typealias FirConstExpressionChecker = FirExpressionChecker<FirConstExpression<*>
|
|||||||
typealias FirCallableReferenceAccessChecker = FirExpressionChecker<FirCallableReferenceAccess>
|
typealias FirCallableReferenceAccessChecker = FirExpressionChecker<FirCallableReferenceAccess>
|
||||||
typealias FirThisReceiverExpressionChecker = FirExpressionChecker<FirThisReceiverExpression>
|
typealias FirThisReceiverExpressionChecker = FirExpressionChecker<FirThisReceiverExpression>
|
||||||
typealias FirWhileLoopChecker = FirExpressionChecker<FirWhileLoop>
|
typealias FirWhileLoopChecker = FirExpressionChecker<FirWhileLoop>
|
||||||
|
typealias FirThrowExpressionChecker = FirExpressionChecker<FirThrowExpression>
|
||||||
typealias FirDoWhileLoopChecker = FirExpressionChecker<FirDoWhileLoop>
|
typealias FirDoWhileLoopChecker = FirExpressionChecker<FirDoWhileLoop>
|
||||||
typealias FirArrayOfCallChecker = FirExpressionChecker<FirArrayOfCall>
|
typealias FirArrayOfCallChecker = FirExpressionChecker<FirArrayOfCall>
|
||||||
typealias FirClassReferenceExpressionChecker = FirExpressionChecker<FirClassReferenceExpression>
|
typealias FirClassReferenceExpressionChecker = FirExpressionChecker<FirClassReferenceExpression>
|
||||||
|
|||||||
+5
@@ -25,6 +25,11 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
FirRecursiveProblemChecker
|
FirRecursiveProblemChecker
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override val throwExpressionCheckers: Set<FirThrowExpressionChecker>
|
||||||
|
get() = setOf(
|
||||||
|
FirThrowExpressionTypeChecker,
|
||||||
|
)
|
||||||
|
|
||||||
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
|
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirOptInUsageAccessChecker,
|
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)
|
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(
|
private fun <E : FirStatement> Collection<FirExpressionChecker<E>>.check(
|
||||||
expression: E,
|
expression: E,
|
||||||
context: CheckerContext
|
context: CheckerContext
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ fun illegalReturnIf(): Char {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun returnNothing(): Nothing {
|
fun returnNothing(): Nothing {
|
||||||
throw 1
|
throw <!TYPE_MISMATCH!>1<!>
|
||||||
}
|
}
|
||||||
fun f(): Int {
|
fun f(): Int {
|
||||||
if (1 < 2) { return 1 } else returnNothing()
|
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
|
// FILE: J.java
|
||||||
|
|
||||||
import org.jetbrains.annotations.*;
|
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
|
// +JDK
|
||||||
|
|
||||||
typealias Exn = java.lang.Exception
|
typealias Exn = java.lang.Exception
|
||||||
|
|||||||
Generated
+6
@@ -501,6 +501,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/kt54587_2.kt");
|
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
|
@Test
|
||||||
@TestMetadata("kt55733.kt")
|
@TestMetadata("kt55733.kt")
|
||||||
public void testKt55733() throws Exception {
|
public void testKt55733() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user