FIR: introduce parameter type is Throwable check
This commit is contained in:
committed by
Mikhail Glukhikh
parent
5c0231b727
commit
9ad88a5a0d
@@ -1,5 +1,6 @@
|
|||||||
FILE: catchParameter.kt
|
FILE: catchParameter.kt
|
||||||
public final fun <T> test(): R|kotlin/Unit| {
|
public final typealias StringType = R|kotlin/String|
|
||||||
|
public final fun <T : R|kotlin/Throwable|> test(): R|kotlin/Unit| {
|
||||||
try {
|
try {
|
||||||
}
|
}
|
||||||
catch (e: R|kotlin/NullPointerException| = R|java/lang/NullPointerException.NullPointerException|()) {
|
catch (e: R|kotlin/NullPointerException| = R|java/lang/NullPointerException.NullPointerException|()) {
|
||||||
@@ -10,6 +11,26 @@ FILE: catchParameter.kt
|
|||||||
catch (e: R|T|) {
|
catch (e: R|T|) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
}
|
||||||
|
catch (e: R|() -> kotlin/Int|) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
}
|
||||||
|
catch (e: R|StringType|) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
}
|
||||||
|
catch (e: R|kotlin/Int| = Int(5)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
}
|
||||||
|
catch (e: R|kotlin/Throwable|) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public final inline fun <reified T> anotherTest(): R|kotlin/Unit| {
|
public final inline fun <reified T> anotherTest(): R|kotlin/Unit| {
|
||||||
try {
|
try {
|
||||||
@@ -17,4 +38,4 @@ FILE: catchParameter.kt
|
|||||||
catch (e: R|T|) {
|
catch (e: R|T|) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
fun <T> test() {
|
typealias StringType = String
|
||||||
|
|
||||||
|
fun <T : Throwable> test() {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
} catch (<!CATCH_PARAMETER_WITH_DEFAULT_VALUE!>e: NullPointerException = NullPointerException()<!>) {
|
} catch (<!CATCH_PARAMETER_WITH_DEFAULT_VALUE!>e: NullPointerException = NullPointerException()<!>) {
|
||||||
@@ -6,8 +8,16 @@ fun <T> test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {} catch (<!TYPE_PARAMETER_IN_CATCH_CLAUSE!>e: T<!>) {}
|
try {} catch (<!TYPE_PARAMETER_IN_CATCH_CLAUSE!>e: T<!>) {}
|
||||||
|
|
||||||
|
try {} catch (<!TYPE_MISMATCH!>e: () -> Int<!>) {}
|
||||||
|
|
||||||
|
try {} catch (<!TYPE_MISMATCH!>e: StringType<!>) {}
|
||||||
|
|
||||||
|
try {} catch (<!CATCH_PARAMETER_WITH_DEFAULT_VALUE, TYPE_MISMATCH!>e: Int = 5<!>) {}
|
||||||
|
|
||||||
|
try {} catch (e: Throwable) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T> anotherTest() {
|
inline fun <reified T> anotherTest() {
|
||||||
try {} catch (<!REIFIED_TYPE_IN_CATCH_CLAUSE!>e: T<!>) {}
|
try {} catch (<!REIFIED_TYPE_IN_CATCH_CLAUSE, TYPE_MISMATCH!>e: T<!>) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
|||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer.isSupertypeOf
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
|
||||||
@@ -22,18 +23,18 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
|||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
|
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
||||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.typeCheckerContext
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtModifierList
|
import org.jetbrains.kotlin.psi.KtModifierList
|
||||||
|
|||||||
+24
-5
@@ -5,31 +5,50 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.FirReturnsImpliesAnalyzer.isSupertypeOf
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirTryExpression
|
import org.jetbrains.kotlin.fir.expressions.FirTryExpression
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
|
import org.jetbrains.kotlin.fir.typeCheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
|
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.constructClassLikeType
|
||||||
|
|
||||||
object FirCatchParameterChecker : FirTryExpressionChecker() {
|
object FirCatchParameterChecker : FirTryExpressionChecker() {
|
||||||
|
private val throwable = StandardClassIds.byName("Throwable")
|
||||||
|
.constructClassLikeType(emptyArray(), false)
|
||||||
|
|
||||||
override fun check(expression: FirTryExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirTryExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
for (catchEntry in expression.catches) {
|
for (catchEntry in expression.catches) {
|
||||||
val catchParameter = catchEntry.parameter
|
val catchParameter = catchEntry.parameter
|
||||||
|
|
||||||
if (catchParameter.defaultValue != null)
|
if (catchParameter.defaultValue != null)
|
||||||
reporter.report(catchParameter.source?.let { FirErrors.CATCH_PARAMETER_WITH_DEFAULT_VALUE.on(it) })
|
catchParameter.source?.let { reporter.report(FirErrors.CATCH_PARAMETER_WITH_DEFAULT_VALUE.on(it)) }
|
||||||
|
|
||||||
val typeRef = catchParameter.returnTypeRef
|
val typeRef = catchParameter.returnTypeRef
|
||||||
if (typeRef is FirResolvedTypeRef && typeRef.type is ConeTypeParameterType) {
|
if (typeRef !is FirResolvedTypeRef) return
|
||||||
val isReified = (typeRef.type as ConeTypeParameterType).lookupTag.typeParameterSymbol.fir.isReified
|
|
||||||
|
val coneType = typeRef.type
|
||||||
|
if (coneType is ConeTypeParameterType) {
|
||||||
|
val isReified = coneType.lookupTag.typeParameterSymbol.fir.isReified
|
||||||
|
|
||||||
if (isReified) {
|
if (isReified) {
|
||||||
reporter.report(catchParameter.source?.let { FirErrors.REIFIED_TYPE_IN_CATCH_CLAUSE.on(it) })
|
catchParameter.source?.let { reporter.report(FirErrors.REIFIED_TYPE_IN_CATCH_CLAUSE.on(it)) }
|
||||||
} else {
|
} else {
|
||||||
reporter.report(catchParameter.source?.let { FirErrors.TYPE_PARAMETER_IN_CATCH_CLAUSE.on(it) })
|
catchParameter.source?.let { reporter.report(FirErrors.TYPE_PARAMETER_IN_CATCH_CLAUSE.on(it)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!coneType.isThrowable(context.session))
|
||||||
|
catchParameter.source?.let { reporter.report(FirErrors.TYPE_MISMATCH.on(it, throwable, coneType)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ConeKotlinType.isThrowable(session: FirSession) =
|
||||||
|
throwable.isSupertypeOf(session.typeCheckerContext, this.fullyExpandedType(session))
|
||||||
}
|
}
|
||||||
Vendored
+2
-2
@@ -109,7 +109,7 @@ fun t7() : Int {
|
|||||||
return 1
|
return 1
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
catch (e : Any) {
|
catch (<!TYPE_MISMATCH!>e : Any<!>) {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
return 1 // this is OK, like in Java
|
return 1 // this is OK, like in Java
|
||||||
@@ -120,7 +120,7 @@ fun t8() : Int {
|
|||||||
return 1
|
return 1
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
catch (e : Any) {
|
catch (<!TYPE_MISMATCH!>e : Any<!>) {
|
||||||
return 1
|
return 1
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user